org.apache.commons.attributes.AttributeIndex Maven / Gradle / Ivy
/*
* 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 MethodParameter
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 ConstructorParameter
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 Class
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 Method
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 Method
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 Field
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 Constructor
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 ConstructorParameter
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 MethodParameter
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;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy