View Javadoc
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; 55 56 import java.lang.reflect.Constructor; 57 import java.lang.reflect.Modifier; 58 import java.util.*; 59 import net.sf.cglib.core.*; 60 import org.objectweb.asm.ClassVisitor; 61 62 /*** 63 * <code>Mixin</code> allows 64 * multiple objects to be combined into a single larger object. The 65 * methods in the generated object simply call the original methods in the 66 * underlying "delegate" objects. 67 * @author Chris Nokleberg 68 * @version $Id: Mixin.java,v 1.14 2003/10/03 23:09:29 herbyderby Exp $ 69 */ 70 abstract public class Mixin { 71 private static final MixinKey KEY_FACTORY = 72 (MixinKey)KeyFactory.create(MixinKey.class, KeyFactory.CLASS_BY_NAME); 73 private static final Map ROUTE_CACHE = Collections.synchronizedMap(new HashMap()); 74 75 interface MixinKey { 76 public Object newInstance(Class[] classes, int[] route); 77 } 78 79 abstract public Mixin newInstance(Object[] delegates); 80 81 public static Mixin create(Object[] delegates) { 82 Generator gen = new Generator(); 83 gen.setDelegates(delegates); 84 return gen.create(); 85 } 86 87 public static Mixin create(Class[] interfaces, Object[] delegates) { 88 Generator gen = new Generator(); 89 gen.setClasses(interfaces); 90 gen.setDelegates(delegates); 91 return gen.create(); 92 } 93 94 public static Mixin createBean(Object[] beans) { 95 Generator gen = new Generator(); 96 gen.setAsBeans(true); 97 gen.setDelegates(beans); 98 return gen.create(); 99 } 100 101 public static class Generator extends AbstractClassGenerator { 102 private static final Source SOURCE = new Source(Mixin.class.getName()); 103 104 private Class[] classes; 105 private Object[] delegates; 106 private int[] route; 107 private boolean asBeans; 108 109 public Generator() { 110 super(SOURCE); 111 } 112 113 protected ClassLoader getDefaultClassLoader() { 114 return delegates[0].getClass().getClassLoader(); // is this right? 115 } 116 117 public void setAsBeans(boolean asBeans) { 118 this.asBeans = asBeans; 119 } 120 121 public void setClasses(Class[] classes) { 122 this.classes = classes; 123 } 124 125 public void setDelegates(Object[] delegates) { 126 this.delegates = delegates; 127 } 128 129 public void setRoute(int[] route) { 130 this.route = route; 131 } 132 133 public Mixin create() { 134 if (classes == null) { 135 if (asBeans) { 136 classes = ReflectUtils.getClasses(delegates); 137 route = null; 138 } else { 139 Route r = route(delegates); 140 classes = r.classes; 141 route = r.route; 142 } 143 } 144 setNamePrefix(classes[ReflectUtils.findPackageProtected(classes)].getName()); 145 return (Mixin)super.create(KEY_FACTORY.newInstance(classes, route)); 146 } 147 148 public void generateClass(ClassVisitor v) { 149 if (asBeans) { 150 new MixinBeanEmitter(v, getClassName(), classes); 151 } else { 152 new MixinEmitter(v, getClassName(), classes, route); 153 } 154 } 155 156 protected Object firstInstance(Class type) { 157 return ((Mixin)ReflectUtils.newInstance(type)).newInstance(delegates); 158 } 159 160 protected Object nextInstance(Object instance) { 161 return ((Mixin)instance).newInstance(delegates); 162 } 163 } 164 165 public static Class[] getClasses(Object[] delegates) { 166 return (Class[])route(delegates).classes.clone(); 167 } 168 169 public static int[] getRoute(Object[] delegates) { 170 return (int[])route(delegates).route.clone(); 171 } 172 173 private static Route route(Object[] delegates) { 174 Object key = ClassesKey.create(delegates); 175 Route route = (Route)ROUTE_CACHE.get(key); 176 if (route == null) { 177 ROUTE_CACHE.put(key, route = new Route(delegates)); 178 } 179 return route; 180 } 181 182 private static class Route 183 { 184 private Class[] classes; 185 private int[] route; 186 187 Route(Object[] delegates) { 188 Map map = new HashMap(); 189 ArrayList collect = new ArrayList(); 190 for (int i = 0; i < delegates.length; i++) { 191 Class delegate = delegates[i].getClass(); 192 collect.clear(); 193 collectAllInterfaces(delegate, collect); 194 for (Iterator it = collect.iterator(); it.hasNext();) { 195 Class iface = (Class)it.next(); 196 if (!map.containsKey(iface)) { 197 map.put(iface, new Integer(i)); 198 } 199 } 200 } 201 classes = new Class[map.size()]; 202 route = new int[map.size()]; 203 int index = 0; 204 for (Iterator it = map.keySet().iterator(); it.hasNext();) { 205 Class key = (Class)it.next(); 206 classes[index] = key; 207 route[index] = ((Integer)map.get(key)).intValue(); 208 index++; 209 } 210 } 211 } 212 213 private static void collectAllInterfaces(Class type, List list) { 214 if (!type.equals(Object.class)) { 215 list.addAll(Arrays.asList(type.getInterfaces())); 216 collectAllInterfaces(type.getSuperclass(), list); 217 } 218 } 219 }

This page was automatically generated by Maven