001: /*
002: * Copyright 2003 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 java.lang.reflect.*;
019: import net.sf.cglib.core.*;
020: import org.objectweb.asm.ClassVisitor;
021: import org.objectweb.asm.Type;
022:
023: /**
024: * @author Chris Nokleberg
025: * @version $Id: ConstructorDelegate.java,v 1.20 2006/03/05 02:43:19 herbyderby Exp $
026: */
027: abstract public class ConstructorDelegate {
028: private static final ConstructorKey KEY_FACTORY = (ConstructorKey) KeyFactory
029: .create(ConstructorKey.class, KeyFactory.CLASS_BY_NAME);
030:
031: interface ConstructorKey {
032: public Object newInstance(String declaring, String iface);
033: }
034:
035: protected ConstructorDelegate() {
036: }
037:
038: public static ConstructorDelegate create(Class targetClass,
039: Class iface) {
040: Generator gen = new Generator();
041: gen.setTargetClass(targetClass);
042: gen.setInterface(iface);
043: return gen.create();
044: }
045:
046: public static class Generator extends AbstractClassGenerator {
047: private static final Source SOURCE = new Source(
048: ConstructorDelegate.class.getName());
049: private static final Type CONSTRUCTOR_DELEGATE = TypeUtils
050: .parseType("net.sf.cglib.reflect.ConstructorDelegate");
051:
052: private Class iface;
053: private Class targetClass;
054:
055: public Generator() {
056: super (SOURCE);
057: }
058:
059: public void setInterface(Class iface) {
060: this .iface = iface;
061: }
062:
063: public void setTargetClass(Class targetClass) {
064: this .targetClass = targetClass;
065: }
066:
067: public ConstructorDelegate create() {
068: setNamePrefix(targetClass.getName());
069: Object key = KEY_FACTORY.newInstance(iface.getName(),
070: targetClass.getName());
071: return (ConstructorDelegate) super .create(key);
072: }
073:
074: protected ClassLoader getDefaultClassLoader() {
075: return targetClass.getClassLoader();
076: }
077:
078: public void generateClass(ClassVisitor v) {
079: setNamePrefix(targetClass.getName());
080:
081: final Method newInstance = ReflectUtils
082: .findNewInstance(iface);
083: if (!newInstance.getReturnType().isAssignableFrom(
084: targetClass)) {
085: throw new IllegalArgumentException(
086: "incompatible return type");
087: }
088: final Constructor constructor;
089: try {
090: constructor = targetClass
091: .getDeclaredConstructor(newInstance
092: .getParameterTypes());
093: } catch (NoSuchMethodException e) {
094: throw new IllegalArgumentException(
095: "interface does not match any known constructor");
096: }
097:
098: ClassEmitter ce = new ClassEmitter(v);
099: ce.begin_class(Constants.V1_2, Constants.ACC_PUBLIC,
100: getClassName(), CONSTRUCTOR_DELEGATE,
101: new Type[] { Type.getType(iface) },
102: Constants.SOURCE_FILE);
103: Type declaring = Type.getType(constructor
104: .getDeclaringClass());
105: EmitUtils.null_constructor(ce);
106: CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC,
107: ReflectUtils.getSignature(newInstance),
108: ReflectUtils.getExceptionTypes(newInstance));
109: e.new_instance(declaring);
110: e.dup();
111: e.load_args();
112: e.invoke_constructor(declaring, ReflectUtils
113: .getSignature(constructor));
114: e.return_value();
115: e.end_method();
116: ce.end_class();
117: }
118:
119: protected Object firstInstance(Class type) {
120: return ReflectUtils.newInstance(type);
121: }
122:
123: protected Object nextInstance(Object instance) {
124: return instance;
125: }
126: }
127: }
|