You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by le...@apache.org on 2004/03/21 01:04:15 UTC

cvs commit: jakarta-commons-sandbox/attributes/compiler/src/java/org/apache/commons/attributes/compiler AttributeIndexer.java

leosutic    2004/03/20 16:04:15

  Modified:    attributes/api/src/java/org/apache/commons/attributes
                        AttributeIndex.java Indexed.java
               attributes/compiler/src/java/org/apache/commons/attributes/compiler
                        AttributeIndexer.java
  Log:
  Improved indexing. (Turns out people are actually using this feature.)
  
  Revision  Changes    Path
  1.7       +340 -21   jakarta-commons-sandbox/attributes/api/src/java/org/apache/commons/attributes/AttributeIndex.java
  
  Index: AttributeIndex.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/attributes/api/src/java/org/apache/commons/attributes/AttributeIndex.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- AttributeIndex.java	19 Feb 2004 14:49:12 -0000	1.6
  +++ AttributeIndex.java	21 Mar 2004 00:04:15 -0000	1.7
  @@ -18,46 +18,274 @@
   import java.io.InputStream;
   import java.io.InputStreamReader;
   import java.io.BufferedReader;
  +import java.lang.reflect.Constructor;
  +import java.lang.reflect.Method;
  +import java.lang.reflect.Field;
   import java.net.URL;
   import java.net.URLConnection;
  +import java.util.ArrayList;
   import java.util.Collection;
   import java.util.Collections;
   import java.util.Enumeration;
   import java.util.HashMap;
   import java.util.HashSet;
  +import java.util.Iterator;
   import java.util.StringTokenizer;
   
   /**
  - * An index providing a list of classes with given attributes. This
  + * An index providing a list of elements with given attributes. This
    * requires that the attribute is <code>Indexed</code> and that the
    * attribute indexer tool has been run on the jar file containing the
    * classes.
    */
   public class AttributeIndex {
       
  +    /**
  +     * A method parameter.
  +     */
  +    public static class MethodParameter {
  +        
  +        private final Method method;
  +        private final int index;
  +        
  +        public MethodParameter (Method method, int index) {
  +            this.method = method;
  +            this.index = index;
  +        }
  +        
  +        /**
  +         * Get the method this parameter is defined in.
  +         */
  +        public Method getMethod () {
  +            return method;
  +        }
  +        
  +        /**
  +         * Get the index of this parameter in the parameter list of the method.
  +         */
  +        public int getIndex () {
  +            return index;
  +        }
  +        
  +        public boolean equals (Object o) {
  +            return o instanceof MethodParameter &&
  +                method.equals (((MethodParameter) o).method) &&
  +                index == ((MethodParameter) o).index;
  +        }
  +        
  +        public int hashCode () {
  +            return method.hashCode () + index;
  +        }
  +        
  +        public String toString () {
  +            return method.toString () + ":" + index;
  +        }
  +    }
  +    
  +    /**
  +     * A constructor parameter.
  +     */
  +    public static class ConstructorParameter {
  +        
  +        private final Constructor ctor;
  +        private final int index;
  +        
  +        public ConstructorParameter (Constructor ctor, int index) {
  +            this.ctor = ctor;
  +            this.index = index;
  +        }
  +        
  +        /**
  +         * Get the constructor this parameter is defined in.
  +         */
  +        public Constructor getConstructor () {
  +            return ctor;
  +        }
  +        
  +        /**
  +         * Get the index of this parameter in the parameter list of the constructor.
  +         */
  +        public int getIndex () {
  +            return index;
  +        }
  +        
  +        public boolean equals (Object o) {
  +            return o instanceof ConstructorParameter &&
  +                ctor.equals (((ConstructorParameter) o).ctor) &&
  +                index == ((ConstructorParameter) o).index;
  +        }
  +        
  +        public int hashCode () {
  +            return ctor.hashCode () + index;
  +        }
  +        
  +        public String toString () {
  +            return ctor.toString () + ":" + index;
  +        }
  +    }
  +    
  +    private static class IndexNode {
  +        public Collection classes = new HashSet ();
  +        public Collection fields = new HashSet ();
  +        public Collection methods = new HashSet ();
  +        public Collection constructors = new HashSet ();
  +        public Collection returnValues = new HashSet ();
  +        public Collection constructorParameters = new HashSet ();
  +        public Collection methodParameters = new HashSet ();
  +        
  +        public void seal () {
  +            classes = seal (classes);
  +            fields = seal (fields);
  +            methods = seal (methods);
  +            constructors = seal (constructors);
  +            returnValues = seal (returnValues);
  +            constructorParameters = seal (constructorParameters);
  +            methodParameters = seal (methodParameters);
  +        }
  +        
  +        private Collection seal (Collection coll) {
  +            return Collections.unmodifiableCollection (coll);
  +        }
  +    }
  +    
       private final HashMap index = new HashMap ();
  +    private final ClassLoader classLoader;
       
       /**
        * Creates a new AttributeIndex for the given ClassLoader.
        */
       public AttributeIndex (ClassLoader cl) throws Exception {
  +        this.classLoader = cl;
           Enumeration enum = cl.getResources ("META-INF/attrs.index");
           while (enum.hasMoreElements ()) {
               URL url = (URL) enum.nextElement ();
               loadFromURL (url);
           }
  +        
  +        Iterator iter = index.values ().iterator ();
  +        while (iter.hasNext ()) {
  +            ((IndexNode) iter.next ()).seal ();
  +        }
  +    }
  +    
  +    private IndexNode getNode (Class attributeClass) {
  +        IndexNode node = (IndexNode) index.get (attributeClass.getName ());
  +        if (node == null) {
  +            node = new IndexNode ();
  +            index.put (attributeClass.getName (), node);
  +        }
  +        
  +        return node;
  +    }
  +    
  +    private void addIndex (Collection attributes, Class clazz) {
  +        Iterator iter = attributes.iterator ();
  +        while (iter.hasNext ()) {
  +            getNode (iter.next ().getClass ()).classes.add (clazz);
  +        }
  +    }
  +    
  +    private void addIndex (Collection attributes, Field field) {
  +        Iterator iter = attributes.iterator ();
  +        while (iter.hasNext ()) {
  +            getNode (iter.next ().getClass ()).fields.add (field);
  +        }
  +    }
  +    
  +    private void addIndex (Collection attributes, Method method) {
  +        Iterator iter = attributes.iterator ();
  +        while (iter.hasNext ()) {
  +            getNode (iter.next ().getClass ()).methods.add (method);
  +        }
  +    }
  +    
  +    private void addIndex (Collection attributes, Constructor constructor) {
  +        Iterator iter = attributes.iterator ();
  +        while (iter.hasNext ()) {
  +            getNode (iter.next ().getClass ()).constructors.add (constructor);
  +        }
  +    }
  +    
  +    private void addReturnIndex (Collection attributes, Method method) {
  +        Iterator iter = attributes.iterator ();
  +        while (iter.hasNext ()) {
  +            getNode (iter.next ().getClass ()).returnValues.add (method);
  +        }
  +    }
  +    
  +    private void addIndex (Collection attributes, Method method, int parameter) {
  +        Iterator iter = attributes.iterator ();
  +        while (iter.hasNext ()) {
  +            getNode (iter.next ().getClass ()).methodParameters.add (new MethodParameter (method, parameter));
  +        }
  +    }
  +    
  +    private void addIndex (Collection attributes, Constructor ctor, int parameter) {
  +        Iterator iter = attributes.iterator ();
  +        while (iter.hasNext ()) {
  +            getNode (iter.next ().getClass ()).constructorParameters.add (new ConstructorParameter (ctor, parameter));
  +        }
       }
       
       /**
        * Add a class to the index.
        */
  -    private void addClass (String attributeClass, String clazz) {
  -        Collection coll = (Collection) index.get (attributeClass);
  -        if (coll == null) {
  -            coll = new HashSet ();
  -            index.put (attributeClass, coll);
  +    private void addClass (String clazzName) throws Exception {
  +        Class clazz = classLoader.loadClass (clazzName);
  +        
  +        // Get the attributes attached to the class itself...
  +        Collection coll = Attributes.getAttributes (clazz);
  +        
  +        coll = AttributeUtil.getObjectsWithAttributeType (coll, Indexed.class);
  +        addIndex (coll, clazz);
  +        
  +        Field[] fields = clazz.getDeclaredFields ();
  +        for (int i = 0; i < fields.length; i++) {
  +            coll = Attributes.getAttributes (fields[i]);
  +            
  +            coll = AttributeUtil.getObjectsWithAttributeType (coll, Indexed.class);
  +            addIndex (coll, fields[i]);
  +        }
  +        
  +        Method[] methods = clazz.getDeclaredMethods ();
  +        for (int i = 0; i < methods.length; i++) {
  +            coll = Attributes.getAttributes (methods[i]);
  +            
  +            coll = AttributeUtil.getObjectsWithAttributeType (coll, Indexed.class);
  +            addIndex (coll, methods[i]);
  +            
  +            // Return values
  +            coll = Attributes.getReturnAttributes (methods[i]);
  +            
  +            coll = AttributeUtil.getObjectsWithAttributeType (coll, Indexed.class);
  +            addReturnIndex (coll, methods[i]);
  +            
  +            // Parameters
  +            int numParameters = methods[i].getParameterTypes().length; 
  +            for (int j = 0; j < numParameters; j++) {
  +                coll = Attributes.getParameterAttributes (methods[i], j);
  +                
  +                coll = AttributeUtil.getObjectsWithAttributeType (coll, Indexed.class);
  +                addIndex (coll, methods[i], j);
  +            }
  +        }
  +        
  +        Constructor[] ctors = clazz.getDeclaredConstructors ();
  +        for (int i = 0; i < ctors.length; i++) {
  +            coll = Attributes.getAttributes (ctors[i]);
  +            
  +            coll = AttributeUtil.getObjectsWithAttributeType (coll, Indexed.class);
  +            addIndex (coll, ctors[i]);
  +            
  +            // Parameters
  +            int numParameters = ctors[i].getParameterTypes().length; 
  +            for (int j = 0; j < numParameters; j++) {
  +                coll = Attributes.getParameterAttributes (ctors[i], j);
  +                
  +                coll = AttributeUtil.getObjectsWithAttributeType (coll, Indexed.class);
  +                addIndex (coll, ctors[i], j);
  +            }
           }
  -        coll.add (clazz);
       }
       
       /**
  @@ -65,30 +293,36 @@
        */
       private void loadFromURL (URL url) throws Exception {
           URLConnection connection = url.openConnection ();
  -            BufferedReader br = new BufferedReader (new InputStreamReader (connection.getInputStream ()));
  -            try {
  -                String currentAttributeClass = null;
  -                String line = null;
  -                while ((line = br.readLine ()) != null) {
  -                    if (line.startsWith ("Attribute: ")) {
  -                        currentAttributeClass = line.substring ("Attribute: ".length ()).trim ();
  -                    } else if (line.startsWith ("Class: ")) {
  -                        String className = line.substring ("Class: ".length ()).trim ();
  -                        addClass (currentAttributeClass, className);
  -                    }
  +        BufferedReader br = new BufferedReader (new InputStreamReader (connection.getInputStream ()));
  +        try {
  +            String currentAttributeClass = null;
  +            String line = null;
  +            while ((line = br.readLine ()) != null) {
  +                if (line.startsWith ("Class: ")) {
  +                    String className = line.substring ("Class: ".length ()).trim ();
  +                    addClass (className);
                   }
  -            } finally {
  -                br.close ();
               }
  +        } finally {
  +            br.close ();
  +        }
       }
       
       /**
        * Gets a Collection of the classes that have an attribute of the specified class.
        * The Collection contains the class names (String).
  +     * 
  +     * @deprecated Use the getClasses(Class) method instead.
        */    
       public Collection getClassesWithAttribute (String attributeClass) {
           if (index.containsKey (attributeClass)) {
  -            return (Collection) index.get (attributeClass);
  +            Collection classes = ((IndexNode) index.get (attributeClass)).classes;
  +            Iterator iter = classes.iterator ();
  +            Collection converted = new ArrayList (classes.size ());
  +            while (iter.hasNext ()) {
  +                converted.add (((Class) iter.next ()).getName ().replace ('$', '.'));
  +            }
  +            return converted;
           } else {
               return Collections.EMPTY_SET;
           }
  @@ -97,9 +331,94 @@
       /**
        * Gets a Collection of the classes that have an attribute of the specified class.
        * The Collection contains the class names (String).
  +     *
  +     * @deprecated Use the getClasses(Class) method instead.
        */
       public Collection getClassesWithAttribute (Class attributeClass) {
           return getClassesWithAttribute (attributeClass.getName ());
       }
       
  +    /**
  +     * Gets a Collection of the <code>Class</code>es that have an attribute of the specified class.
  +     * The Collection contains the classes (Class).
  +     */    
  +    public Collection getClasses (Class attributeClass) {
  +        if (index.containsKey (attributeClass.getName ())) {
  +            return ((IndexNode) index.get (attributeClass.getName ())).classes;
  +        } else {
  +            return Collections.EMPTY_SET;
  +        }
  +    }
  +    
  +    /**
  +     * Gets a Collection of the <code>Method</code>s that have an attribute of the specified class.
  +     * The Collection contains the methods (java.lang.reflect.Method).
  +     */    
  +    public Collection getMethods (Class attributeClass) {
  +        if (index.containsKey (attributeClass.getName ())) {
  +            return ((IndexNode) index.get (attributeClass.getName ())).methods;
  +        } else {
  +            return Collections.EMPTY_SET;
  +        }
  +    }
  +    
  +    /**
  +     * Gets a Collection of the <code>Method</code>s whose return value has an attribute of the specified class.
  +     * The Collection contains the methods (java.lang.reflect.Method).
  +     */    
  +    public Collection getMethodsReturning (Class attributeClass) {
  +        if (index.containsKey (attributeClass.getName ())) {
  +            return ((IndexNode) index.get (attributeClass.getName ())).returnValues;
  +        } else {
  +            return Collections.EMPTY_SET;
  +        }
  +    }
  +    
  +    /**
  +     * Gets a Collection of the <code>Field</code>s that have an attribute of the specified class.
  +     * The Collection contains the methods (java.lang.reflect.Field).
  +     */    
  +    public Collection getFields (Class attributeClass) {
  +        if (index.containsKey (attributeClass.getName ())) {
  +            return ((IndexNode) index.get (attributeClass.getName ())).fields;
  +        } else {
  +            return Collections.EMPTY_SET;
  +        }
  +    }
  +    
  +    /**
  +     * Gets a Collection of the <code>Constructor</code>s that have an attribute of the specified class.
  +     * The Collection contains the methods (java.lang.reflect.Constructor).
  +     */    
  +    public Collection getConstructors (Class attributeClass) {
  +        if (index.containsKey (attributeClass.getName ())) {
  +            return ((IndexNode) index.get (attributeClass.getName ())).constructors;
  +        } else {
  +            return Collections.EMPTY_SET;
  +        }
  +    }
  +    
  +    /**
  +     * Gets a Collection of the <code>ConstructorParameter</code>s that have an attribute of the specified class.
  +     * The Collection contains the methods (AttributeIndex.ConstructorParameter).
  +     */    
  +    public Collection getConstructorParameters (Class attributeClass) {
  +        if (index.containsKey (attributeClass.getName ())) {
  +            return ((IndexNode) index.get (attributeClass.getName ())).constructorParameters;
  +        } else {
  +            return Collections.EMPTY_SET;
  +        }
  +    }
  +    
  +    /**
  +     * Gets a Collection of the <code>MethodParameter</code>s that have an attribute of the specified class.
  +     * The Collection contains the methods (AttributeIndex.MethodParameter).
  +     */    
  +    public Collection getMethodParameters (Class attributeClass) {
  +        if (index.containsKey (attributeClass.getName ())) {
  +            return ((IndexNode) index.get (attributeClass.getName ())).methodParameters;
  +        } else {
  +            return Collections.EMPTY_SET;
  +        }
  +    }
   }
  
  
  
  1.7       +4 -11     jakarta-commons-sandbox/attributes/api/src/java/org/apache/commons/attributes/Indexed.java
  
  Index: Indexed.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/attributes/api/src/java/org/apache/commons/attributes/Indexed.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- Indexed.java	20 Mar 2004 00:47:21 -0000	1.6
  +++ Indexed.java	21 Mar 2004 00:04:15 -0000	1.7
  @@ -17,17 +17,10 @@
   
   /**
    * This attribute is used to mark attributes as being indexed.
  - * Indexed attributes will result in the attribute-jar-index tool
  - * creating an entry for a class marked with an attribute that is indexed.
  - * For example, if the attribute Service is Indexed, and the classes
  - * MyService and MyService2 have Service as a class attribute, the 
  - * jar-index will be:
  - *
  - * <pre><code>
  - * AttributeType: Service
  - * Class: MyService
  - * Class: MyService2
  - * </code></pre>
  + * Elements with indexed attributes can be found via an AttributeIndex,
  + * but incur a slight processing and memory penalty. You must also
  + * run the attribute-indexer tool on the Jar-file containing the classes
  + * you wish to find via the index.
    */
   public class Indexed {
   }
  
  
  
  1.8       +12 -50    jakarta-commons-sandbox/attributes/compiler/src/java/org/apache/commons/attributes/compiler/AttributeIndexer.java
  
  Index: AttributeIndexer.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/attributes/compiler/src/java/org/apache/commons/attributes/compiler/AttributeIndexer.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- AttributeIndexer.java	19 Feb 2004 14:49:13 -0000	1.7
  +++ AttributeIndexer.java	21 Mar 2004 00:04:15 -0000	1.8
  @@ -24,11 +24,13 @@
   import java.io.PrintStream;
   import java.net.URL;
   import java.net.URLClassLoader;
  +import java.util.ArrayList;
   import java.util.Collection;
   import java.util.Enumeration;
   import java.util.HashMap;
   import java.util.HashSet;
   import java.util.Iterator;
  +import java.util.List;
   import java.util.jar.JarFile;
   import java.util.jar.JarEntry;
   import java.util.jar.JarOutputStream;
  @@ -63,7 +65,7 @@
   public class AttributeIndexer extends Task {
       
       private File jarFile;
  -    private HashMap attributes = new HashMap ();
  +    private List classes = new ArrayList ();
       private Path classPath;
       private File baseName;
       private boolean inMaven = false;
  @@ -73,15 +75,6 @@
       public AttributeIndexer () {
       }
       
  -    protected void addAttribute (String className, String attributeName) {
  -        HashSet thisAttr = (HashSet) attributes.get (attributeName);
  -        if (thisAttr == null) {
  -            thisAttr = new HashSet ();
  -            attributes.put (attributeName, thisAttr);
  -        }
  -        thisAttr.add (className);
  -    }
  -    
       public void setJarfile (File jarFile) {
           this.jarFile = jarFile;
       }
  @@ -96,9 +89,7 @@
           return classPath;
       }
       
  -    private static final String SUFFIX = "$__attributeRepository";
  -    private static final String CLASS_SUFFIX = SUFFIX + ".class";
  -    private static final String SOURCE_SUFFIX = SUFFIX + ".java";
  +    private static final String SUFFIX = "$__attributeRepository.class";
       
       protected void copyEntry (JarFile jar, JarEntry entry, JarOutputStream outputStream) throws Exception {
           outputStream.putNextEntry (entry);
  @@ -153,10 +144,7 @@
               return;
           }
           try {
  -            log ("Building attribute index for " + jarFile.getPath ());
  -            
  -            AntClassLoader cl = new AntClassLoader (this.getClass ().getClassLoader (), project, classPath, true);
  -            cl.addPathElement (jarFile.getPath ());
  +            log ("Creating attribute index for " + jarFile.getPath ());
               
               JarFile jar = new JarFile (jarFile);
               File newJarFile = new File (jarFile.getPath () + ".new");
  @@ -167,26 +155,9 @@
                       JarEntry entry = (JarEntry) enum.nextElement ();
                       if (!entry.isDirectory ()) {
                           String className = entry.getName ();
  -                        if (className.endsWith (CLASS_SUFFIX)) {
  -                            className = className.replace ('/', '.').replace ('\\', '.');
  -                            String baseClassName = className.substring (0, className.length () - CLASS_SUFFIX.length ()).replace ('$', '.');
  -                            className = className.substring (0, className.length () - 6);
  -                            Class repoClass = cl.loadClass (className);
  -                            AttributeRepositoryClass repo = (AttributeRepositoryClass) repoClass.newInstance ();
  -                            Collection classAttrs = repo.getClassAttributes ();
  -                            
  -                            Collection indexedAttrs = new HashSet ();
  -                            Iterator inner = classAttrs.iterator ();
  -                            while (inner.hasNext ()) {
  -                                indexedAttrs.add (inner.next ().getClass ());
  -                            }
  -                            
  -                            indexedAttrs = AttributeUtil.getClassesWithAttributeType (indexedAttrs, Indexed.class);
  -                            
  -                            inner = indexedAttrs.iterator ();
  -                            while (inner.hasNext ()) {
  -                                addAttribute (baseClassName, ((Class) inner.next ()).getName ());
  -                            }
  +                        if (className.endsWith (".class") && !className.endsWith (SUFFIX)) {
  +                            className = className.replace ('/', '.').replace ('\\', '.').substring (0, className.length () - 6);
  +                            classes.add (className);
                           }
                       }  
                       
  @@ -197,25 +168,16 @@
                   
                   output.putNextEntry (new JarEntry (INDEX_FILENAME));
                   
  -                
  -                Iterator attrs = attributes.keySet ().iterator ();
  +                Iterator attrs = classes.iterator ();
                   while (attrs.hasNext ()) {
  -                    String attrName = (String) attrs.next ();
  -                    output.write (("Attribute: " + attrName + "\n").getBytes ());
  -                    
  -                    Iterator classes = ((Collection) attributes.get (attrName)).iterator ();
  -                    while (classes.hasNext ()) {
  -                        output.write (("Class: " + classes.next () + "\n").getBytes ());
  -                    }
  -                    output.write ("\n".getBytes ());
  +                    String className = (String) attrs.next ();
  +                    output.write (("Class: " + className + "\n").getBytes ());
                   }
               } finally {
                   output.close ();
                   jar.close ();
               }
  -            
  -            cl.cleanup ();
  -            
  +                        
               jarFile.delete ();
               newJarFile.renameTo (jarFile);
           } catch (Exception e) {
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org