1 21 package proguard.classfile.editor; 22 23 import proguard.classfile.*; 24 import proguard.classfile.attribute.*; 25 import proguard.classfile.attribute.annotation.*; 26 import proguard.classfile.attribute.annotation.visitor.*; 27 import proguard.classfile.attribute.visitor.*; 28 import proguard.classfile.constant.*; 29 import proguard.classfile.constant.visitor.ConstantVisitor; 30 import proguard.classfile.util.*; 31 import proguard.classfile.visitor.*; 32 33 41 public class ClassReferenceFixer 42 extends SimplifiedVisitor 43 implements ClassVisitor, 44 ConstantVisitor, 45 MemberVisitor, 46 AttributeVisitor, 47 InnerClassesInfoVisitor, 48 LocalVariableInfoVisitor, 49 LocalVariableTypeInfoVisitor, 50 AnnotationVisitor, 51 ElementValueVisitor 52 { 53 private boolean ensureUniqueMemberNames; 54 55 56 private ConstantPoolEditor constantPoolEditor = new ConstantPoolEditor(); 57 58 59 66 public ClassReferenceFixer(boolean ensureUniqueMemberNames) 67 { 68 this.ensureUniqueMemberNames = ensureUniqueMemberNames; 69 } 70 71 72 74 public void visitProgramClass(ProgramClass programClass) 75 { 76 programClass.constantPoolEntriesAccept(this); 78 79 programClass.fieldsAccept(this); 81 programClass.methodsAccept(this); 82 83 programClass.attributesAccept(this); 85 } 86 87 88 public void visitLibraryClass(LibraryClass libraryClass) 89 { 90 libraryClass.fieldsAccept(this); 92 libraryClass.methodsAccept(this); 93 } 94 95 96 98 public void visitProgramField(ProgramClass programClass, ProgramField programField) 99 { 100 String descriptor = programField.getDescriptor(programClass); 102 String newDescriptor = newDescriptor(descriptor, 103 programField.referencedClass); 104 105 if (!descriptor.equals(newDescriptor)) 106 { 107 programField.u2descriptorIndex = 109 constantPoolEditor.addUtf8Constant(programClass, newDescriptor); 110 111 if (ensureUniqueMemberNames) 113 { 114 String name = programField.getName(programClass); 115 String newName = newUniqueMemberName(name, descriptor); 116 programField.u2nameIndex = 117 constantPoolEditor.addUtf8Constant(programClass, newName); 118 } 119 } 120 121 programField.attributesAccept(programClass, this); 123 } 124 125 126 public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) 127 { 128 String descriptor = programMethod.getDescriptor(programClass); 130 String newDescriptor = newDescriptor(descriptor, 131 programMethod.referencedClasses); 132 133 if (!descriptor.equals(newDescriptor)) 134 { 135 programMethod.u2descriptorIndex = 137 constantPoolEditor.addUtf8Constant(programClass, newDescriptor); 138 139 if (ensureUniqueMemberNames) 141 { 142 String name = programMethod.getName(programClass); 143 String newName = newUniqueMemberName(name, descriptor); 144 programMethod.u2nameIndex = 145 constantPoolEditor.addUtf8Constant(programClass, newName); 146 } 147 } 148 149 programMethod.attributesAccept(programClass, this); 151 } 152 153 154 public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField) 155 { 156 String descriptor = libraryField.getDescriptor(libraryClass); 158 String newDescriptor = newDescriptor(descriptor, 159 libraryField.referencedClass); 160 161 libraryField.descriptor = newDescriptor; 163 } 164 165 166 public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod) 167 { 168 String descriptor = libraryMethod.getDescriptor(libraryClass); 170 String newDescriptor = newDescriptor(descriptor, 171 libraryMethod.referencedClasses); 172 173 libraryMethod.descriptor = newDescriptor; 175 } 176 177 178 180 public void visitAnyConstant(Clazz clazz, Constant constant) {} 181 182 183 public void visitStringConstant(Clazz clazz, StringConstant stringConstant) 184 { 185 Clazz referencedClass = stringConstant.referencedClass; 187 Member referencedMember = stringConstant.referencedMember; 188 if (referencedClass != null && 189 referencedMember == null) 190 { 191 String externalClassName = stringConstant.getString(clazz); 193 String internalClassName = ClassUtil.internalClassName(externalClassName); 194 String newInternalClassName = newClassName(internalClassName, 195 referencedClass); 196 197 if (!newInternalClassName.equals(internalClassName)) 199 { 200 String newExternalClassName = ClassUtil.externalClassName(newInternalClassName); 201 202 stringConstant.u2stringIndex = 204 constantPoolEditor.addUtf8Constant((ProgramClass)clazz, 205 newExternalClassName); 206 } 207 } 208 } 209 210 211 public void visitClassConstant(Clazz clazz, ClassConstant classConstant) 212 { 213 Clazz referencedClass = classConstant.referencedClass; 215 if (referencedClass != null) 216 { 217 String className = classConstant.getName(clazz); 219 String newClassName = newClassName(className, referencedClass); 220 if (!className.equals(newClassName)) 221 { 222 classConstant.u2nameIndex = 224 constantPoolEditor.addUtf8Constant((ProgramClass)clazz, 225 newClassName); 226 } 227 } 228 } 229 230 231 233 public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} 234 235 236 public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute) 237 { 238 innerClassesAttribute.innerClassEntriesAccept(clazz, this); 240 } 241 242 243 public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) 244 { 245 codeAttribute.attributesAccept(clazz, method, this); 247 } 248 249 250 public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute) 251 { 252 localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); 254 } 255 256 257 public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute) 258 { 259 localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); 261 } 262 263 264 public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) 265 { 266 String signature = clazz.getString(signatureAttribute.u2signatureIndex); 268 String newSignature = newDescriptor(signature, 269 signatureAttribute.referencedClasses); 270 271 if (!signature.equals(newSignature)) 272 { 273 signatureAttribute.u2signatureIndex = 274 constantPoolEditor.addUtf8Constant((ProgramClass)clazz, 275 newSignature); 276 } 277 } 278 279 280 public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute) 281 { 282 annotationsAttribute.annotationsAccept(clazz, this); 284 } 285 286 287 public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute) 288 { 289 parameterAnnotationsAttribute.annotationsAccept(clazz, method, this); 291 } 292 293 294 public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) 295 { 296 annotationDefaultAttribute.defaultValueAccept(clazz, this); 298 } 299 300 301 303 public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo) 304 { 305 int innerClassIndex = innerClassesInfo.u2innerClassIndex; 307 int innerNameIndex = innerClassesInfo.u2innerNameIndex; 308 if (innerClassIndex != 0 && 309 innerNameIndex != 0) 310 { 311 String newInnerName = clazz.getClassName(innerClassIndex); 312 int index = newInnerName.lastIndexOf(ClassConstants.INNER_CLASS_SEPARATOR); 313 if (index >= 0) 314 { 315 innerClassesInfo.u2innerNameIndex = 316 constantPoolEditor.addUtf8Constant((ProgramClass)clazz, 317 newInnerName.substring(index + 1)); 318 } 319 } 320 } 321 322 323 325 public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) 326 { 327 String descriptor = clazz.getString(localVariableInfo.u2descriptorIndex); 329 String newDescriptor = newDescriptor(descriptor, 330 localVariableInfo.referencedClass); 331 332 if (!descriptor.equals(newDescriptor)) 333 { 334 localVariableInfo.u2descriptorIndex = 336 constantPoolEditor.addUtf8Constant((ProgramClass)clazz, 337 newDescriptor); 338 } 339 } 340 341 342 344 public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo) 345 { 346 String signature = clazz.getString(localVariableTypeInfo.u2signatureIndex); 348 String newSignature = newDescriptor(signature, 349 localVariableTypeInfo.referencedClasses); 350 351 if (!signature.equals(newSignature)) 352 { 353 localVariableTypeInfo.u2signatureIndex = 354 constantPoolEditor.addUtf8Constant((ProgramClass)clazz, 355 newSignature); 356 } 357 } 358 359 360 362 public void visitAnnotation(Clazz clazz, Annotation annotation) 363 { 364 String typeName = clazz.getString(annotation.u2typeIndex); 366 String newTypeName = newDescriptor(typeName, 367 annotation.referencedClasses); 368 369 if (!typeName.equals(newTypeName)) 370 { 371 annotation.u2typeIndex = 373 constantPoolEditor.addUtf8Constant((ProgramClass)clazz, 374 newTypeName); 375 } 376 377 annotation.elementValuesAccept(clazz, this); 379 } 380 381 382 384 public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue) 385 { 386 } 387 388 389 public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue) 390 { 391 String typeName = clazz.getString(enumConstantElementValue.u2typeNameIndex); 393 String newTypeName = newDescriptor(typeName, 394 enumConstantElementValue.referencedClasses); 395 396 if (!typeName.equals(newTypeName)) 397 { 398 enumConstantElementValue.u2typeNameIndex = 400 constantPoolEditor.addUtf8Constant((ProgramClass)clazz, 401 newTypeName); 402 } 403 } 404 405 406 public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue) 407 { 408 String className = clazz.getString(classElementValue.u2classInfoIndex); 410 String newClassName = newDescriptor(className, 411 classElementValue.referencedClasses); 412 413 if (!className.equals(newClassName)) 414 { 415 classElementValue.u2classInfoIndex = 417 constantPoolEditor.addUtf8Constant((ProgramClass)clazz, 418 newClassName); 419 } 420 } 421 422 423 public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue) 424 { 425 annotationElementValue.annotationAccept(clazz, this); 427 } 428 429 430 public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue) 431 { 432 arrayElementValue.elementValuesAccept(clazz, annotation, this); 434 } 435 436 437 439 private static String newDescriptor(String descriptor, 440 Clazz referencedClass) 441 { 442 if (referencedClass == null) 444 { 445 return descriptor; 446 } 447 448 DescriptorClassEnumeration descriptorClassEnumeration = 450 new DescriptorClassEnumeration(descriptor); 451 452 StringBuffer newDescriptorBuffer = new StringBuffer (descriptor.length()); 453 newDescriptorBuffer.append(descriptorClassEnumeration.nextFluff()); 454 455 if (descriptorClassEnumeration.hasMoreClassNames()) 458 { 459 String className = descriptorClassEnumeration.nextClassName(); 460 String fluff = descriptorClassEnumeration.nextFluff(); 461 462 String newClassName = newClassName(className, 463 referencedClass); 464 465 newDescriptorBuffer.append(newClassName); 466 newDescriptorBuffer.append(fluff); 467 } 468 469 return newDescriptorBuffer.toString(); 470 } 471 472 473 private static String newDescriptor(String descriptor, 474 Clazz[] referencedClasses) 475 { 476 if (referencedClasses == null || 478 referencedClasses.length == 0) 479 { 480 return descriptor; 481 } 482 483 DescriptorClassEnumeration descriptorClassEnumeration = 485 new DescriptorClassEnumeration(descriptor); 486 487 StringBuffer newDescriptorBuffer = new StringBuffer (descriptor.length()); 488 newDescriptorBuffer.append(descriptorClassEnumeration.nextFluff()); 489 490 int index = 0; 491 while (descriptorClassEnumeration.hasMoreClassNames()) 492 { 493 String className = descriptorClassEnumeration.nextClassName(); 494 String fluff = descriptorClassEnumeration.nextFluff(); 495 496 String newClassName = newClassName(className, 497 referencedClasses[index++]); 498 499 newDescriptorBuffer.append(newClassName); 500 newDescriptorBuffer.append(fluff); 501 } 502 503 return newDescriptorBuffer.toString(); 504 } 505 506 507 510 private String newUniqueMemberName(String name, String descriptor) 511 { 512 return name.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) ? 514 ClassConstants.INTERNAL_METHOD_NAME_INIT : 515 name + ClassConstants.SPECIAL_MEMBER_SEPARATOR + Long.toHexString(Math.abs((descriptor).hashCode())); 516 } 517 518 519 524 private static String newClassName(String className, 525 Clazz referencedClass) 526 { 527 if (referencedClass == null) 529 { 530 return className; 531 } 532 533 String newClassName = referencedClass.getName(); 535 536 if (className.charAt(0) == ClassConstants.INTERNAL_TYPE_ARRAY) 538 { 539 newClassName = 541 className.substring(0, className.indexOf(ClassConstants.INTERNAL_TYPE_CLASS_START)+1) + 542 newClassName + 543 ClassConstants.INTERNAL_TYPE_CLASS_END; 544 } 545 546 return newClassName; 547 } 548 } 549 | Popular Tags |