1 /* 2 * Copyright (c) 1998, 2008, 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.List; 29 import java.util.ArrayList; 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 JNITypeParser(String signature)42 JNITypeParser(String signature) { 43 this.signature = signature; 44 } 45 typeNameToSignature(String signature)46 static String typeNameToSignature(String signature) { 47 StringBuffer buffer = new StringBuffer(); 48 int firstIndex = signature.indexOf('['); 49 int index = firstIndex; 50 while (index != -1) { 51 buffer.append('['); 52 index = signature.indexOf('[', index + 1); 53 } 54 55 if (firstIndex != -1) { 56 signature = signature.substring(0, firstIndex); 57 } 58 59 if (signature.equals("boolean")) { 60 buffer.append('Z'); 61 } else if (signature.equals("byte")) { 62 buffer.append('B'); 63 } else if (signature.equals("char")) { 64 buffer.append('C'); 65 } else if (signature.equals("short")) { 66 buffer.append('S'); 67 } else if (signature.equals("int")) { 68 buffer.append('I'); 69 } else if (signature.equals("long")) { 70 buffer.append('J'); 71 } else if (signature.equals("float")) { 72 buffer.append('F'); 73 } else if (signature.equals("double")) { 74 buffer.append('D'); 75 } else { 76 buffer.append('L'); 77 buffer.append(signature.replace('.', '/')); 78 buffer.append(';'); 79 } 80 81 return buffer.toString(); 82 } 83 typeName()84 String typeName() { 85 return typeNameList().get(typeNameList().size()-1); 86 } 87 argumentTypeNames()88 List<String> argumentTypeNames() { 89 return typeNameList().subList(0, typeNameList().size() - 1); 90 } 91 signature()92 String signature() { 93 return signatureList().get(signatureList().size()-1); 94 } 95 argumentSignatures()96 List<String> argumentSignatures() { 97 return signatureList().subList(0, signatureList().size() - 1); 98 } 99 dimensionCount()100 int dimensionCount() { 101 int count = 0; 102 String signature = signature(); 103 while (signature.charAt(count) == '[') { 104 count++; 105 } 106 return count; 107 } 108 componentSignature(int level)109 String componentSignature(int level) { 110 return signature().substring(level); 111 } 112 signatureList()113 private synchronized List<String> signatureList() { 114 if (signatureList == null) { 115 signatureList = new ArrayList<String>(10); 116 String elem; 117 118 currentIndex = 0; 119 120 while(currentIndex < signature.length()) { 121 elem = nextSignature(); 122 signatureList.add(elem); 123 } 124 if (signatureList.size() == 0) { 125 throw new IllegalArgumentException("Invalid JNI signature '" + 126 signature + "'"); 127 } 128 } 129 return signatureList; 130 } 131 typeNameList()132 private synchronized List<String> typeNameList() { 133 if (typeNameList == null) { 134 typeNameList = new ArrayList<String>(10); 135 String elem; 136 137 currentIndex = 0; 138 139 while(currentIndex < signature.length()) { 140 elem = nextTypeName(); 141 typeNameList.add(elem); 142 } 143 if (typeNameList.size() == 0) { 144 throw new IllegalArgumentException("Invalid JNI signature '" + 145 signature + "'"); 146 } 147 } 148 return typeNameList; 149 } 150 nextSignature()151 private String nextSignature() { 152 char key = signature.charAt(currentIndex++); 153 154 switch(key) { 155 case (JDWP.Tag.ARRAY): 156 return key + nextSignature(); 157 158 case (JDWP.Tag.OBJECT): 159 int endClass = signature.indexOf(SIGNATURE_ENDCLASS, 160 currentIndex); 161 String retVal = signature.substring(currentIndex - 1, 162 endClass + 1); 163 currentIndex = endClass + 1; 164 return retVal; 165 166 case (JDWP.Tag.VOID): 167 case (JDWP.Tag.BOOLEAN): 168 case (JDWP.Tag.BYTE): 169 case (JDWP.Tag.CHAR): 170 case (JDWP.Tag.SHORT): 171 case (JDWP.Tag.INT): 172 case (JDWP.Tag.LONG): 173 case (JDWP.Tag.FLOAT): 174 case (JDWP.Tag.DOUBLE): 175 return String.valueOf(key); 176 177 case SIGNATURE_ENDFUNC: 178 case SIGNATURE_FUNC: 179 return nextSignature(); 180 181 default: 182 throw new IllegalArgumentException( 183 "Invalid JNI signature character '" + key + "'"); 184 185 } 186 } 187 nextTypeName()188 private String nextTypeName() { 189 char key = signature.charAt(currentIndex++); 190 191 switch(key) { 192 case (JDWP.Tag.ARRAY): 193 return nextTypeName() + "[]"; 194 195 case (JDWP.Tag.BYTE): 196 return "byte"; 197 198 case (JDWP.Tag.CHAR): 199 return "char"; 200 201 case (JDWP.Tag.OBJECT): 202 int endClass = signature.indexOf(SIGNATURE_ENDCLASS, 203 currentIndex); 204 String retVal = signature.substring(currentIndex, 205 endClass); 206 retVal = retVal.replace('/','.'); 207 currentIndex = endClass + 1; 208 return retVal; 209 210 case (JDWP.Tag.FLOAT): 211 return "float"; 212 213 case (JDWP.Tag.DOUBLE): 214 return "double"; 215 216 case (JDWP.Tag.INT): 217 return "int"; 218 219 case (JDWP.Tag.LONG): 220 return "long"; 221 222 case (JDWP.Tag.SHORT): 223 return "short"; 224 225 case (JDWP.Tag.VOID): 226 return "void"; 227 228 case (JDWP.Tag.BOOLEAN): 229 return "boolean"; 230 231 case SIGNATURE_ENDFUNC: 232 case SIGNATURE_FUNC: 233 return nextTypeName(); 234 235 default: 236 throw new IllegalArgumentException( 237 "Invalid JNI signature character '" + key + "'"); 238 239 } 240 } 241 } 242