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