Exemplo n.º 1
0
  /**
   * @param annotations
   * @return
   */
  private List<Tag> handleAnnotation(
      Set<? extends org.jf.dexlib2.iface.Annotation> annotations, String classType) {
    if (annotations == null || annotations.size() == 0) return null;

    List<Tag> tags = new ArrayList<Tag>();
    VisibilityAnnotationTag[] vatg =
        new VisibilityAnnotationTag[3]; // RUNTIME_VISIBLE, RUNTIME_INVISIBLE, SOURCE_VISIBLE, see
    // soot.tagkit.AnnotationConstants

    for (Annotation a : annotations) {
      int v = getVisibility(a.getVisibility());

      Tag t = null;
      Type atype = DexType.toSoot(a.getType());
      String atypes = atype.toString();
      int eSize = a.getElements().size();
      Debug.printDbg("annotation type: ", atypes, " elements: ", eSize);

      if (atypes.equals("dalvik.annotation.AnnotationDefault")) {
        if (eSize != 1)
          throw new RuntimeException(
              "error: expected 1 element for annotation Default. Got " + eSize + " instead.");
        // get element
        AnnotationElem e = getElements(a.getElements()).get(0);
        AnnotationTag adt = new AnnotationTag(a.getType());
        adt.addElem(e);
        if (vatg[v] == null) vatg[v] = new VisibilityAnnotationTag(v);
        vatg[v].addAnnotation(adt);

      } else if (atypes.equals("dalvik.annotation.EnclosingClass")) {
        if (eSize != 1)
          throw new RuntimeException(
              "error: expected 1 element for annotation EnclosingClass. Got "
                  + eSize
                  + " instead.");

        for (AnnotationElement elem : a.getElements()) {
          String outerClass = ((TypeEncodedValue) elem.getValue()).getValue();
          outerClass = Util.dottedClassName(outerClass);
          deps.typesToSignature.add(RefType.v(outerClass));
          clazz.setOuterClass(SootResolver.v().makeClassRef(outerClass));
          assert clazz.getOuterClass() != clazz;
        }

        // EnclosingClass comes in pair with InnerClass.
        // Those are generated from a single InnerClassTag,
        // that is re-constructed only for the InnerClass Dalvik
        // annotation.
        continue;

      } else if (atypes.equals("dalvik.annotation.EnclosingMethod")) {
        if (eSize != 1)
          throw new RuntimeException(
              "error: expected 1 element for annotation EnclosingMethod. Got "
                  + eSize
                  + " instead.");
        AnnotationStringElem e = (AnnotationStringElem) getElements(a.getElements()).get(0);
        String[] split1 = e.getValue().split("\\ \\|");
        String classString = split1[0];
        String methodString = split1[1];
        String parameters = split1[2];
        String returnType = split1[3];
        String methodSigString = "(" + parameters + ")" + returnType;
        t = new EnclosingMethodTag(classString, methodString, methodSigString);

        String outerClass = classString.replace("/", ".");
        deps.typesToSignature.add(RefType.v(outerClass));
        clazz.setOuterClass(SootResolver.v().makeClassRef(outerClass));
        assert clazz.getOuterClass() != clazz;

      } else if (atypes.equals("dalvik.annotation.InnerClass")) {
        int accessFlags = -1; // access flags of the inner class
        String name = null; // name of the inner class

        for (AnnotationElem ele : getElements(a.getElements())) {
          if (ele instanceof AnnotationIntElem && ele.getName().equals("accessFlags"))
            accessFlags = ((AnnotationIntElem) ele).getValue();
          else if (ele instanceof AnnotationStringElem && ele.getName().equals("name"))
            name = ((AnnotationStringElem) ele).getValue();
          else throw new RuntimeException("Unexpected inner class annotation element");
        }

        String outerClass; // outer class name
        if (name == null) outerClass = classType.replaceAll("\\$[0-9,a-z,A-Z]*;$", ";");
        else outerClass = classType.replaceFirst("\\$" + name + ";$", ";");

        // Make sure that no funny business is going on if the
        // annotation is broken and does not end in $nn.
        if (outerClass.equals(classType)) {
          outerClass = null;
        }

        Tag innerTag =
            new InnerClassTag(
                DexType.toSootICAT(classType),
                outerClass == null ? null : DexType.toSootICAT(outerClass),
                name,
                accessFlags);
        tags.add(innerTag);

        if (outerClass != null && !clazz.hasOuterClass()) {
          String sootOuterClass = Util.dottedClassName(outerClass);
          deps.typesToSignature.add(RefType.v(sootOuterClass));
          clazz.setOuterClass(SootResolver.v().makeClassRef(sootOuterClass));
          assert clazz.getOuterClass() != clazz;
        }

        continue;

      } else if (atypes.equals("dalvik.annotation.MemberClasses")) {
        AnnotationArrayElem e = (AnnotationArrayElem) getElements(a.getElements()).get(0);
        for (AnnotationElem ae : e.getValues()) {
          AnnotationClassElem c = (AnnotationClassElem) ae;
          String innerClass = c.getDesc();
          String outerClass = innerClass.replaceAll("\\$[^\\$]*$", "");
          String name = innerClass.replaceAll("^.*\\$", "").replaceAll(";$", "");
          if (name.replaceAll("[0-9].*", "").equals("")) { // anonymous or local inner classes
            name = null;
          }
          int accessFlags =
              0; // seems like this information is lost during the .class -- dx --> .dex process.
          Tag innerTag =
              new InnerClassTag(
                  DexType.toSootICAT(innerClass),
                  DexType.toSootICAT(outerClass),
                  name,
                  accessFlags);
          tags.add(innerTag);
        }
        continue;

      } else if (atypes.equals("dalvik.annotation.Signature")) {
        if (eSize != 1)
          throw new RuntimeException(
              "error: expected 1 element for annotation Signature. Got " + eSize + " instead.");
        AnnotationArrayElem e = (AnnotationArrayElem) getElements(a.getElements()).get(0);
        String sig = "";
        for (AnnotationElem ae : e.getValues()) {
          AnnotationStringElem s = (AnnotationStringElem) ae;
          sig += s.getValue();
        }
        t = new SignatureTag(sig);

      } else if (atypes.equals("dalvik.annotation.Throws")) {
        // this is handled in soot.dexpler.DexMethod
        continue;

      } else if (atypes.equals("java.lang.Deprecated")) {
        if (eSize != 0)
          throw new RuntimeException(
              "error: expected 1 element for annotation Deprecated. Got " + eSize + " instead.");

        t = new DeprecatedTag();

        AnnotationTag adt = new AnnotationTag("Ljava/lang/Deprecated;");
        if (vatg[v] == null) vatg[v] = new VisibilityAnnotationTag(v);
        vatg[v].addAnnotation(adt);

      } else {
        Debug.printDbg("read visibility tag: ", a.getType());

        if (vatg[v] == null) vatg[v] = new VisibilityAnnotationTag(v);

        AnnotationTag tag = new AnnotationTag(a.getType());
        for (AnnotationElem e : getElements(a.getElements())) tag.addElem(e);
        vatg[v].addAnnotation(tag);
      }

      tags.add(t);
    }

    for (VisibilityAnnotationTag vat : vatg) if (vat != null) tags.add(vat);

    return tags;
  }
  /**
   * Run from the command-line, with a list of URLs as argument.
   *
   * <p><B>NOTE:</B><br>
   * This code will run with all the documents in memory - if you want to unload each from memory
   * after use, add code to store the corpus in a DataStore.
   */
  public static void main(String args[]) throws GateException, IOException {
    // initialise the GATE library
    Out.prln("Initialising GATE...");
    Gate.init();
    Out.prln("...GATE initialised");

    // initialise ANNIE (this may take several minutes)
    StandAloneAnnie annie = new StandAloneAnnie();
    annie.initAnnie();

    // create a GATE corpus and add a document for each command-line
    // argument
    Corpus corpus = Factory.newCorpus("StandAloneAnnie corpus");
    for (int i = 0; i < args.length; i++) {
      URL u = new URL(args[i]);
      FeatureMap params = Factory.newFeatureMap();
      params.put("sourceUrl", u);
      params.put("preserveOriginalContent", new Boolean(true));
      params.put("collectRepositioningInfo", new Boolean(true));
      Out.prln("Creating doc for " + u);
      Document doc = (Document) Factory.createResource("gate.corpora.DocumentImpl", params);
      corpus.add(doc);
    } // for each of args

    // tell the pipeline about the corpus and run it
    annie.setCorpus(corpus);
    annie.execute();

    // for each document, get an XML document with the
    // person and location names added
    Iterator iter = corpus.iterator();
    int count = 0;
    String startTagPart_1 = "<span GateID=\"";
    String startTagPart_2 = "\" title=\"";
    String startTagPart_3 = "\" style=\"background:Red;\">";
    String endTag = "</span>";

    while (iter.hasNext()) {
      Document doc = (Document) iter.next();
      AnnotationSet defaultAnnotSet = doc.getAnnotations();
      Set annotTypesRequired = new HashSet();
      annotTypesRequired.add("Person");
      annotTypesRequired.add("Location");
      Set<Annotation> peopleAndPlaces =
          new HashSet<Annotation>(defaultAnnotSet.get(annotTypesRequired));

      FeatureMap features = doc.getFeatures();
      String originalContent =
          (String) features.get(GateConstants.ORIGINAL_DOCUMENT_CONTENT_FEATURE_NAME);
      RepositioningInfo info =
          (RepositioningInfo) features.get(GateConstants.DOCUMENT_REPOSITIONING_INFO_FEATURE_NAME);

      ++count;
      File file = new File("StANNIE_" + count + ".HTML");
      Out.prln("File name: '" + file.getAbsolutePath() + "'");
      if (originalContent != null && info != null) {
        Out.prln("OrigContent and reposInfo existing. Generate file...");

        Iterator it = peopleAndPlaces.iterator();
        Annotation currAnnot;
        SortedAnnotationList sortedAnnotations = new SortedAnnotationList();

        while (it.hasNext()) {
          currAnnot = (Annotation) it.next();
          sortedAnnotations.addSortedExclusive(currAnnot);
        } // while

        StringBuffer editableContent = new StringBuffer(originalContent);
        long insertPositionEnd;
        long insertPositionStart;
        // insert anotation tags backward
        Out.prln("Unsorted annotations count: " + peopleAndPlaces.size());
        Out.prln("Sorted annotations count: " + sortedAnnotations.size());
        for (int i = sortedAnnotations.size() - 1; i >= 0; --i) {
          currAnnot = (Annotation) sortedAnnotations.get(i);
          insertPositionStart = currAnnot.getStartNode().getOffset().longValue();
          insertPositionStart = info.getOriginalPos(insertPositionStart);
          insertPositionEnd = currAnnot.getEndNode().getOffset().longValue();
          insertPositionEnd = info.getOriginalPos(insertPositionEnd, true);
          if (insertPositionEnd != -1 && insertPositionStart != -1) {
            editableContent.insert((int) insertPositionEnd, endTag);
            editableContent.insert((int) insertPositionStart, startTagPart_3);
            editableContent.insert((int) insertPositionStart, currAnnot.getType());
            editableContent.insert((int) insertPositionStart, startTagPart_2);
            editableContent.insert((int) insertPositionStart, currAnnot.getId().toString());
            editableContent.insert((int) insertPositionStart, startTagPart_1);
          } // if
        } // for

        FileWriter writer = new FileWriter(file);
        writer.write(editableContent.toString());
        writer.close();
      } // if - should generate
      else if (originalContent != null) {
        Out.prln("OrigContent existing. Generate file...");

        Iterator it = peopleAndPlaces.iterator();
        Annotation currAnnot;
        SortedAnnotationList sortedAnnotations = new SortedAnnotationList();

        while (it.hasNext()) {
          currAnnot = (Annotation) it.next();
          sortedAnnotations.addSortedExclusive(currAnnot);
        } // while

        StringBuffer editableContent = new StringBuffer(originalContent);
        long insertPositionEnd;
        long insertPositionStart;
        // insert anotation tags backward
        Out.prln("Unsorted annotations count: " + peopleAndPlaces.size());
        Out.prln("Sorted annotations count: " + sortedAnnotations.size());
        for (int i = sortedAnnotations.size() - 1; i >= 0; --i) {
          currAnnot = (Annotation) sortedAnnotations.get(i);
          insertPositionStart = currAnnot.getStartNode().getOffset().longValue();
          insertPositionEnd = currAnnot.getEndNode().getOffset().longValue();
          if (insertPositionEnd != -1 && insertPositionStart != -1) {
            editableContent.insert((int) insertPositionEnd, endTag);
            editableContent.insert((int) insertPositionStart, startTagPart_3);
            editableContent.insert((int) insertPositionStart, currAnnot.getType());
            editableContent.insert((int) insertPositionStart, startTagPart_2);
            editableContent.insert((int) insertPositionStart, currAnnot.getId().toString());
            editableContent.insert((int) insertPositionStart, startTagPart_1);
          } // if
        } // for

        FileWriter writer = new FileWriter(file);
        writer.write(editableContent.toString());
        writer.close();
      } else {
        Out.prln("Content : " + originalContent);
        Out.prln("Repositioning: " + info);
      }

      String xmlDocument = doc.toXml(peopleAndPlaces, false);
      String fileName = new String("StANNIE_toXML_" + count + ".HTML");
      FileWriter writer = new FileWriter(fileName);
      writer.write(xmlDocument);
      writer.close();
    } // for each doc
  } // main