001    package edu.rice.cs.cunit.instrumentors.util;
002    
003    import edu.rice.cs.cunit.classFile.ClassFile;
004    import edu.rice.cs.cunit.classFile.ClassFileTools;
005    import edu.rice.cs.cunit.classFile.attributes.AAnnotationsAttributeInfo;
006    import edu.rice.cs.cunit.classFile.attributes.AAttributeInfo;
007    import edu.rice.cs.cunit.classFile.attributes.RuntimeInvisibleAnnotationsAttributeInfo;
008    import edu.rice.cs.cunit.classFile.constantPool.AUTFPoolInfo;
009    import edu.rice.cs.cunit.classFile.constantPool.visitors.CheckUTFVisitor;
010    import edu.rice.cs.cunit.instrumentors.DoNotInstrument;
011    import edu.rice.cs.cunit.instrumentors.IInstrumentationStrategy;
012    import edu.rice.cs.cunit.util.Debug;
013    
014    import java.util.ArrayList;
015    import java.util.List;
016    
017    /**
018     * Decorator to execute several strategies at once.
019     *
020     * @author Mathias Ricken
021     */
022    public class CompoundStrategy implements IInstrumentationStrategy, IScannerStrategy {
023        /**
024         * Parameters for the instrumentors.
025         */
026        List<String> _parameters;
027    
028        /**
029         * Contained strategies.
030         */
031        ArrayList<IInstrumentationStrategy> _combined = new ArrayList<IInstrumentationStrategy>();
032    
033        /**
034         * Constructor for an empty compound strategy.
035         * @param parameters parameters for the instrumentors
036         */
037        public CompoundStrategy(List<String> parameters) {
038            _parameters = parameters;
039        }
040    
041        /**
042         * Constructor for a compound strategy.
043         * @param parameters parameters for the instrumentors
044         * @param contained strategies to combine
045         */
046        public CompoundStrategy(List<String> parameters, IInstrumentationStrategy[] contained) {
047            this(parameters);
048            for (IInstrumentationStrategy is: contained) {
049                _combined.add(is);
050            }
051        }
052    
053        /**
054         * Returns the list of combined strategies.
055         * @return list of combined strategies.
056         */
057        public List<IInstrumentationStrategy> getCombined() {
058            return _combined;
059        }
060    
061        /**
062         * Instrument the class.
063         *
064         * @param cf class file info
065         */
066        public void instrument(ClassFile cf) {
067            String[] doNotInstrumentPatterns = new String[0];
068            AAttributeInfo attr = cf.getAttribute(RuntimeInvisibleAnnotationsAttributeInfo.getAttributeName());
069            if (null!=attr) {
070                RuntimeInvisibleAnnotationsAttributeInfo ann = (RuntimeInvisibleAnnotationsAttributeInfo)attr;
071                for (AAnnotationsAttributeInfo.Annotation a: ann.getAnnotations()) {
072                    String typeString = ClassFileTools.getTypeString(a.getType(), "");
073                    if (typeString.substring(0,typeString.length()-1).equals(DoNotInstrument.class.getName())) {
074                        for (AAnnotationsAttributeInfo.Annotation.NameValuePair nvp: a.getPairs()) {
075                            if (nvp.getName().toString().equals("instrumentors")) {
076                                AAnnotationsAttributeInfo.Annotation.ConstantMemberValue c = nvp.getValue().execute(
077                                        AAnnotationsAttributeInfo.Annotation.CheckConstantMemberVisitor.singleton(), null);
078                                AUTFPoolInfo patternString = c.getConstValue().execute(CheckUTFVisitor.singleton(), null);
079                                doNotInstrumentPatterns = patternString.toString().split(";");
080                                break;
081                            }
082                        }
083                        break;
084                    }
085                }
086            }
087            // apply all instrumentors
088            for(IInstrumentationStrategy itor : _combined) {
089                if (!ClassFileTools.classNameMatches(itor.getClass().getName(),doNotInstrumentPatterns)) {
090                    itor.instrument(cf);
091                }
092                else {
093                    Debug.out.println("Class "+cf.getThisClassName()+" not instrumented with "+
094                                      itor.getClass().getName()+" because it matched @DoNotInstrument instrumentors");
095                }
096            }
097        }
098    
099        /**
100         * Returns the combined list of all scan results.
101         * @return combined list of usage locations
102         */
103        public List<IScanResult> getScanResults() {
104            List<IScanResult> results = new ArrayList<IScanResult>();
105            for(IInstrumentationStrategy is: _combined) {
106                if (is instanceof IScannerStrategy) {
107                    results.addAll(((IScannerStrategy)is).getScanResults());
108                }
109            }
110            return results;
111        }
112    
113        /**
114         * Instrumentation of all classes is done.
115         */
116        public void done() {
117            // apply all instrumentors
118            for(IInstrumentationStrategy itor : _combined) {
119                itor.done();
120            }
121        }
122    }