1 21 package proguard.classfile.util; 22 23 import proguard.classfile.*; 24 import proguard.classfile.attribute.*; 25 import proguard.classfile.attribute.visitor.*; 26 import proguard.classfile.attribute.annotation.*; 27 import proguard.classfile.attribute.annotation.visitor.*; 28 import proguard.classfile.constant.*; 29 import proguard.classfile.constant.visitor.ConstantVisitor; 30 import proguard.classfile.visitor.*; 31 32 33 53 public class ClassReferenceInitializer 54 extends SimplifiedVisitor 55 implements ClassVisitor, 56 MemberVisitor, 57 ConstantVisitor, 58 AttributeVisitor, 59 LocalVariableInfoVisitor, 60 LocalVariableTypeInfoVisitor, 61 AnnotationVisitor, 62 ElementValueVisitor 63 { 64 private ClassPool programClassPool; 65 private ClassPool libraryClassPool; 66 private WarningPrinter warningPrinter; 67 68 private MemberFinder memberFinder = new MemberFinder(); 69 70 71 76 public ClassReferenceInitializer(ClassPool programClassPool, 77 ClassPool libraryClassPool, 78 WarningPrinter warningPrinter) 79 { 80 this.programClassPool = programClassPool; 81 this.libraryClassPool = libraryClassPool; 82 this.warningPrinter = warningPrinter; 83 } 84 85 86 88 public void visitProgramClass(ProgramClass programClass) 89 { 90 programClass.constantPoolEntriesAccept(this); 92 93 programClass.fieldsAccept(this); 95 programClass.methodsAccept(this); 96 97 programClass.attributesAccept(this); 99 } 100 101 102 public void visitLibraryClass(LibraryClass libraryClass) 103 { 104 libraryClass.fieldsAccept(this); 106 libraryClass.methodsAccept(this); 107 } 108 109 110 112 public void visitProgramField(ProgramClass programClass, ProgramField programField) 113 { 114 programField.referencedClass = 115 findReferencedClass(programField.getDescriptor(programClass)); 116 117 programField.attributesAccept(programClass, this); 119 } 120 121 122 public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) 123 { 124 programMethod.referencedClasses = 125 findReferencedClasses(programMethod.getDescriptor(programClass)); 126 127 programMethod.attributesAccept(programClass, this); 129 } 130 131 132 public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField) 133 { 134 libraryField.referencedClass = 135 findReferencedClass(libraryField.getDescriptor(libraryClass)); 136 } 137 138 139 public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod) 140 { 141 libraryMethod.referencedClasses = 142 findReferencedClasses(libraryMethod.getDescriptor(libraryClass)); 143 } 144 145 146 148 public void visitAnyConstant(Clazz clazz, Constant constant) {} 149 150 151 public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant) 152 { 153 String className = refConstant.getClassName(clazz); 154 155 Clazz referencedClass = findClass(className); 159 160 if (referencedClass != null && 161 !ClassUtil.isInternalArrayType(className)) 162 { 163 String name = refConstant.getName(clazz); 164 String type = refConstant.getType(clazz); 165 166 boolean isFieldRef = refConstant.getTag() == ClassConstants.CONSTANT_Fieldref; 167 168 refConstant.referencedMember = memberFinder.findMember(clazz, 171 referencedClass, 172 name, 173 type, 174 isFieldRef); 175 refConstant.referencedClass = memberFinder.correspondingClass(); 176 177 if (refConstant.referencedMember == null && 178 warningPrinter != null) 179 { 180 warningPrinter.print("Warning: " + 182 ClassUtil.externalClassName(clazz.getName()) + 183 ": can't find referenced " + 184 (isFieldRef ? 185 "field '" + ClassUtil.externalFullFieldDescription(0, name, type) : 186 "method '" + ClassUtil.externalFullMethodDescription(className, 0, name, type)) + 187 "' in class " + 188 ClassUtil.externalClassName(className)); 189 } 190 } 191 } 192 193 194 public void visitClassConstant(Clazz clazz, ClassConstant classConstant) 195 { 196 classConstant.referencedClass = 197 findClass(classConstant.getName(clazz)); 198 } 199 200 201 203 public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} 204 205 206 public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute) 207 { 208 String className = enclosingMethodAttribute.getClassName(clazz); 209 210 Clazz referencedClass = findClass(className); 212 213 if (referencedClass == null) 214 { 215 if (warningPrinter != null) 217 { 218 warningPrinter.print("Warning: " + 219 ClassUtil.externalClassName(clazz.getName()) + 220 ": can't find enclosing class " + 221 ClassUtil.externalClassName(className)); 222 } 223 224 return; 225 } 226 227 if (enclosingMethodAttribute.u2nameAndTypeIndex == 0) 229 { 230 return; 231 } 232 233 String name = enclosingMethodAttribute.getName(clazz); 234 String type = enclosingMethodAttribute.getType(clazz); 235 236 Method referencedMethod = referencedClass.findMethod(name, type); 238 239 if (referencedMethod == null) 240 { 241 if (warningPrinter != null) 243 { 244 warningPrinter.print("Warning: " + 245 ClassUtil.externalClassName(clazz.getName()) + 246 ": can't find enclosing method '" + 247 ClassUtil.externalFullMethodDescription(className, 0, name, type) + 248 "' in class " + 249 ClassUtil.externalClassName(className)); 250 } 251 252 return; 253 } 254 255 enclosingMethodAttribute.referencedClass = referencedClass; 257 enclosingMethodAttribute.referencedMethod = referencedMethod; 258 } 259 260 261 public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) 262 { 263 codeAttribute.attributesAccept(clazz, method, this); 265 } 266 267 268 public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute) 269 { 270 localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); 272 } 273 274 275 public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute) 276 { 277 localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); 279 } 280 281 282 public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) 283 { 284 signatureAttribute.referencedClasses = 285 findReferencedClasses(clazz.getString(signatureAttribute.u2signatureIndex)); 286 } 287 288 289 public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute) 290 { 291 annotationsAttribute.annotationsAccept(clazz, this); 293 } 294 295 296 public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute) 297 { 298 parameterAnnotationsAttribute.annotationsAccept(clazz, method, this); 300 } 301 302 303 public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) 304 { 305 annotationDefaultAttribute.defaultValueAccept(clazz, this); 307 } 308 309 310 312 public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) 313 { 314 localVariableInfo.referencedClass = 315 findReferencedClass(clazz.getString(localVariableInfo.u2descriptorIndex)); 316 } 317 318 319 321 public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo) 322 { 323 localVariableTypeInfo.referencedClasses = 324 findReferencedClasses(clazz.getString(localVariableTypeInfo.u2signatureIndex)); 325 } 326 327 328 330 public void visitAnnotation(Clazz clazz, Annotation annotation) 331 { 332 annotation.referencedClasses = 333 findReferencedClasses(clazz.getString(annotation.u2typeIndex)); 334 335 annotation.elementValuesAccept(clazz, this); 337 } 338 339 340 342 public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue) 343 { 344 initializeElementValue(clazz, annotation, constantElementValue); 345 } 346 347 348 public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue) 349 { 350 initializeElementValue(clazz, annotation, enumConstantElementValue); 351 352 enumConstantElementValue.referencedClasses = 353 findReferencedClasses(clazz.getString(enumConstantElementValue.u2typeNameIndex)); 354 } 355 356 357 public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue) 358 { 359 initializeElementValue(clazz, annotation, classElementValue); 360 361 classElementValue.referencedClasses = 362 findReferencedClasses(clazz.getString(classElementValue.u2classInfoIndex)); 363 } 364 365 366 public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue) 367 { 368 initializeElementValue(clazz, annotation, annotationElementValue); 369 370 annotationElementValue.annotationAccept(clazz, this); 372 } 373 374 375 public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue) 376 { 377 initializeElementValue(clazz, annotation, arrayElementValue); 378 379 arrayElementValue.elementValuesAccept(clazz, annotation, this); 381 } 382 383 384 387 private void initializeElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue) 388 { 389 if (annotation != null && 391 annotation.referencedClasses != null && 392 elementValue.u2elementNameIndex != 0) 393 { 394 String name = clazz.getString(elementValue.u2elementNameIndex); 397 398 Clazz referencedClass = annotation.referencedClasses[0]; 399 elementValue.referencedClass = referencedClass; 400 elementValue.referencedMethod = referencedClass.findMethod(name, null); 401 } 402 } 403 404 405 407 411 private Clazz findReferencedClass(String descriptor) 412 { 413 DescriptorClassEnumeration enumeration = 414 new DescriptorClassEnumeration(descriptor); 415 416 if (enumeration.hasMoreClassNames()) 417 { 418 return findClass(enumeration.nextClassName()); 419 } 420 421 return null; 422 } 423 424 425 429 private Clazz[] findReferencedClasses(String descriptor) 430 { 431 DescriptorClassEnumeration enumeration = 432 new DescriptorClassEnumeration(descriptor); 433 434 int classCount = enumeration.classCount(); 435 if (classCount > 0) 436 { 437 Clazz[] referencedClasses = new Clazz[classCount]; 438 439 boolean foundReferencedClasses = false; 440 441 for (int index = 0; index < classCount; index++) 442 { 443 String name = enumeration.nextClassName(); 444 445 Clazz referencedClass = findClass(name); 446 447 if (referencedClass != null) 448 { 449 referencedClasses[index] = referencedClass; 450 foundReferencedClasses = true; 451 } 452 } 453 454 if (foundReferencedClasses) 455 { 456 return referencedClasses; 457 } 458 } 459 460 return null; 461 } 462 463 464 468 private Clazz findClass(String name) 469 { 470 Clazz clazz = programClassPool.getClass(name); 472 473 if (clazz == null) 475 { 476 clazz = libraryClassPool.getClass(name); 477 } 478 479 return clazz; 480 } 481 } 482 | Popular Tags |