001: /*
002: * Copyright 2003,2004 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package net.sf.cglib.reflect;
017:
018: import net.sf.cglib.core.*;
019: import java.lang.reflect.Constructor;
020: import java.lang.reflect.InvocationTargetException;
021: import java.lang.reflect.Method;
022: import org.objectweb.asm.ClassVisitor;
023: import org.objectweb.asm.Type;
024:
025: abstract public class FastClass {
026: private Class type;
027:
028: protected FastClass() {
029: throw new Error(
030: "Using the FastClass empty constructor--please report to the cglib-devel mailing list");
031: }
032:
033: protected FastClass(Class type) {
034: this .type = type;
035: }
036:
037: public static FastClass create(Class type) {
038:
039: return create(type.getClassLoader(), type);
040:
041: }
042:
043: public static FastClass create(ClassLoader loader, Class type) {
044: Generator gen = new Generator();
045: gen.setType(type);
046: gen.setClassLoader(loader);
047: return gen.create();
048: }
049:
050: public static class Generator extends AbstractClassGenerator {
051: private static final Source SOURCE = new Source(FastClass.class
052: .getName());
053: private Class type;
054:
055: public Generator() {
056: super (SOURCE);
057: }
058:
059: public void setType(Class type) {
060: this .type = type;
061: }
062:
063: public FastClass create() {
064: setNamePrefix(type.getName());
065: return (FastClass) super .create(type.getName());
066: }
067:
068: protected ClassLoader getDefaultClassLoader() {
069: return type.getClassLoader();
070: }
071:
072: public void generateClass(ClassVisitor v) throws Exception {
073: new FastClassEmitter(v, getClassName(), type);
074: }
075:
076: protected Object firstInstance(Class type) {
077: return ReflectUtils.newInstance(type,
078: new Class[] { Class.class },
079: new Object[] { this .type });
080: }
081:
082: protected Object nextInstance(Object instance) {
083: return instance;
084: }
085: }
086:
087: public Object invoke(String name, Class[] parameterTypes,
088: Object obj, Object[] args) throws InvocationTargetException {
089: return invoke(getIndex(name, parameterTypes), obj, args);
090: }
091:
092: public Object newInstance() throws InvocationTargetException {
093: return newInstance(getIndex(Constants.EMPTY_CLASS_ARRAY), null);
094: }
095:
096: public Object newInstance(Class[] parameterTypes, Object[] args)
097: throws InvocationTargetException {
098: return newInstance(getIndex(parameterTypes), args);
099: }
100:
101: public FastMethod getMethod(Method method) {
102: return new FastMethod(this , method);
103: }
104:
105: public FastConstructor getConstructor(Constructor constructor) {
106: return new FastConstructor(this , constructor);
107: }
108:
109: public FastMethod getMethod(String name, Class[] parameterTypes) {
110: try {
111: return getMethod(type.getMethod(name, parameterTypes));
112: } catch (NoSuchMethodException e) {
113: throw new NoSuchMethodError(e.getMessage());
114: }
115: }
116:
117: public FastConstructor getConstructor(Class[] parameterTypes) {
118: try {
119: return getConstructor(type.getConstructor(parameterTypes));
120: } catch (NoSuchMethodException e) {
121: throw new NoSuchMethodError(e.getMessage());
122: }
123: }
124:
125: public String getName() {
126: return type.getName();
127: }
128:
129: public Class getJavaClass() {
130: return type;
131: }
132:
133: public String toString() {
134: return type.toString();
135: }
136:
137: public int hashCode() {
138: return type.hashCode();
139: }
140:
141: public boolean equals(Object o) {
142: if (o == null || !(o instanceof FastClass)) {
143: return false;
144: }
145: return type.equals(((FastClass) o).type);
146: }
147:
148: /**
149: * Return the index of the matching method. The index may be used
150: * later to invoke the method with less overhead. If more than one
151: * method matches (i.e. they differ by return type only), one is
152: * chosen arbitrarily.
153: * @see #invoke(int, Object, Object[])
154: * @param name the method name
155: * @param parameterTypes the parameter array
156: * @return the index, or <code>-1</code> if none is found.
157: */
158: abstract public int getIndex(String name, Class[] parameterTypes);
159:
160: /**
161: * Return the index of the matching constructor. The index may be used
162: * later to create a new instance with less overhead.
163: * @see #newInstance(int, Object[])
164: * @param parameterTypes the parameter array
165: * @return the constructor index, or <code>-1</code> if none is found.
166: */
167: abstract public int getIndex(Class[] parameterTypes);
168:
169: /**
170: * Invoke the method with the specified index.
171: * @see getIndex(name, Class[])
172: * @param index the method index
173: * @param obj the object the underlying method is invoked from
174: * @param args the arguments used for the method call
175: * @throws java.lang.reflect.InvocationTargetException if the underlying method throws an exception
176: */
177: abstract public Object invoke(int index, Object obj, Object[] args)
178: throws InvocationTargetException;
179:
180: /**
181: * Create a new instance using the specified constructor index and arguments.
182: * @see getIndex(Class[])
183: * @param index the constructor index
184: * @param args the arguments passed to the constructor
185: * @throws java.lang.reflect.InvocationTargetException if the constructor throws an exception
186: */
187: abstract public Object newInstance(int index, Object[] args)
188: throws InvocationTargetException;
189:
190: abstract public int getIndex(Signature sig);
191:
192: /**
193: * Returns the maximum method index for this class.
194: */
195: abstract public int getMaxIndex();
196:
197: protected static String getSignatureWithoutReturnType(String name,
198: Class[] parameterTypes) {
199: StringBuffer sb = new StringBuffer();
200: sb.append(name);
201: sb.append('(');
202: for (int i = 0; i < parameterTypes.length; i++) {
203: sb.append(Type.getDescriptor(parameterTypes[i]));
204: }
205: sb.append(')');
206: return sb.toString();
207: }
208: }
|