- /*
- * Copyright 2003-2004 The Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.apache.commons.attributes;
-
- 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 elements with given attributes. This
- * requires that the attribute is {@link Indexed} and that the
- * attribute indexer tool has been run on the jar file containing the
- * classes.
- */
- public class AttributeIndex {
-
- /**
- * Reference to a method parameter. A method parameter
- * is defined by the Method object it is defined in, and the index
- * of the parameter in the method's parameter list.
- */
- public static class MethodParameter {
-
- private final Method method;
- private final int index;
-
- /**
- * Constructs a new MethodParameter.
- */
- 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;
- }
-
- /**
- * Compares two <code>MethodParameter</code>s for equality.
- * They must point to the same method and have the same index.
- */
- public boolean equals (Object o) {
- return o != null && o instanceof MethodParameter &&
- method.equals (((MethodParameter) o).method) &&
- index == ((MethodParameter) o).index;
- }
-
- /**
- * Computes the hashCode.
- */
- public int hashCode () {
- return method.hashCode () + index;
- }
-
- /**
- * Converts this method parameter into a human-readable string.
- */
- public String toString () {
- return method.toString () + ":" + index;
- }
- }
-
- /**
- * A constructor parameter. A method parameter
- * is defined by the Method object it is defined in, and the index
- * of the parameter in the method's parameter list.
- */
- public static class ConstructorParameter {
-
- private final Constructor ctor;
- private final int index;
-
-
- /**
- * Constructs a new ConstructorParameter.
- */
- 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;
- }
-
- /**
- * Compares two <code>ConstructorParameter</code>s for equality.
- * They must point to the same constructor and have the same index.
- */
- public boolean equals (Object o) {
- return o != null && o instanceof ConstructorParameter &&
- ctor.equals (((ConstructorParameter) o).ctor) &&
- index == ((ConstructorParameter) o).index;
- }
-
- /**
- * Computes the hashCode.
- */
- public int hashCode () {
- return ctor.hashCode () + index;
- }
-
- /**
- * Converts this constructor parameter into a human-readable string.
- */
- 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 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);
- }
- }
- }
-
- /**
- * Load the attrs.index from a given URL.
- */
- 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 ("Class: ")) {
- String className = line.substring ("Class: ".length ()).trim ();
- addClass (className);
- }
- }
- } 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)) {
- 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;
- }
- }
-
- /**
- * 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 ({@link 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 ({@link AttributeIndex.MethodParameter}).
- */
- public Collection getMethodParameters (Class attributeClass) {
- if (index.containsKey (attributeClass.getName ())) {
- return ((IndexNode) index.get (attributeClass.getName ())).methodParameters;
- } else {
- return Collections.EMPTY_SET;
- }
- }
- }