Esempio n. 1
0
  void handleClassAnnotation(ClassDef classDef) {
    Set<? extends Annotation> aSet = classDef.getAnnotations();
    if (aSet == null || aSet.isEmpty()) return;

    List<Tag> tags = handleAnnotation(aSet, classDef.getType());
    if (tags == null) return;

    InnerClassAttribute ica = null;
    for (Tag t : tags)
      if (t != null) {
        if (t instanceof InnerClassTag) {
          if (ica == null) {
            // Do we already have an InnerClassAttribute?
            ica = (InnerClassAttribute) clazz.getTag("InnerClassAttribute");
            // If not, create one
            if (ica == null) {
              ica = new InnerClassAttribute();
              clazz.addTag(ica);
            }
          }
          ica.add((InnerClassTag) t);
        } else if (t instanceof VisibilityAnnotationTag) {
          // If a dalvik/annotation/AnnotationDefault tag is present
          // in a class, its AnnotationElements must be propagated
          // to methods through the creation of new AnnotationDefaultTag.
          VisibilityAnnotationTag vt = (VisibilityAnnotationTag) t;
          for (AnnotationTag a : vt.getAnnotations()) {
            if (a.getType().equals("Ldalvik/annotation/AnnotationDefault;")) {
              for (AnnotationElem ae : a.getElems()) {
                if (ae instanceof AnnotationAnnotationElem) {
                  AnnotationAnnotationElem aae = (AnnotationAnnotationElem) ae;
                  AnnotationTag at = aae.getValue();
                  // extract default elements
                  Map<String, AnnotationElem> defaults = new HashMap<String, AnnotationElem>();
                  for (AnnotationElem aelem : at.getElems()) {
                    defaults.put(aelem.getName(), aelem);
                  }
                  // create default tags containing default elements
                  // and add tags on methods
                  for (SootMethod sm : clazz.getMethods()) {
                    String methodName = sm.getName();
                    if (defaults.containsKey(methodName)) {
                      AnnotationElem e = defaults.get(methodName);

                      // Okay, the name is the same, but is it actually the same type?
                      Type annotationType = getSootType(e);
                      boolean isCorrectType = false;
                      if (annotationType == null) {
                        // we do not know the type of the annotation, so we guess it's the correct
                        // type.
                        isCorrectType = true;
                      } else {
                        if (annotationType.equals(sm.getReturnType())) {
                          isCorrectType = true;
                        } else if (annotationType.equals(ARRAY_TYPE)) {
                          if (sm.getReturnType() instanceof ArrayType) isCorrectType = true;
                        }
                      }

                      if (isCorrectType && sm.getParameterCount() == 0) {
                        e.setName("default");
                        AnnotationDefaultTag d = new AnnotationDefaultTag(e);
                        sm.addTag(d);

                        // In case there is more than one matching method, we only use the first one
                        defaults.remove(sm.getName());
                      }
                    }
                  }
                  for (Entry<String, AnnotationElem> leftOverEntry : defaults.entrySet()) {
                    // We were not able to find a matching method for the tag, because the return
                    // signature
                    // does not match
                    SootMethod found = clazz.getMethodByNameUnsafe(leftOverEntry.getKey());
                    AnnotationElem element = leftOverEntry.getValue();
                    if (found != null) {
                      element.setName("default");
                      AnnotationDefaultTag d = new AnnotationDefaultTag(element);
                      found.addTag(d);
                    }
                  }
                }
              }
            }
          }
          if (!(vt.getVisibility() == AnnotationConstants.RUNTIME_INVISIBLE)) clazz.addTag(vt);
        } else {
          clazz.addTag(t);
        }
        Debug.printDbg("add class annotation: ", t, " type: ", t.getClass());
      }
  }