1 25 28 package classycle; 29 30 import java.util.Collections ; 31 import java.util.LinkedHashSet ; 32 import java.util.Set ; 33 34 import classycle.classfile.UTF8Constant; 35 36 class ClassNameExtractor 37 { 38 39 static boolean isValid(String className) 40 { 41 boolean valid = true; 42 boolean firstCharacter = true; 43 for (int i = 0, n = className.length(); valid && i < n; i++) 44 { 45 char c = className.charAt(i); 46 if (firstCharacter) 47 { 48 firstCharacter = false; 49 valid = Character.isJavaIdentifierStart(c); 50 } else 51 { 52 if (c == '.') 53 { 54 firstCharacter = true; 55 } else 56 { 57 valid = Character.isJavaIdentifierPart(c); 58 } 59 } 60 } 61 return valid && firstCharacter == false; 62 } 63 64 private final String _constant; 65 66 private int _index; 67 private int _endIndex; 68 private Set _classNames = new LinkedHashSet (); 69 private boolean _valid = true; 70 71 ClassNameExtractor(UTF8Constant constant) 72 { 73 _constant = constant.getString(); 74 _endIndex = _constant.length(); 75 } 76 77 Set extract() 78 { 79 if (getCurrentCharacter() == '<') 80 { 81 int ddIndex = _constant.indexOf("::", _index); 82 if (ddIndex > 0) 83 { 84 _index = ddIndex + 2; 85 parseTypes(false); 86 if (getCurrentCharacter() == '>') 87 { 88 _index++; 89 } else 90 { 91 setInvalid(); 92 } 93 } else 94 { 95 setInvalid(); 96 } 97 } 98 if (getCurrentCharacter() == '(') 99 { 100 int endIndex = _constant.indexOf(')', _index); 101 if (endIndex > 0) 102 { 103 _index++; 104 _endIndex = endIndex; 105 parseTypes(false); 106 _index = endIndex + 1; 107 _endIndex = _constant.length(); 108 } else 109 { 110 setInvalid(); 111 } 112 } 113 if (_valid) 114 { 115 int numberOfTypes = parseTypes(false); 116 if (numberOfTypes == 0) 117 { 118 setInvalid(); 119 } 120 } 121 return _valid ? _classNames : Collections.EMPTY_SET; 122 } 123 124 private int parseTypes(boolean generics) 125 { 126 int numberOfTypes = 0; 127 while (_valid && endOfTypes() == false) 128 { 129 parseType(generics); 130 numberOfTypes++; 131 } 132 return numberOfTypes; 133 } 134 135 private char getCurrentCharacter() 136 { 137 return _index < _endIndex ? _constant.charAt(_index) : 0; 138 } 139 140 private void setInvalid() 141 { 142 _valid = false; 143 } 144 145 private boolean endOfTypes() 146 { 147 return _index >= _endIndex || _constant.charAt(_index) == '>'; 148 } 149 150 private void parseType(boolean generics) 151 { 152 if (generics) 153 { 154 char currentCharacter = getCurrentCharacter(); 155 if (currentCharacter == '+') 156 { 157 _index++; 158 } else if (currentCharacter == '*') 159 { 160 _index++; 161 return; 162 } 163 } 164 boolean arrayType = false; 165 for (; getCurrentCharacter() == '['; _index++) 166 { 167 arrayType = true; 168 } 169 if (arrayType && endOfTypes()) 170 { 171 setInvalid(); 172 } else 173 { 174 char c = getCurrentCharacter(); 175 _index++; 176 if (c == 'L') 177 { 178 parseComplexType(); 179 } else if (c == 'T') 180 { 181 int index = _constant.indexOf(';', _index); 182 if (index < 0) 183 { 184 setInvalid(); 185 } else 186 { 187 _index = index + 1; 188 } 189 } else if ("BCDFIJSVZ".indexOf(c) < 0) 190 { 191 setInvalid(); 192 } 193 } 194 } 195 196 private void parseComplexType() 197 { 198 int typeIndex = _constant.indexOf('<', _index); 199 int endIndex = _constant.indexOf(';', _index); 200 if (typeIndex >= 0 && typeIndex < endIndex) { 201 extractClassName(typeIndex); 202 parseTypes(true); 203 _index += 2; 204 } else if (endIndex > 0) 205 { 206 extractClassName(endIndex); 207 } else 208 { 209 setInvalid(); 210 } 211 } 212 213 private void extractClassName(int endIndex) 214 { 215 String className = _constant.substring(_index, endIndex); 216 className = className.replace('/', '.'); 217 _classNames.add(className); 218 _index = endIndex + 1; 219 if (isValid(className) == false) 220 { 221 setInvalid(); 222 } 223 } 224 225 } 226 | Popular Tags |