All Downloads are FREE. Search and download functionalities are using the official Maven repository.

soot.jimple.toolkits.annotation.j5anno.AnnotationGenerator Maven / Gradle / Ivy

package soot.jimple.toolkits.annotation.j5anno;

/*-
 * #%L
 * Soot - a J*va Optimization Framework
 * %%
 * Copyright (C) 2008 Will Benton
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 2.1 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import soot.G;
import soot.Singletons.Global;
import soot.SootClass;
import soot.SootField;
import soot.SootMethod;
import soot.tagkit.AnnotationConstants;
import soot.tagkit.AnnotationElem;
import soot.tagkit.AnnotationTag;
import soot.tagkit.Host;
import soot.tagkit.Tag;
import soot.tagkit.VisibilityAnnotationTag;

/**
 * AnnotationGenerator is a singleton class that wraps up Soot's support for Java 5 annotations in a more convenient
 * interface. It supplies three annotate() methods that take an Host, an annotation class, and zero or more
 * AnnotationElem objects; these methods find the appropriate Tag on the given Host for the
 * appropriate annotation visibility and add an annotation of the given type to it. Note that the first two methods
 * expect an annotation class, which the last method expects a class name. If the class is passed, this class has to be on
 * Soot's classpath at compile time. It is not enough to add the class to the soo-classpath!
*
* * One caveat: annotate() does not add annotation classes to the Scene, so you will have to manually add any * annotation classes that were not already in the Scene to the output directory or jar. * * @author Will Benton * @author Eric Bodden */ public class AnnotationGenerator { public AnnotationGenerator(Global g) { } /** * Returns the unique instance of AnnotationGenerator. */ public static AnnotationGenerator v() { return G.v().soot_jimple_toolkits_annotation_j5anno_AnnotationGenerator(); } /** * Applies a Java 1.5-style annotation to a given Host. The Host must be of type {@link SootClass}, {@link SootMethod} or * {@link SootField}. * * @param h * a method, field, or class * @param klass * the class of the annotation to apply to h * @param elems * a (possibly empty) sequence of AnnotationElem objects corresponding to the elements that should be contained in * this annotation */ public void annotate(Host h, Class klass, AnnotationElem... elems) { annotate(h, klass, Arrays.asList(elems)); } /** * Applies a Java 1.5-style annotation to a given Host. The Host must be of type {@link SootClass}, {@link SootMethod} or * {@link SootField}. * * @param h * a method, field, or class * @param klass * the class of the annotation to apply to h * @param elems * a (possibly empty) sequence of AnnotationElem objects corresponding to the elements that should be contained in * this annotation */ public void annotate(Host h, Class klass, List elems) { // error-checking -- is this annotation appropriate for the target Host? Target t = klass.getAnnotation(Target.class); Collection elementTypes = Arrays.asList(t.value()); final String ERR = "Annotation class " + klass + " not applicable to host of type " + h.getClass() + "."; if (h instanceof SootClass) { if (!elementTypes.contains(ElementType.TYPE)) { throw new RuntimeException(ERR); } } else if (h instanceof SootMethod) { if (!elementTypes.contains(ElementType.METHOD)) { throw new RuntimeException(ERR); } } else if (h instanceof SootField) { if (!elementTypes.contains(ElementType.FIELD)) { throw new RuntimeException(ERR); } } else { throw new RuntimeException("Tried to attach annotation to host of type " + h.getClass() + "."); } // get the retention type of the class Retention r = klass.getAnnotation(Retention.class); // CLASS (runtime invisible) retention is the default int retPolicy = AnnotationConstants.RUNTIME_INVISIBLE; if (r != null) { // TODO why actually do we have AnnotationConstants at all and don't use // RetentionPolicy directly? (Eric Bodden 20/05/2008) switch (r.value()) { case CLASS: retPolicy = AnnotationConstants.RUNTIME_INVISIBLE; break; case RUNTIME: retPolicy = AnnotationConstants.RUNTIME_VISIBLE; break; default: throw new RuntimeException("Unexpected retention policy: " + retPolicy); } } annotate(h, klass.getCanonicalName(), retPolicy, elems); } /** * Applies a Java 1.5-style annotation to a given Host. The Host must be of type {@link SootClass}, {@link SootMethod} or * {@link SootField}. * * @param h * a method, field, or class * @param annotationName * the qualified name of the annotation class * @param visibility * any of the constants in {@link AnnotationConstants} * @param elems * a (possibly empty) sequence of AnnotationElem objects corresponding to the elements that should be contained in * this annotation */ public void annotate(Host h, String annotationName, int visibility, List elems) { annotationName = annotationName.replace('.', '/'); if (!annotationName.endsWith(";")) { annotationName = "L" + annotationName + ';'; } VisibilityAnnotationTag tagToAdd = findOrAdd(h, visibility); AnnotationTag at = new AnnotationTag(annotationName, elems); tagToAdd.addAnnotation(at); } /** * Finds a VisibilityAnnotationTag attached to a given Host with the appropriate visibility, or adds one if no such tag is * attached. * * @param h * an Host * @param visibility * a visibility level, taken from soot.tagkit.AnnotationConstants * @return */ private VisibilityAnnotationTag findOrAdd(Host h, int visibility) { ArrayList va_tags = new ArrayList(); for (Tag t : h.getTags()) { if (t instanceof VisibilityAnnotationTag) { VisibilityAnnotationTag vat = (VisibilityAnnotationTag) t; if (vat.getVisibility() == visibility) { va_tags.add(vat); } } } if (va_tags.isEmpty()) { VisibilityAnnotationTag vat = new VisibilityAnnotationTag(visibility); h.addTag(vat); return vat; } // return the first visibility annotation with the right visibility return (va_tags.get(0)); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy