KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > cglib > reflect > ConstructorDelegate


1 /*
2  * Copyright 2003 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package net.sf.cglib.reflect;
17
18 import java.lang.reflect.*;
19 import net.sf.cglib.core.*;
20 import org.objectweb.asm.ClassVisitor;
21 import org.objectweb.asm.Type;
22
23 /**
24  * @author Chris Nokleberg
25  * @version $Id: ConstructorDelegate.java,v 1.20 2006/03/05 02:43:19 herbyderby Exp $
26  */

27 abstract public class ConstructorDelegate {
28     private static final ConstructorKey KEY_FACTORY =
29       (ConstructorKey)KeyFactory.create(ConstructorKey.class, KeyFactory.CLASS_BY_NAME);
30     
31     interface ConstructorKey {
32         public Object JavaDoc newInstance(String JavaDoc declaring, String JavaDoc iface);
33     }
34
35     protected ConstructorDelegate() {
36     }
37
38     public static ConstructorDelegate create(Class JavaDoc targetClass, Class JavaDoc iface) {
39         Generator gen = new Generator();
40         gen.setTargetClass(targetClass);
41         gen.setInterface(iface);
42         return gen.create();
43     }
44
45     public static class Generator extends AbstractClassGenerator {
46         private static final Source SOURCE = new Source(ConstructorDelegate.class.getName());
47         private static final Type CONSTRUCTOR_DELEGATE =
48           TypeUtils.parseType("net.sf.cglib.reflect.ConstructorDelegate");
49
50         private Class JavaDoc iface;
51         private Class JavaDoc targetClass;
52
53         public Generator() {
54             super(SOURCE);
55         }
56
57         public void setInterface(Class JavaDoc iface) {
58             this.iface = iface;
59         }
60
61         public void setTargetClass(Class JavaDoc targetClass) {
62             this.targetClass = targetClass;
63         }
64
65         public ConstructorDelegate create() {
66             setNamePrefix(targetClass.getName());
67             Object JavaDoc key = KEY_FACTORY.newInstance(iface.getName(), targetClass.getName());
68             return (ConstructorDelegate)super.create(key);
69         }
70
71         protected ClassLoader JavaDoc getDefaultClassLoader() {
72             return targetClass.getClassLoader();
73         }
74
75         public void generateClass(ClassVisitor v) {
76             setNamePrefix(targetClass.getName());
77
78             final Method newInstance = ReflectUtils.findNewInstance(iface);
79             if (!newInstance.getReturnType().isAssignableFrom(targetClass)) {
80                 throw new IllegalArgumentException JavaDoc("incompatible return type");
81             }
82             final Constructor constructor;
83             try {
84                 constructor = targetClass.getDeclaredConstructor(newInstance.getParameterTypes());
85             } catch (NoSuchMethodException JavaDoc e) {
86                 throw new IllegalArgumentException JavaDoc("interface does not match any known constructor");
87             }
88
89             ClassEmitter ce = new ClassEmitter(v);
90             ce.begin_class(Constants.V1_2,
91                            Constants.ACC_PUBLIC,
92                            getClassName(),
93                            CONSTRUCTOR_DELEGATE,
94                            new Type[]{ Type.getType(iface) },
95                            Constants.SOURCE_FILE);
96             Type declaring = Type.getType(constructor.getDeclaringClass());
97             EmitUtils.null_constructor(ce);
98             CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC,
99                                             ReflectUtils.getSignature(newInstance),
100                                             ReflectUtils.getExceptionTypes(newInstance));
101             e.new_instance(declaring);
102             e.dup();
103             e.load_args();
104             e.invoke_constructor(declaring, ReflectUtils.getSignature(constructor));
105             e.return_value();
106             e.end_method();
107             ce.end_class();
108         }
109
110         protected Object JavaDoc firstInstance(Class JavaDoc type) {
111             return ReflectUtils.newInstance(type);
112         }
113
114         protected Object JavaDoc nextInstance(Object JavaDoc instance) {
115             return instance;
116         }
117     }
118 }
119
Popular Tags