KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * Copyright 2003,2004 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 java.util.*;
20 import net.sf.cglib.core.*;
21 import org.objectweb.asm.ClassVisitor;
22 import org.objectweb.asm.MethodVisitor;
23 import org.objectweb.asm.Type;
24
25 abstract public class MulticastDelegate implements Cloneable JavaDoc {
26     protected Object JavaDoc[] targets = {};
27
28     protected MulticastDelegate() {
29     }
30
31     public List getTargets() {
32         return new ArrayList(Arrays.asList(targets));
33     }
34
35     abstract public MulticastDelegate add(Object JavaDoc target);
36
37     protected MulticastDelegate addHelper(Object JavaDoc target) {
38         MulticastDelegate copy = newInstance();
39         copy.targets = new Object JavaDoc[targets.length + 1];
40         System.arraycopy(targets, 0, copy.targets, 0, targets.length);
41         copy.targets[targets.length] = target;
42         return copy;
43     }
44
45     public MulticastDelegate remove(Object JavaDoc target) {
46         for (int i = targets.length - 1; i >= 0; i--) {
47             if (targets[i].equals(target)) {
48                 MulticastDelegate copy = newInstance();
49                 copy.targets = new Object JavaDoc[targets.length - 1];
50                 System.arraycopy(targets, 0, copy.targets, 0, i);
51                 System.arraycopy(targets, i + 1, copy.targets, i, targets.length - i - 1);
52                 return copy;
53             }
54         }
55         return this;
56     }
57
58     abstract public MulticastDelegate newInstance();
59
60     public static MulticastDelegate create(Class JavaDoc iface) {
61         Generator gen = new Generator();
62         gen.setInterface(iface);
63         return gen.create();
64     }
65
66     public static class Generator extends AbstractClassGenerator {
67         private static final Source SOURCE = new Source(MulticastDelegate.class.getName());
68         private static final Type MULTICAST_DELEGATE =
69           TypeUtils.parseType("net.sf.cglib.reflect.MulticastDelegate");
70         private static final Signature NEW_INSTANCE =
71           new Signature("newInstance", MULTICAST_DELEGATE, new Type[0]);
72         private static final Signature ADD_DELEGATE =
73           new Signature("add", MULTICAST_DELEGATE, new Type[]{ Constants.TYPE_OBJECT });
74         private static final Signature ADD_HELPER =
75           new Signature("addHelper", MULTICAST_DELEGATE, new Type[]{ Constants.TYPE_OBJECT });
76
77         private Class JavaDoc iface;
78
79         public Generator() {
80             super(SOURCE);
81         }
82
83         protected ClassLoader JavaDoc getDefaultClassLoader() {
84             return iface.getClassLoader();
85         }
86
87         public void setInterface(Class JavaDoc iface) {
88             this.iface = iface;
89         }
90
91         public MulticastDelegate create() {
92             setNamePrefix(MulticastDelegate.class.getName());
93             return (MulticastDelegate)super.create(iface.getName());
94         }
95
96         public void generateClass(ClassVisitor cv) {
97             final MethodInfo method = ReflectUtils.getMethodInfo(ReflectUtils.findInterfaceMethod(iface));
98             
99             ClassEmitter ce = new ClassEmitter(cv);
100             ce.begin_class(Constants.V1_2,
101                            Constants.ACC_PUBLIC,
102                            getClassName(),
103                            MULTICAST_DELEGATE,
104                            new Type[]{ Type.getType(iface) },
105                            Constants.SOURCE_FILE);
106             EmitUtils.null_constructor(ce);
107
108             // generate proxied method
109
emitProxy(ce, method);
110
111             // newInstance
112
CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, NEW_INSTANCE, null);
113             e.new_instance_this();
114             e.dup();
115             e.invoke_constructor_this();
116             e.return_value();
117             e.end_method();
118
119             // add
120
e = ce.begin_method(Constants.ACC_PUBLIC, ADD_DELEGATE, null);
121             e.load_this();
122             e.load_arg(0);
123             e.checkcast(Type.getType(iface));
124             e.invoke_virtual_this(ADD_HELPER);
125             e.return_value();
126             e.end_method();
127
128             ce.end_class();
129         }
130
131         private void emitProxy(ClassEmitter ce, final MethodInfo method) {
132             final CodeEmitter e = EmitUtils.begin_method(ce, method, Constants.ACC_PUBLIC);
133             Type returnType = method.getSignature().getReturnType();
134             final boolean returns = returnType != Type.VOID_TYPE;
135             Local result = null;
136             if (returns) {
137                 result = e.make_local(returnType);
138                 e.zero_or_null(returnType);
139                 e.store_local(result);
140             }
141             e.load_this();
142             e.super_getfield("targets", Constants.TYPE_OBJECT_ARRAY);
143             final Local result2 = result;
144             EmitUtils.process_array(e, Constants.TYPE_OBJECT_ARRAY, new ProcessArrayCallback() {
145                 public void processElement(Type type) {
146                     e.checkcast(Type.getType(iface));
147                     e.load_args();
148                     e.invoke(method);
149                     if (returns) {
150                         e.store_local(result2);
151                     }
152                 }
153             });
154             if (returns) {
155                 e.load_local(result);
156             }
157             e.return_value();
158             e.end_method();
159         }
160
161         protected Object JavaDoc firstInstance(Class JavaDoc type) {
162             // make a new instance in case first object is used with a long list of targets
163
return ((MulticastDelegate)ReflectUtils.newInstance(type)).newInstance();
164         }
165
166         protected Object JavaDoc nextInstance(Object JavaDoc instance) {
167             return ((MulticastDelegate)instance).newInstance();
168         }
169     }
170 }
171
Popular Tags