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.util.Debug;
011    import edu.rice.cs.cunit.instrumentors.IInstrumentationStrategy;
012    import edu.rice.cs.cunit.instrumentors.DoNotInstrument;
013    
014    /**
015     * Decorator to conditionally execute a decorated strategy.
016     *
017     * @author Mathias Ricken
018     */
019    public abstract class ConditionalStrategy implements IInstrumentationStrategy {
020        /**
021         * Decorated strategy;
022         */
023        IInstrumentationStrategy _decoree;
024    
025        public ConditionalStrategy(IInstrumentationStrategy decoree) {
026            _decoree = decoree;
027        }
028    
029        /**
030         * Instrument the class.
031         *
032         * @param cf class file info
033         */
034        public void instrument(ClassFile cf) {
035            String[] doNotInstrumentPatterns = new String[0];
036            AAttributeInfo attr = cf.getAttribute(RuntimeInvisibleAnnotationsAttributeInfo.getAttributeName());
037            if (null!=attr) {
038                RuntimeInvisibleAnnotationsAttributeInfo ann = (RuntimeInvisibleAnnotationsAttributeInfo)attr;
039                for (AAnnotationsAttributeInfo.Annotation a: ann.getAnnotations()) {
040                    String typeString = ClassFileTools.getTypeString(a.getType(), "");
041                    if (typeString.substring(0,typeString.length()-1).equals(DoNotInstrument.class.getName())) {
042                        for (AAnnotationsAttributeInfo.Annotation.NameValuePair nvp: a.getPairs()) {
043                            if (nvp.getName().toString().equals("instrumentors")) {
044                                AAnnotationsAttributeInfo.Annotation.ConstantMemberValue c = nvp.getValue().execute(
045                                        AAnnotationsAttributeInfo.Annotation.CheckConstantMemberVisitor.singleton(), null);
046                                AUTFPoolInfo patternString = c.getConstValue().execute(CheckUTFVisitor.singleton(), null);
047                                doNotInstrumentPatterns = patternString.toString().split(";");
048                                break;
049                            }
050                        }
051                        break;
052                    }
053                }
054            }
055            if (apply(cf)) {
056                if (!ClassFileTools.classNameMatches(_decoree.getClass().getName(),doNotInstrumentPatterns)) {
057                    _decoree.instrument(cf);
058                }
059                else {
060                    Debug.out.println("Class "+cf.getThisClassName()+" not instrumented with "+
061                                      _decoree.getClass().getName()+" because it matched @DoNotInstrument instrumentors");
062                }
063            }
064        }
065    
066        /**
067         * Return true if the decoree should be applied to this class.
068         *
069         * @return true if decoree should be applied.
070         */
071        public abstract boolean apply(ClassFile cf);
072    
073        /**
074         * Instrumentation of all classes is done.
075         */
076        public void done() {
077            _decoree.done();
078        }
079    }