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

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

There is a newer version: 1.12.0
Show newest version
/* Soot - a J*va Optimization Framework
 * Copyright (C) 2008 Will Benton
 *
 * This library 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 library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
package soot.jimple.toolkits.annotation.j5anno;

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.SootClass;
import soot.SootField;
import soot.SootMethod;
import soot.Singletons.Global;
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.size()); for (AnnotationElem elem : elems) at.addElem(elem); 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