/* * 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 com.asper.sources.net.sf.cglib.reflect; import com.asper.sources.net.sf.cglib.core.Signature; import com.asper.sources.org.objectweb.asm.Type; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class FastClass { private Class type; protected FastClass() { throw new Error("Using the FastClass empty constructor--please report to the cglib-devel mailing list"); } protected FastClass(Class type) { this.type = type; } public static FastClass create(Class type) { return create(type.getClassLoader(), type); } public static FastClass create(ClassLoader loader, Class type) { return new FastClass(type); } public Object invoke(String name, Class[] parameterTypes, Object obj, Object[] args) throws InvocationTargetException { return invoke(getIndex(name, parameterTypes), obj, args); } public static final Class[] EMPTY_CLASS_ARRAY = {}; public Object newInstance() throws InvocationTargetException { return newInstance(getIndex(EMPTY_CLASS_ARRAY), null); } public Object newInstance(Class[] parameterTypes, Object[] args) throws InvocationTargetException { return newInstance(getIndex(parameterTypes), args); } public FastMethod getMethod(Method method) { return new FastMethod(this, method); } public FastConstructor getConstructor(Constructor constructor) { return new FastConstructor(this, constructor); } public FastMethod getMethod(String name, Class[] parameterTypes) { try { return getMethod(type.getMethod(name, parameterTypes)); } catch (NoSuchMethodException e) { throw new NoSuchMethodError(e.getMessage()); } } public FastConstructor getConstructor(Class[] parameterTypes) { try { return getConstructor(type.getConstructor(parameterTypes)); } catch (NoSuchMethodException e) { throw new NoSuchMethodError(e.getMessage()); } } public String getName() { return type.getName(); } public Class getJavaClass() { return type; } public String toString() { return type.toString(); } public int hashCode() { return type.hashCode(); } public boolean equals(Object o) { if (o == null || !(o instanceof FastClass)) { return false; } return type.equals(((FastClass) o).type); } /** * Return the index of the matching method. The index may be used * later to invoke the method with less overhead. If more than one * method matches (i.e. they differ by return type only), one is * chosen arbitrarily. * * @param name the method name * @param parameterTypes the parameter array * @return the index, or <code>-1</code> if none is found. * @see #invoke(int, Object, Object[]) */ public int getIndex(String name, Class[] parameterTypes) { Method[] methods = type.getMethods(); int index = 0; for (Method method : methods) { if (method.getName().equals(name)) { Class<?>[] types = method.getParameterTypes(); int length = types.length; boolean found = false; if (parameterTypes.length == length) { found = true; for (int i = 0; i < length; i++) { Class a = parameterTypes[i]; Class b = types[i]; if (!a.equals(b)) found = false; } } if (found) return index; } index++; } return -1; } /** * Return the index of the matching constructor. The index may be used * later to create a new instance with less overhead. * * @param parameterTypes the parameter array * @return the constructor index, or <code>-1</code> if none is found. * @see #newInstance(int, Object[]) */ public int getIndex(Class[] parameterTypes) { Method[] methods = type.getMethods(); int index = 0; for (Method method : methods) { Class<?>[] types = method.getParameterTypes(); int length = types.length; boolean found = false; if (parameterTypes.length == length) { found = true; for (int i = 0; i < length; i++) { Class a = parameterTypes[i]; Class b = types[i]; if (!a.equals(b)) found = false; } } if (found) return index; else index++; } return -1; } public int getIndex(Signature signatureA) { Method[] methods = type.getMethods(); int index = 0; for (Method method : methods) { Signature signatureB = new Signature(method.getName(), Type.getReturnType(method), Type.getArgumentTypes(method)); if(signatureA.equals(signatureB)) return index; else index++; } return -1; } /** * Invoke the method with the specified index. * * @param index the method index * @param obj the object the underlying method is invoked from * @param args the arguments used for the method call * @throws java.lang.reflect.InvocationTargetException * if the underlying method throws an exception * */ public Object invoke(int index, Object obj, Object[] args) throws InvocationTargetException { Method method = type.getMethods()[index]; try { return method.invoke(obj, args); } catch (IllegalAccessException e) { throw new InvocationTargetException(e); } } /** * Create a new instance using the specified constructor index and arguments. * * @param index the constructor index * @param args the arguments passed to the constructor * @throws java.lang.reflect.InvocationTargetException * if the constructor throws an exception * */ public Object newInstance(int index, Object[] args) throws InvocationTargetException { try { return type.getConstructors()[index].newInstance(args); } catch (InstantiationException e) { throw new InvocationTargetException(e); } catch (IllegalAccessException e) { throw new InvocationTargetException(e); } } /** * Returns the maximum method index for this class. */ public int getMaxIndex() { return type.getMethods().length; } protected static String getSignatureWithoutReturnType(String name, Class[] parameterTypes) { StringBuffer sb = new StringBuffer(); sb.append(name); sb.append('('); for (int i = 0; i < parameterTypes.length; i++) { sb.append(Type.getDescriptor(parameterTypes[i])); } sb.append(')'); return sb.toString(); } }