rev 58768 : 8238358: Implementation of JEP 371: Hidden Classes
Reviewed-by: alanb, cjplummer, coleenp, dholmes, dlong, forax, jlahoda, psandoz, plevart, vromero
Contributed-by: mandy.chung@oracle.com, lois.foltan@oracle.com, david.holmes@oracle.com, harold.seigel@oracle.com, serguei.spitsyn@oracle.com, alex.buckley@oracle.com, jamsheed.c.m@oracle.com, jan.lahoda@oracle.com, amy.lu@oracle.com
rev 58769 : [mq]: type-descriptor-name

   1 /*
   2  * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.tools.jdi;
  27 
  28 import java.util.ArrayList;
  29 import java.util.List;
  30 
  31 public class JNITypeParser {
  32 
  33     static final char SIGNATURE_ENDCLASS = ';';
  34     static final char SIGNATURE_FUNC = '(';
  35     static final char SIGNATURE_ENDFUNC = ')';
  36 
  37     private String signature;
  38     private List<String> typeNameList;
  39     private List<String> signatureList;
  40     private int currentIndex;
  41 
  42     JNITypeParser(String signature) {
  43         this.signature = signature;
  44     }
  45 
  46     static String typeNameToSignature(String typeName) {
  47         StringBuilder sb = new StringBuilder();
  48         int firstIndex = typeName.indexOf('[');
  49         int index = firstIndex;
  50         while (index != -1) {
  51             sb.append('[');
  52             index = typeName.indexOf('[', index + 1);
  53         }
  54 
  55         if (firstIndex != -1) {
  56             typeName = typeName.substring(0, firstIndex);
  57         }
  58 
  59         if (typeName.equals("boolean")) {
  60             sb.append('Z');
  61         } else if (typeName.equals("byte")) {
  62             sb.append('B');
  63         } else if (typeName.equals("char")) {
  64             sb.append('C');
  65         } else if (typeName.equals("short")) {
  66             sb.append('S');
  67         } else if (typeName.equals("int")) {
  68             sb.append('I');
  69         } else if (typeName.equals("long")) {
  70             sb.append('J');
  71         } else if (typeName.equals("float")) {
  72             sb.append('F');
  73         } else if (typeName.equals("double")) {
  74             sb.append('D');
  75         } else {
  76             sb.append('L');
  77             index = typeName.indexOf("/");   // check if it's a hidden class
  78             if (index < 0) {
  79                 sb.append(typeName.replace('.', '/'));
  80             } else {
  81                 sb.append(typeName.substring(0, index).replace('.', '/'));
  82                 sb.append(".");
  83                 sb.append(typeName.substring(index + 1));
  84             }
  85             sb.append(';');
  86         }
  87 
  88         return sb.toString();
  89     }
  90 
  91     String typeName() {
  92         return typeNameList().get(typeNameList().size()-1);
  93     }
  94 
  95     List<String> argumentTypeNames() {
  96         return typeNameList().subList(0, typeNameList().size() - 1);
  97     }
  98 
  99     String signature() {
 100         return signatureList().get(signatureList().size()-1);
 101     }
 102 
 103     List<String> argumentSignatures() {
 104         return signatureList().subList(0, signatureList().size() - 1);
 105     }
 106 
 107     int dimensionCount() {
 108         int count = 0;
 109         String signature = signature();
 110         while (signature.charAt(count) == '[') {
 111             count++;
 112         }
 113         return count;
 114     }
 115 
 116     String componentSignature(int level) {
 117         return signature().substring(level);
 118     }
 119 
 120     private synchronized List<String> signatureList() {
 121         if (signatureList == null) {
 122             signatureList = new ArrayList<>(10);
 123             String elem;
 124 
 125             currentIndex = 0;
 126 
 127             while(currentIndex < signature.length()) {
 128                 elem = nextSignature();
 129                 signatureList.add(elem);
 130             }
 131             if (signatureList.size() == 0) {
 132                 throw new IllegalArgumentException("Invalid JNI signature '" +
 133                                                    signature + "'");
 134             }
 135         }
 136         return signatureList;
 137     }
 138 
 139     private synchronized List<String> typeNameList() {
 140         if (typeNameList == null) {
 141             typeNameList = new ArrayList<>(10);
 142             String elem;
 143 
 144             currentIndex = 0;
 145 
 146             while(currentIndex < signature.length()) {
 147                 elem = nextTypeName();
 148                 typeNameList.add(elem);
 149             }
 150             if (typeNameList.size() == 0) {
 151                 throw new IllegalArgumentException("Invalid JNI signature '" +
 152                                                    signature + "'");
 153             }
 154         }
 155         return typeNameList;
 156     }
 157 
 158     private String nextSignature() {
 159         char key = signature.charAt(currentIndex++);
 160 
 161         switch(key) {
 162             case (JDWP.Tag.ARRAY):
 163                 return  key + nextSignature();
 164 
 165             case (JDWP.Tag.OBJECT):
 166                 int endClass = signature.indexOf(SIGNATURE_ENDCLASS,
 167                                                  currentIndex);
 168                 String retVal = signature.substring(currentIndex - 1,
 169                                                     endClass + 1);
 170                 currentIndex = endClass + 1;
 171                 return retVal;
 172 
 173             case (JDWP.Tag.VOID):
 174             case (JDWP.Tag.BOOLEAN):
 175             case (JDWP.Tag.BYTE):
 176             case (JDWP.Tag.CHAR):
 177             case (JDWP.Tag.SHORT):
 178             case (JDWP.Tag.INT):
 179             case (JDWP.Tag.LONG):
 180             case (JDWP.Tag.FLOAT):
 181             case (JDWP.Tag.DOUBLE):
 182                 return String.valueOf(key);
 183 
 184             case SIGNATURE_ENDFUNC:
 185             case SIGNATURE_FUNC:
 186                 return nextSignature();
 187 
 188             default:
 189                 throw new IllegalArgumentException(
 190                     "Invalid JNI signature character '" + key + "'");
 191 
 192         }
 193     }
 194 
 195     private String nextTypeName() {
 196         char key = signature.charAt(currentIndex++);
 197 
 198         switch(key) {
 199             case (JDWP.Tag.ARRAY):
 200                 return  nextTypeName() + "[]";
 201 
 202             case (JDWP.Tag.BYTE):
 203                 return "byte";
 204 
 205             case (JDWP.Tag.CHAR):
 206                 return "char";
 207 
 208             case (JDWP.Tag.OBJECT):
 209                 int endClass = signature.indexOf(SIGNATURE_ENDCLASS,
 210                                                  currentIndex);
 211                 String retVal = signature.substring(currentIndex,
 212                                                     endClass);
 213                 int index = retVal.indexOf(".");
 214                 if (index < 0) {
 215                     retVal = retVal.replace('/', '.');
 216                 } else {
 217                     // hidden class
 218                     retVal = retVal.substring(0, index).replace('/', '.')
 219                                 + "/" + retVal.substring(index + 1);
 220                 }
 221                 currentIndex = endClass + 1;
 222                 return retVal;
 223 
 224             case (JDWP.Tag.FLOAT):
 225                 return "float";
 226 
 227             case (JDWP.Tag.DOUBLE):
 228                 return "double";
 229 
 230             case (JDWP.Tag.INT):
 231                 return "int";
 232 
 233             case (JDWP.Tag.LONG):
 234                 return "long";
 235 
 236             case (JDWP.Tag.SHORT):
 237                 return "short";
 238 
 239             case (JDWP.Tag.VOID):
 240                 return "void";
 241 
 242             case (JDWP.Tag.BOOLEAN):
 243                 return "boolean";
 244 
 245             case SIGNATURE_ENDFUNC:
 246             case SIGNATURE_FUNC:
 247                 return nextTypeName();
 248 
 249             default:
 250                 throw new IllegalArgumentException(
 251                     "Invalid JNI signature character '" + key + "'");
 252         }
 253     }
 254 }
--- EOF ---