1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package signature.converter.dex; 18 19 import static signature.converter.dex.DexUtil.convertAnyWay; 20 import static signature.converter.dex.DexUtil.declaresExceptions; 21 import static signature.converter.dex.DexUtil.declaresMemberClasses; 22 import static signature.converter.dex.DexUtil.findPackageInfo; 23 import static signature.converter.dex.DexUtil.getClassModifiers; 24 import static signature.converter.dex.DexUtil.getClassName; 25 import static signature.converter.dex.DexUtil.getDefaultMappingsAnnotation; 26 import static signature.converter.dex.DexUtil.getDexName; 27 import static signature.converter.dex.DexUtil.getEnclosingClassName; 28 import static signature.converter.dex.DexUtil.getExceptionSignature; 29 import static signature.converter.dex.DexUtil.getGenericSignature; 30 import static signature.converter.dex.DexUtil.getKind; 31 import static signature.converter.dex.DexUtil.getMemberClassNames; 32 import static signature.converter.dex.DexUtil.getModifier; 33 import static signature.converter.dex.DexUtil.getPackageName; 34 import static signature.converter.dex.DexUtil.getQualifiedName; 35 import static signature.converter.dex.DexUtil.hasAnnotationDefaultSignature; 36 import static signature.converter.dex.DexUtil.hasGenericSignature; 37 import static signature.converter.dex.DexUtil.isAnnotation; 38 import static signature.converter.dex.DexUtil.isConstructor; 39 import static signature.converter.dex.DexUtil.isEnclosingClass; 40 import static signature.converter.dex.DexUtil.isEnum; 41 import static signature.converter.dex.DexUtil.isInternalAnnotation; 42 import static signature.converter.dex.DexUtil.isJavaLangObject; 43 import static signature.converter.dex.DexUtil.isMethod; 44 import static signature.converter.dex.DexUtil.isVisible; 45 import static signature.converter.dex.DexUtil.splitTypeList; 46 47 import java.util.ArrayList; 48 import java.util.Collections; 49 import java.util.HashMap; 50 import java.util.HashSet; 51 import java.util.Iterator; 52 import java.util.List; 53 import java.util.Map; 54 import java.util.Set; 55 56 import signature.converter.Visibility; 57 import signature.model.IAnnotation; 58 import signature.model.IAnnotationElement; 59 import signature.model.IAnnotationField; 60 import signature.model.IClassDefinition; 61 import signature.model.IClassReference; 62 import signature.model.IConstructor; 63 import signature.model.IEnumConstant; 64 import signature.model.IField; 65 import signature.model.IMethod; 66 import signature.model.IPackage; 67 import signature.model.IParameter; 68 import signature.model.ITypeReference; 69 import signature.model.ITypeVariableDefinition; 70 import signature.model.Kind; 71 import signature.model.Modifier; 72 import signature.model.impl.SigAnnotation; 73 import signature.model.impl.SigAnnotationElement; 74 import signature.model.impl.SigAnnotationField; 75 import signature.model.impl.SigApi; 76 import signature.model.impl.SigClassDefinition; 77 import signature.model.impl.SigClassReference; 78 import signature.model.impl.SigConstructor; 79 import signature.model.impl.SigEnumConstant; 80 import signature.model.impl.SigExecutableMember; 81 import signature.model.impl.SigField; 82 import signature.model.impl.SigMethod; 83 import signature.model.impl.SigPackage; 84 import signature.model.impl.SigParameter; 85 import signature.model.impl.Uninitialized; 86 import signature.model.util.TypePool; 87 import dex.structure.DexAnnotation; 88 import dex.structure.DexAnnotationAttribute; 89 import dex.structure.DexClass; 90 import dex.structure.DexEncodedAnnotation; 91 import dex.structure.DexEncodedValue; 92 import dex.structure.DexField; 93 import dex.structure.DexFile; 94 import dex.structure.DexMethod; 95 import dex.structure.DexParameter; 96 97 /** 98 * Converts a set of dex files to the signature compare api. 99 */ 100 public final class DexToSigConverter implements IClassInitializer { 101 102 private final FieldPool elementPool; 103 private final TypePool factory; 104 private static final Set<IField> EMPTY_FIELDS = Collections.emptySet(); 105 private static final Set<IEnumConstant> EMPTY_ENUM_CONSTANTS = Collections 106 .emptySet(); 107 private static final Set<IAnnotationField> EMPTY_ANNOTATION_FIELDS = 108 Collections.emptySet(); 109 private static final List<ITypeVariableDefinition> EMPTY_TYPE_VARIABLES = 110 Collections.emptyList(); 111 private static final Set<IClassDefinition> EMPTY_INNER_CLASSES = 112 Collections.emptySet(); 113 private static final Set<ITypeReference> EMPTY_EXCEPTIONS = Collections 114 .emptySet(); 115 private Visibility visibility; 116 private Map<String, DexClass> dexNameToDexClass; 117 118 119 /** 120 * Creates a new instance of {@link DexToSigConverter}. 121 */ 122 public DexToSigConverter() { 123 factory = new TypePool(); 124 elementPool = new FieldPool(); 125 } 126 127 128 public SigApi convertApi(String apiName, Set<DexFile> dexFiles, 129 Visibility visibility) { 130 this.visibility = visibility; 131 SigApi api = new SigApi(apiName, visibility); 132 api.setPackages(convertPackages(dexFiles)); 133 factory.replaceAllUninitialiezWithNull(); 134 return api; 135 } 136 137 /** 138 * Converts the given {@link DexFile}s into the corresponding (packages 139 * including their (classes and their members, etc.))E 140 * 141 * @param parsedFiles 142 * the dex files to convert 143 * @return the converted packages 144 */ 145 /* package */Set<IPackage> convertPackages(Set<DexFile> parsedFiles) { 146 Map<String, SigPackage> packageNameToPackage = 147 new HashMap<String, SigPackage>(); 148 Map<SigPackage, Set<DexClass>> packageToDexClasses = 149 new HashMap<SigPackage, Set<DexClass>>(); 150 151 dexNameToDexClass = new HashMap<String, DexClass>(); 152 153 for (DexFile dexFile : parsedFiles) { 154 List<DexClass> definedClasses = dexFile.getDefinedClasses(); 155 for (DexClass dexClass : definedClasses) { 156 157 dexNameToDexClass.put(dexClass.getName(), dexClass); 158 159 String dexName = dexClass.getName(); 160 String packageName = getPackageName(dexName); 161 SigPackage aPackage = packageNameToPackage.get(packageName); 162 if (aPackage == null) { 163 aPackage = convertPackage(packageName); 164 packageNameToPackage.put(packageName, aPackage); 165 166 Set<DexClass> classes = new HashSet<DexClass>(); 167 packageToDexClasses.put(aPackage, classes); 168 } 169 Set<DexClass> classes = packageToDexClasses.get(aPackage); 170 classes.add(dexClass); 171 } 172 } 173 174 Set<SigClassDefinition> allClasses = new HashSet<SigClassDefinition>(); 175 176 for (SigPackage aPackage : packageToDexClasses.keySet()) { 177 Set<SigClassDefinition> classes = convertClasses(packageToDexClasses 178 .get(aPackage)); 179 allClasses.addAll(classes); 180 aPackage.setClasses(new HashSet<IClassDefinition>(classes)); 181 } 182 183 // remove package info 184 for (SigPackage aPackage : packageToDexClasses.keySet()) { 185 IClassDefinition packageInfo = findPackageInfo(aPackage); 186 if (packageInfo != null) { 187 aPackage.setAnnotations(packageInfo.getAnnotations()); 188 aPackage.getClasses().remove(packageInfo); 189 } 190 } 191 192 // link enclosed classes only if they are part of visible api 193 for (SigClassDefinition sigClass : allClasses) { 194 String dexName = getDexName(sigClass); 195 DexClass dexClass = dexNameToDexClass.get(dexName); 196 197 if (declaresMemberClasses(dexClass)) { 198 Set<String> enclosedClassesNames = 199 getMemberClassNames(dexClass); 200 Set<IClassDefinition> memberClasses = 201 new HashSet<IClassDefinition>(); 202 for (String enclosedClassName : enclosedClassesNames) { 203 SigClassDefinition memberClass = factory.getClass( 204 getPackageName(enclosedClassName), 205 getClassName(enclosedClassName)); 206 // add inner class only if parsed 207 if (allClasses.contains(memberClass)) { 208 memberClasses.add(memberClass); 209 } 210 } 211 sigClass.setInnerClasses(memberClasses); 212 } else { 213 sigClass.setInnerClasses(EMPTY_INNER_CLASSES); 214 } 215 } 216 217 // remove inner classes, is outer class is not visible 218 for (SigClassDefinition sigClass : allClasses) { 219 if (hasInvisibleParent(sigClass, dexNameToDexClass)) { 220 SigPackage sigPackage = packageNameToPackage.get(sigClass 221 .getPackageName()); 222 sigPackage.getClasses().remove(sigClass); 223 } 224 } 225 return new HashSet<IPackage>(packageToDexClasses.keySet()); 226 } 227 228 private boolean hasInvisibleParent(IClassDefinition sigClass, 229 Map<String, DexClass> dexNameToDexClass) { 230 231 do { 232 String dexName = getDexName(sigClass); 233 DexClass dexClass = dexNameToDexClass.get(dexName); 234 if (isEnclosingClass(dexClass)) { 235 IClassDefinition declaringClass = sigClass.getDeclaringClass(); 236 DexClass declaringDexClass = dexNameToDexClass 237 .get(getDexName(declaringClass)); 238 if (!isVisible(declaringDexClass, visibility)) { 239 return true; 240 } 241 } 242 } while ((sigClass = sigClass.getDeclaringClass()) != null); 243 return false; 244 } 245 246 /** 247 * Converts a simple string to the corresponding {@link SigPackage}.<br> 248 * Format: "a.b.c" 249 * 250 * @param packageName 251 * the name of the package 252 * @return the package 253 */ 254 protected SigPackage convertPackage(String packageName) { 255 SigPackage sigPackage = new SigPackage(packageName); 256 return sigPackage; 257 } 258 259 /** 260 * Converts a set of {@link DexClass} objects to a set of the corresponding 261 * {@link SigClassDefinition} objects. 262 * 263 * @param dexClasses 264 * the {@link DexClass} objects 265 * @return a set of {@link DexClass} objects 266 */ 267 protected Set<SigClassDefinition> convertClasses(Set<DexClass> dexClasses) { 268 Set<SigClassDefinition> classes = new HashSet<SigClassDefinition>(); 269 for (DexClass dexClass : dexClasses) { 270 // convert all classes but synthetic, return only initialized 271 if (convertAnyWay(dexClass)) { 272 SigClassDefinition sigCLass = convertClass(dexClass); 273 if (isVisible(dexClass, visibility)) { 274 classes.add(sigCLass); 275 } 276 } 277 } 278 return classes; 279 } 280 281 /** 282 * Converts a {@link DexClass} to the corresponding 283 * {@link SigClassDefinition}. 284 * 285 * @param dexClass 286 * the {@link DexClass} to convert 287 * @return the corresponding {@link SigClassDefinition} 288 */ 289 protected SigClassDefinition convertClass(DexClass dexClass) { 290 assert dexClass != null; 291 292 String packageName = getPackageName(dexClass.getName()); 293 String className = getClassName(dexClass.getName()); 294 SigClassDefinition sigClass = factory.getClass(packageName, className); 295 // Kind 296 sigClass.setKind(getKind(dexClass)); 297 // modifiers 298 Set<Modifier> modifiers = getModifier(getClassModifiers(dexClass)); 299 sigClass.setModifiers(modifiers); 300 301 if (isEnclosingClass(dexClass)) { 302 String declaringClassDexName = getEnclosingClassName(dexClass); 303 declaringClassDexName = getClassName(declaringClassDexName); 304 // declaring class is in same package 305 sigClass.setDeclaringClass(factory.getClass(sigClass 306 .getPackageName(), declaringClassDexName)); 307 } else { 308 sigClass.setDeclaringClass(null); 309 } 310 311 if (hasGenericSignature(dexClass)) { 312 GenericSignatureParser parser = new GenericSignatureParser(factory, 313 this); 314 parser.parseForClass(sigClass, getGenericSignature(dexClass)); 315 sigClass.setTypeParameters(parser.formalTypeParameters); 316 317 if (Kind.INTERFACE.equals(sigClass.getKind())) { 318 sigClass.setSuperClass(null); 319 } else { 320 sigClass.setSuperClass(parser.superclassType); 321 } 322 323 sigClass.setInterfaces(new HashSet<ITypeReference>( 324 parser.interfaceTypes)); 325 } else { 326 327 // Type parameters 328 sigClass.setTypeParameters(EMPTY_TYPE_VARIABLES); 329 330 // java.lang.Object has no super class 331 if (isJavaLangObject(dexClass)) { 332 sigClass.setSuperClass(null); 333 } else { 334 335 if (Kind.INTERFACE.equals(sigClass.getKind()) 336 || Kind.ANNOTATION.equals(sigClass.getKind())) { 337 sigClass.setSuperClass(null); 338 } else { 339 String superClassPackageName = getPackageName(dexClass 340 .getSuperClass()); 341 String superClassName = getClassName(dexClass 342 .getSuperClass()); 343 sigClass.setSuperClass(factory.getClassReference( 344 superClassPackageName, superClassName)); 345 } 346 } 347 348 List<String> interfaceDexNames = dexClass.getInterfaces(); 349 Set<ITypeReference> interfaces = new HashSet<ITypeReference>(); 350 for (String interfaceDexName : interfaceDexNames) { 351 String interfacePackageName = getPackageName(interfaceDexName); 352 String interfaceName = getClassName(interfaceDexName); 353 SigClassDefinition interfaze = factory.getClass( 354 interfacePackageName, interfaceName); 355 interfaze.setKind(Kind.INTERFACE); 356 interfaces.add(new SigClassReference(interfaze)); 357 } 358 sigClass.setInterfaces(interfaces); 359 } 360 361 // constructors 362 Set<SigConstructor> constructors = convertConstructors(dexClass 363 .getMethods()); 364 for (SigConstructor constructor : constructors) { 365 constructor.setDeclaringClass(sigClass); 366 } 367 sigClass.setConstructors(new HashSet<IConstructor>(constructors)); 368 369 // methods 370 Set<SigMethod> methods = Collections.emptySet(); 371 372 373 if (isAnnotation(dexClass)) { 374 Map<String, Object> mappings = getDefaultValueMapping(dexClass); 375 Set<SigAnnotationField> annotationFields = convertAnnotationFields( 376 dexClass.getMethods(), mappings); 377 sigClass.setAnnotationFields(new HashSet<IAnnotationField>( 378 annotationFields)); 379 addAnnotationsToAnnotationFields(dexClass.getMethods(), 380 annotationFields); 381 382 sigClass.setEnumConstants(EMPTY_ENUM_CONSTANTS); 383 sigClass.setFields(EMPTY_FIELDS); 384 385 // sigClass.setAnnotationFields(new 386 // HashSet<IAnnotationField>(convertAnnotationFields(dexClass))); 387 } else if (isEnum(dexClass)) { 388 Set<IField> fields = new HashSet<IField>(); 389 Set<IEnumConstant> enumConstants = new HashSet<IEnumConstant>(); 390 391 for (DexField dexField : dexClass.getFields()) { 392 if (isVisible(dexField, visibility)) { 393 if (dexField.isEnumConstant()) { 394 enumConstants.add(convertEnumConstant(dexField)); 395 } else { 396 fields.add(convertField(dexField)); 397 } 398 } 399 } 400 401 sigClass.setFields(fields); 402 sigClass.setEnumConstants(enumConstants); 403 sigClass.setAnnotationFields(EMPTY_ANNOTATION_FIELDS); 404 methods = convertMethods(dexClass.getMethods()); 405 } else { 406 // fields 407 sigClass.setFields(new HashSet<IField>(convertFields(dexClass 408 .getFields()))); 409 sigClass.setEnumConstants(EMPTY_ENUM_CONSTANTS); 410 sigClass.setAnnotationFields(EMPTY_ANNOTATION_FIELDS); 411 methods = convertMethods(dexClass.getMethods()); 412 } 413 414 for (SigMethod method : methods) { 415 method.setDeclaringClass(sigClass); 416 } 417 sigClass.setMethods(new HashSet<IMethod>(methods)); 418 419 // Annotations 420 sigClass.setAnnotations(convertAnnotations(dexClass.getAnnotations())); 421 422 return sigClass; 423 } 424 425 @SuppressWarnings("unchecked") 426 private Map<String, Object> getDefaultValueMapping(DexClass dexClass) { 427 HashMap<String, Object> mappings = new HashMap<String, Object>(); 428 if (hasAnnotationDefaultSignature(dexClass)) { 429 // read mapping to defaults from annotation 430 DexAnnotation annotation = getDefaultMappingsAnnotation(dexClass); 431 DexAnnotationAttribute dexAnnotationAttribute = annotation 432 .getAttributes().get(0); 433 if ("value".equals(dexAnnotationAttribute.getName())) { 434 DexEncodedValue encodedValue = dexAnnotationAttribute 435 .getEncodedValue(); 436 DexEncodedValue value = (DexEncodedValue) encodedValue 437 .getValue(); 438 List<DexAnnotationAttribute> defaults = 439 (List<DexAnnotationAttribute>) value.getValue(); 440 for (DexAnnotationAttribute defaultAttribute : defaults) { 441 mappings.put(defaultAttribute.getName(), 442 convertEncodedValue(defaultAttribute 443 .getEncodedValue())); 444 } 445 } 446 } 447 return mappings; 448 } 449 450 451 private void addAnnotationsToAnnotationFields(List<DexMethod> methods, 452 Set<SigAnnotationField> annotationFields) { 453 Map<String, SigAnnotationField> nameToAnnotationField = 454 new HashMap<String, SigAnnotationField>(); 455 456 for (SigAnnotationField annotationField : annotationFields) { 457 nameToAnnotationField.put(annotationField.getName(), 458 annotationField); 459 } 460 461 for (DexMethod method : methods) { 462 SigAnnotationField annotationField = nameToAnnotationField 463 .get(method.getName()); 464 annotationField.setAnnotations(convertAnnotations(method 465 .getAnnotations())); 466 } 467 } 468 469 470 private Set<SigAnnotationField> convertAnnotationFields( 471 List<DexMethod> list, Map<String, Object> mappings) { 472 Set<SigAnnotationField> annotationfields = 473 new HashSet<SigAnnotationField>(); 474 for (DexMethod dexMethod : list) { 475 if (isVisible(dexMethod, visibility)) { 476 annotationfields.add(convertAnnotationField(dexMethod, mappings 477 .get(dexMethod.getName()))); 478 } 479 } 480 return annotationfields; 481 } 482 483 private SigAnnotationField convertAnnotationField(DexMethod dexMethod, 484 Object defaultValue) { 485 SigAnnotationField annotationField = new SigAnnotationField(dexMethod 486 .getName()); 487 annotationField.setDefaultValue(defaultValue); 488 annotationField.setModifiers(getModifier(dexMethod.getModifiers())); 489 GenericSignatureParser parser = new GenericSignatureParser(factory, 490 this); 491 annotationField.setType(parser.parseNonGenericType(dexMethod 492 .getReturnType())); 493 return annotationField; 494 } 495 496 private IEnumConstant convertEnumConstant(DexField dexField) { 497 String qualifiedTypeName = getQualifiedName(dexField 498 .getDeclaringClass().getName()); 499 SigEnumConstant enumConstant = elementPool.getEnumConstant( 500 qualifiedTypeName, dexField.getName()); 501 Set<Modifier> modifiers = getModifier(dexField.getModifiers()); 502 modifiers.add(Modifier.STATIC); 503 enumConstant.setModifiers(modifiers); 504 505 String typePackageName = getPackageName(dexField.getType()); 506 String typeName = getClassName(dexField.getType()); 507 enumConstant.setType(factory.getClassReference(typePackageName, 508 typeName)); 509 enumConstant.setAnnotations(convertAnnotations(dexField 510 .getAnnotations())); 511 return enumConstant; 512 } 513 514 private Set<SigField> convertFields(List<DexField> dexFields) { 515 Set<SigField> fields = new HashSet<SigField>(); 516 for (DexField dexField : dexFields) { 517 if (isVisible(dexField, visibility)) { 518 fields.add(convertField(dexField)); 519 } 520 } 521 return fields; 522 } 523 524 private SigField convertField(DexField dexField) { 525 String qualTypeName = getQualifiedName(dexField.getDeclaringClass() 526 .getName()); 527 SigField field = elementPool.getField(qualTypeName, dexField.getName()); 528 529 field.setModifiers(getModifier(dexField.getModifiers())); 530 531 field.setAnnotations(convertAnnotations(dexField.getAnnotations())); 532 533 if (hasGenericSignature(dexField)) { 534 GenericSignatureParser parser = new GenericSignatureParser(factory, 535 this); 536 String declaringClassPackageName = getPackageName(dexField 537 .getDeclaringClass().getName()); 538 String declaringClassName = getClassName(dexField 539 .getDeclaringClass().getName()); 540 541 parser.parseForField(factory.getClass(declaringClassPackageName, 542 declaringClassName), getGenericSignature(dexField)); 543 field.setType(parser.fieldType); 544 } else { 545 GenericSignatureParser parser = new GenericSignatureParser(factory, 546 this); 547 field.setType(parser.parseNonGenericType(dexField.getType())); 548 } 549 550 return field; 551 } 552 553 /** 554 * Converts a set of {@link DexMethod} to a set of corresponding 555 * {@link IConstructor}. This method ignores methods which are not 556 * constructors. 557 * 558 * @param methods 559 * the {@link DexMethod}s to convert 560 * @return the corresponding {@link IConstructor}s 561 */ 562 private Set<SigConstructor> convertConstructors(List<DexMethod> methods) { 563 Set<SigConstructor> constructors = new HashSet<SigConstructor>(); 564 for (DexMethod method : methods) { 565 if (isConstructor(method) && isVisible(method, visibility)) { 566 constructors.add(convertConstructor(method)); 567 } 568 } 569 return constructors; 570 } 571 572 /** 573 * Converts a set of {@link DexMethod} to a set of corresponding 574 * {@link DexMethod}. This method ignores methods which are constructors. 575 * 576 * @param methods 577 * the {@link DexMethod}s to convert 578 * @return the corresponding {@link IConstructor}s 579 */ 580 private Set<SigMethod> convertMethods(List<DexMethod> methods) { 581 Set<SigMethod> sigMethods = new HashSet<SigMethod>(); 582 for (DexMethod method : methods) { 583 if (isMethod(method) && isVisible(method, visibility)) { 584 sigMethods.add(convertMethod(method)); 585 } 586 } 587 return sigMethods; 588 } 589 590 /** 591 * Converts a dexMethod which must be a constructor to the corresponding 592 * {@link SigConstructor} instance. 593 * 594 * @param dexMethod 595 * the dex constructor to convert 596 * @return the corresponding {@link SigConstructor} 597 */ 598 public SigConstructor convertConstructor(DexMethod dexMethod) { 599 String declaringClassName = getClassName(dexMethod.getDeclaringClass() 600 .getName()); 601 602 SigConstructor constructor = new SigConstructor(declaringClassName); 603 constructor.setModifiers(getModifier(dexMethod.getModifiers())); 604 String declaringClassPackageName = getPackageName(dexMethod 605 .getDeclaringClass().getName()); 606 607 608 SigClassDefinition declaringClass = factory.getClass( 609 declaringClassPackageName, declaringClassName); 610 constructor.setDeclaringClass(declaringClass); 611 612 // Annotations 613 constructor.setAnnotations(convertAnnotations(dexMethod 614 .getAnnotations())); 615 616 if (hasGenericSignature(dexMethod)) { 617 GenericSignatureParser parser = new GenericSignatureParser(factory, 618 this); 619 parser.parseForConstructor(constructor, 620 getGenericSignature(dexMethod)); 621 622 // type parameters 623 constructor.setTypeParameters(parser.formalTypeParameters); 624 625 // parameters 626 // generic parameter types parameters 627 List<DexParameter> dexParameters = dexMethod.getParameters(); 628 List<IParameter> parameters = new ArrayList<IParameter>( 629 parser.parameterTypes.size()); 630 Iterator<DexParameter> iterator = dexParameters.iterator(); 631 for (ITypeReference parameterType : parser.parameterTypes) { 632 SigParameter parameter = new SigParameter(parameterType); 633 iterator.hasNext(); 634 DexParameter dexParam = iterator.next(); 635 parameter.setAnnotations(convertAnnotations(dexParam 636 .getAnnotations())); 637 parameters.add(parameter); 638 } 639 640 constructor.setParameters(parameters); 641 642 // exceptions 643 constructor.setExceptions(new HashSet<ITypeReference>( 644 parser.exceptionTypes)); 645 646 } else { 647 convertNonGenericExecutableMember(constructor, dexMethod); 648 649 // remove first parameter of non static inner class constructors 650 // implicit outer.this reference 651 if (declaringClass.getDeclaringClass() != null) { 652 if (!declaringClass.getModifiers().contains(Modifier.STATIC)) { 653 if (constructor.getParameters().isEmpty()) { 654 throw new IllegalStateException( 655 "Expected at least one parameter!"); 656 } 657 IParameter first = constructor.getParameters().remove(0); 658 String enclosingName = declaringClass.getDeclaringClass() 659 .getName(); 660 String firstParameterTypeName = ((IClassReference) first 661 .getType()).getClassDefinition().getName(); 662 if (!enclosingName.equals(firstParameterTypeName)) 663 throw new IllegalStateException( 664 "Expected first constructor parameter of type " 665 + enclosingName); 666 } 667 } 668 } 669 670 addExceptions(constructor, dexMethod); 671 return constructor; 672 } 673 674 public SigMethod convertMethod(DexMethod dexMethod) { 675 SigMethod method = new SigMethod(dexMethod.getName()); 676 method.setModifiers(getModifier(dexMethod.getModifiers())); 677 678 String declaringClassPackageName = getPackageName(dexMethod 679 .getDeclaringClass().getName()); 680 String declaringClassName = getClassName(dexMethod.getDeclaringClass() 681 .getName()); 682 683 method.setDeclaringClass(factory.getClass(declaringClassPackageName, 684 declaringClassName)); 685 686 // Annotations 687 method.setAnnotations(convertAnnotations(dexMethod.getAnnotations())); 688 689 if (hasGenericSignature(dexMethod)) { 690 GenericSignatureParser parser = new GenericSignatureParser(factory, 691 this); 692 parser.parseForMethod(method, getGenericSignature(dexMethod)); 693 694 // type parameters 695 method.setTypeParameters(parser.formalTypeParameters); 696 697 // generic parameter types parameters 698 List<DexParameter> dexParameters = dexMethod.getParameters(); 699 List<IParameter> parameters = new ArrayList<IParameter>( 700 parser.parameterTypes.size()); 701 Iterator<DexParameter> iterator = dexParameters.iterator(); 702 for (ITypeReference parameterType : parser.parameterTypes) { 703 SigParameter parameter = new SigParameter(parameterType); 704 iterator.hasNext(); 705 DexParameter dexParam = iterator.next(); 706 parameter.setAnnotations(convertAnnotations(dexParam 707 .getAnnotations())); 708 parameters.add(parameter); 709 } 710 method.setParameters(parameters); 711 712 // exceptions 713 method.setExceptions(new HashSet<ITypeReference>( 714 parser.exceptionTypes)); 715 method.setReturnType(parser.returnType); 716 717 } else { 718 convertNonGenericExecutableMember(method, dexMethod); 719 GenericSignatureParser parser = new GenericSignatureParser(factory, 720 this); 721 ITypeReference type = parser.parseNonGenericReturnType(dexMethod 722 .getReturnType()); 723 method.setReturnType(type); 724 } 725 addExceptions(method, dexMethod); 726 return method; 727 } 728 729 private void addExceptions(SigExecutableMember member, 730 DexMethod dexMethod) { 731 if (declaresExceptions(dexMethod)) { 732 String exceptionSignature = getExceptionSignature(dexMethod); 733 Set<String> exceptionTypeNames = splitTypeList(exceptionSignature); 734 Set<ITypeReference> exceptions = new HashSet<ITypeReference>(); 735 736 for (String exTypeName : exceptionTypeNames) { 737 String packageName = getPackageName(exTypeName); 738 String className = getClassName(exTypeName); 739 exceptions.add(factory 740 .getClassReference(packageName, className)); 741 } 742 member.setExceptions(exceptions); 743 } else { 744 member.setExceptions(EMPTY_EXCEPTIONS); 745 } 746 } 747 748 private void convertNonGenericExecutableMember(SigExecutableMember member, 749 DexMethod dexMethod) { 750 List<DexParameter> dexParameters = dexMethod.getParameters(); 751 List<IParameter> parameters = new ArrayList<IParameter>(dexParameters 752 .size()); 753 754 for (DexParameter dexParameter : dexParameters) { 755 GenericSignatureParser parser = new GenericSignatureParser(factory, 756 this); 757 ITypeReference type = parser.parseNonGenericType(dexParameter 758 .getTypeName()); 759 SigParameter parameter = new SigParameter(type); 760 parameters.add(parameter); 761 // Annotations 762 parameter.setAnnotations(convertAnnotations(dexParameter 763 .getAnnotations())); 764 } 765 member.setParameters(parameters); 766 767 member.setTypeParameters(EMPTY_TYPE_VARIABLES); 768 769 // if (declaresExceptions(dexMethod)) { 770 // String exceptionSignature = getExceptionSignature(dexMethod); 771 // Set<String> exceptionTypeNames = splitTypeList(exceptionSignature); 772 // Set<IType> exceptions = new HashSet<IType>(); 773 // 774 // for (String exTypeName : exceptionTypeNames) { 775 // String packageName = getPackageName(exTypeName); 776 // String className = getClassName(exTypeName); 777 // exceptions.add(factory.getClass(packageName, className)); 778 // } 779 // member.setExceptions(exceptions); 780 // } else { 781 // member.setExceptions(EMPTY_EXCEPTIONS); 782 // } 783 } 784 785 /** 786 * Converts a set of {@link DexAnnotation} to a set of corresponding 787 * {@link SigAnnotation}. 788 * 789 * @param dexAnnotations 790 * the {@link DexAnnotation}s to convert 791 * @return the corresponding {@link SigAnnotation}s 792 */ 793 private Set<IAnnotation> convertAnnotations( 794 Set<DexAnnotation> dexAnnotations) { 795 Set<IAnnotation> annotations = new HashSet<IAnnotation>(); 796 for (DexAnnotation dexAnnotation : dexAnnotations) { 797 if (!isInternalAnnotation(dexAnnotation)) { 798 annotations.add(convertAnnotation(dexAnnotation)); 799 } 800 } 801 return annotations; 802 } 803 804 /** 805 * Converts a {@link DexAnnotation} to the corresponding 806 * {@link SigAnnotation}. 807 * 808 * @param dexAnnotation 809 * the {@link DexAnnotation} to convert 810 * @return the corresponding {@link SigAnnotation} 811 */ 812 protected SigAnnotation convertAnnotation(DexAnnotation dexAnnotation) { 813 SigAnnotation sigAnnotation = new SigAnnotation(); 814 String packageName = getPackageName(dexAnnotation.getTypeName()); 815 String className = getClassName(dexAnnotation.getTypeName()); 816 sigAnnotation 817 .setType(factory.getClassReference(packageName, className)); 818 sigAnnotation.setElements(convertAnnotationElements(dexAnnotation 819 .getAttributes())); 820 return sigAnnotation; 821 } 822 823 private Set<IAnnotationElement> convertAnnotationElements( 824 List<DexAnnotationAttribute> attributes) { 825 Set<IAnnotationElement> annotationAttributes = 826 new HashSet<IAnnotationElement>(); 827 for (DexAnnotationAttribute dexAnnotationAttribute : attributes) { 828 annotationAttributes 829 .add(convertAnnotationAttribute(dexAnnotationAttribute)); 830 } 831 return annotationAttributes; 832 } 833 834 private IAnnotationElement convertAnnotationAttribute( 835 DexAnnotationAttribute dexAnnotationAttribute) { 836 837 SigAnnotationElement sigElement = new SigAnnotationElement(); 838 String nameOfField = dexAnnotationAttribute.getName(); 839 840 841 String typeName = dexAnnotationAttribute.getAnnotation().getTypeName(); 842 SigClassDefinition annotationClass = factory.getClass( 843 getPackageName(typeName), getClassName(typeName)); 844 if (!Uninitialized.isInitialized( 845 annotationClass.getAnnotationFields())) { 846 initializeClass(getPackageName(typeName), getClassName(typeName)); 847 } 848 for (IAnnotationField field : annotationClass.getAnnotationFields()) { 849 if (nameOfField.equals(field.getName())) { 850 sigElement.setDeclaringField(field); 851 } 852 } 853 854 sigElement.setValue(convertEncodedValue(dexAnnotationAttribute 855 .getEncodedValue())); 856 return sigElement; 857 } 858 859 @SuppressWarnings("unchecked") 860 private Object convertEncodedValue(DexEncodedValue dexEnodedValue) { 861 Object value = null; 862 switch (dexEnodedValue.getType()) { 863 case VALUE_INT: 864 case VALUE_BOOLEAN: 865 case VALUE_BYTE: 866 case VALUE_CHAR: 867 case VALUE_DOUBLE: 868 case VALUE_FLOAT: 869 case VALUE_LONG: 870 case VALUE_NULL: 871 case VALUE_STRING: 872 case VALUE_SHORT: 873 value = dexEnodedValue.getValue(); 874 break; 875 case VALUE_ARRAY: { 876 List<DexEncodedValue> dexValues = 877 (List<DexEncodedValue>) dexEnodedValue.getValue(); 878 Object[] arrayValues = new Object[dexValues.size()]; 879 int i = 0; 880 for (DexEncodedValue dexValue : dexValues) { 881 arrayValues[i++] = convertEncodedValue(dexValue); 882 } 883 value = arrayValues; 884 break; 885 } 886 case VALUE_ANNOTATION: { 887 DexEncodedAnnotation annotation = 888 (DexEncodedAnnotation) dexEnodedValue.getValue(); 889 SigAnnotation sigAnnotation = new SigAnnotation(); 890 String packageName = getPackageName(annotation.getTypeName()); 891 String className = getClassName(annotation.getTypeName()); 892 sigAnnotation.setType(factory.getClassReference(packageName, 893 className)); 894 895 sigAnnotation.setElements(convertAnnotationElements(annotation 896 .getValue())); 897 value = sigAnnotation; 898 break; 899 } 900 case VALUE_FIELD: { 901 String fieldDesc = (String) dexEnodedValue.getValue(); 902 // FORMAT La/b/E;!CONSTANT 903 String[] typeAndFieldName = fieldDesc.split("!"); 904 String typeName = typeAndFieldName[0]; 905 String fieldName = typeAndFieldName[1]; 906 value = elementPool.getField(getQualifiedName(typeName), fieldName); 907 break; 908 } 909 case VALUE_ENUM: { 910 String fieldDesc = (String) dexEnodedValue.getValue(); 911 // FORMAT La/b/E;!CONSTANT 912 String[] typeAndFieldName = fieldDesc.split("!"); 913 String typeName = typeAndFieldName[0]; 914 String fieldName = typeAndFieldName[1]; 915 value = elementPool.getEnumConstant(getQualifiedName(typeName), 916 fieldName); 917 break; 918 } 919 case VALUE_TYPE: { 920 String typeName = (String) dexEnodedValue.getValue(); 921 GenericSignatureParser parser = new GenericSignatureParser(factory, 922 this); 923 value = parser.parseNonGenericReturnType(typeName); 924 break; 925 } 926 default: 927 throw new IllegalStateException(); 928 } 929 return value; 930 } 931 932 public IClassDefinition initializeClass(String packageName, 933 String className) { 934 String dexName = getDexName(packageName, className); 935 DexClass dexClass = dexNameToDexClass.get(dexName); 936 return convertClass(dexClass); 937 } 938 } 939