KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > logicalcobwebs > cglib > reflect > MulticastDelegate


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 2002 The Apache Software Foundation. All rights
5  * reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in
16  * the documentation and/or other materials provided with the
17  * distribution.
18  *
19  * 3. The end-user documentation included with the redistribution,
20  * if any, must include the following acknowledgment:
21  * "This product includes software developed by the
22  * Apache Software Foundation (http://www.apache.org/)."
23  * Alternately, this acknowledgment may appear in the software itself,
24  * if and wherever such third-party acknowledgments normally appear.
25  *
26  * 4. The names "Apache" and "Apache Software Foundation" must
27  * not be used to endorse or promote products derived from this
28  * software without prior written permission. For written
29  * permission, please contact apache@apache.org.
30  *
31  * 5. Products derived from this software may not be called "Apache",
32  * nor may "Apache" appear in their name, without prior written
33  * permission of the Apache Software Foundation.
34  *
35  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46  * SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Apache Software Foundation. For more
51  * information on the Apache Software Foundation, please see
52  * <http://www.apache.org/>.
53  */

54 package org.logicalcobwebs.cglib.reflect;
55
56 import java.lang.reflect.*;
57 import java.util.*;
58 import org.logicalcobwebs.cglib.core.*;
59 import org.logicalcobwebs.asm.ClassVisitor;
60 import org.logicalcobwebs.asm.CodeVisitor;
61 import org.logicalcobwebs.asm.Type;
62
63 abstract public class MulticastDelegate implements Cloneable JavaDoc {
64     protected Object JavaDoc[] targets = {};
65
66     protected MulticastDelegate() {
67     }
68
69     public List getTargets() {
70         return new ArrayList(Arrays.asList(targets));
71     }
72
73     abstract public MulticastDelegate add(Object JavaDoc target);
74
75     protected MulticastDelegate addHelper(Object JavaDoc target) {
76         MulticastDelegate copy = newInstance();
77         copy.targets = new Object JavaDoc[targets.length + 1];
78         System.arraycopy(targets, 0, copy.targets, 0, targets.length);
79         copy.targets[targets.length] = target;
80         return copy;
81     }
82
83     public MulticastDelegate remove(Object JavaDoc target) {
84         for (int i = targets.length - 1; i >= 0; i--) {
85             if (targets[i].equals(target)) {
86                 MulticastDelegate copy = newInstance();
87                 copy.targets = new Object JavaDoc[targets.length - 1];
88                 System.arraycopy(targets, 0, copy.targets, 0, i);
89                 System.arraycopy(targets, i + 1, copy.targets, i, targets.length - i - 1);
90                 return copy;
91             }
92         }
93         return this;
94     }
95
96     abstract public MulticastDelegate newInstance();
97
98     public static MulticastDelegate create(Class JavaDoc iface) {
99         Generator gen = new Generator();
100         gen.setInterface(iface);
101         return gen.create();
102     }
103
104     public static class Generator extends AbstractClassGenerator {
105         private static final Source SOURCE = new Source(MulticastDelegate.class.getName());
106         private static final Signature NEW_INSTANCE =
107           TypeUtils.parseSignature("org.logicalcobwebs.cglib.reflect.MulticastDelegate newInstance()");
108         private static final Signature ADD_DELEGATE =
109           TypeUtils.parseSignature("org.logicalcobwebs.cglib.reflect.MulticastDelegate add(Object)");
110         private static final Signature ADD_HELPER =
111           TypeUtils.parseSignature("org.logicalcobwebs.cglib.reflect.MulticastDelegate addHelper(Object)");
112         private static final Type MULTICAST_DELEGATE =
113           TypeUtils.parseType("org.logicalcobwebs.cglib.reflect.MulticastDelegate");
114
115         private Class JavaDoc iface;
116
117         public Generator() {
118             super(SOURCE);
119         }
120
121         protected ClassLoader JavaDoc getDefaultClassLoader() {
122             return iface.getClassLoader();
123         }
124
125         public void setInterface(Class JavaDoc iface) {
126             this.iface = iface;
127         }
128
129         public MulticastDelegate create() {
130             setNamePrefix(MulticastDelegate.class.getName());
131             return (MulticastDelegate)super.create(iface.getName());
132         }
133
134         public void generateClass(ClassVisitor cv) {
135             final Method method = ReflectUtils.findInterfaceMethod(iface);
136             
137             ClassEmitter ce = new ClassEmitter(cv);
138             ce.begin_class(Constants.ACC_PUBLIC,
139                            getClassName(),
140                            MULTICAST_DELEGATE,
141                            new Type[]{ Type.getType(iface) },
142                            Constants.SOURCE_FILE);
143             EmitUtils.null_constructor(ce);
144
145             // generate proxied method
146
emitProxy(ce, method);
147
148             // newInstance
149
CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, NEW_INSTANCE, null, null);
150             e.new_instance_this();
151             e.dup();
152             e.invoke_constructor_this();
153             e.return_value();
154             e.end_method();
155
156             // add
157
e = ce.begin_method(Constants.ACC_PUBLIC, ADD_DELEGATE, null, null);
158             e.load_this();
159             e.load_arg(0);
160             e.checkcast(Type.getType(iface));
161             e.invoke_virtual_this(ADD_HELPER);
162             e.return_value();
163             e.end_method();
164
165             ce.end_class();
166         }
167
168         private void emitProxy(ClassEmitter ce, final Method method) {
169             final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC,
170                                                   ReflectUtils.getSignature(method),
171                                                   ReflectUtils.getExceptionTypes(method),
172                                                   null);
173             Type returnType = e.getReturnType();
174             final boolean returns = returnType != Type.VOID_TYPE;
175             Local result = null;
176             if (returns) {
177                 result = e.make_local(returnType);
178                 e.zero_or_null(returnType);
179                 e.store_local(result);
180             }
181             e.load_this();
182             e.super_getfield("targets", Constants.TYPE_OBJECT_ARRAY);
183             final Local result2 = result;
184             EmitUtils.process_array(e, Constants.TYPE_OBJECT_ARRAY, new ProcessArrayCallback() {
185                 public void processElement(Type type) {
186                     e.checkcast(Type.getType(iface));
187                     e.load_args();
188                     e.invoke(method);
189                     if (returns) {
190                         e.store_local(result2);
191                     }
192                 }
193             });
194             if (returns) {
195                 e.load_local(result);
196             }
197             e.return_value();
198             e.end_method();
199         }
200
201         protected Object JavaDoc firstInstance(Class JavaDoc type) {
202             // make a new instance in case first object is used with a long list of targets
203
return ((MulticastDelegate)ReflectUtils.newInstance(type)).newInstance();
204         }
205
206         protected Object JavaDoc nextInstance(Object JavaDoc instance) {
207             return ((MulticastDelegate)instance).newInstance();
208         }
209     }
210 }
211
Popular Tags