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 net.sf.cglib.reflect;
55
56 import java.lang.reflect.*;
57 import java.util.*;
58 import net.sf.cglib.core.*;
59 import org.objectweb.asm.ClassVisitor;
60 import org.objectweb.asm.CodeVisitor;
61 import org.objectweb.asm.Type;
62
63 abstract public class MulticastDelegate implements Cloneable {
64 protected Object[] 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 target);
74
75 protected MulticastDelegate addHelper(Object target) {
76 MulticastDelegate copy = newInstance();
77 copy.targets = new Object[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 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[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 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("net.sf.cglib.reflect.MulticastDelegate newInstance()");
108 private static final Signature ADD_DELEGATE =
109 TypeUtils.parseSignature("net.sf.cglib.reflect.MulticastDelegate add(Object)");
110 private static final Signature ADD_HELPER =
111 TypeUtils.parseSignature("net.sf.cglib.reflect.MulticastDelegate addHelper(Object)");
112 private static final Type MULTICAST_DELEGATE =
113 TypeUtils.parseType("net.sf.cglib.reflect.MulticastDelegate");
114
115 private Class iface;
116
117 public Generator() {
118 super(SOURCE);
119 }
120
121 protected ClassLoader getDefaultClassLoader() {
122 return iface.getClassLoader();
123 }
124
125 public void setInterface(Class 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 firstInstance(Class 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 nextInstance(Object instance) {
207 return ((MulticastDelegate)instance).newInstance();
208 }
209 }
210 }
This page was automatically generated by Maven