BeanGenerator.java revision 674060f01e9090cd21b3c5656cc3204912ad17a6
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 */ 16package org.mockito.cglib.beans; 17 18import java.beans.PropertyDescriptor; 19import java.util.*; 20 21import org.mockito.asm.ClassVisitor; 22import org.mockito.asm.Type; 23import org.mockito.cglib.core.*; 24 25/** 26 * @author Juozas Baliuka, Chris Nokleberg 27 */ 28public class BeanGenerator extends AbstractClassGenerator 29{ 30 private static final Source SOURCE = new Source(BeanGenerator.class.getName()); 31 private static final BeanGeneratorKey KEY_FACTORY = 32 (BeanGeneratorKey)KeyFactory.create(BeanGeneratorKey.class); 33 34 interface BeanGeneratorKey { 35 public Object newInstance(String superclass, Map props); 36 } 37 38 private Class superclass; 39 private Map props = new HashMap(); 40 private boolean classOnly; 41 42 public BeanGenerator() { 43 super(SOURCE); 44 } 45 46 /** 47 * Set the class which the generated class will extend. The class 48 * must not be declared as final, and must have a non-private 49 * no-argument constructor. 50 * @param superclass class to extend, or null to extend Object 51 */ 52 public void setSuperclass(Class superclass) { 53 if (superclass != null && superclass.equals(Object.class)) { 54 superclass = null; 55 } 56 this.superclass = superclass; 57 } 58 59 public void addProperty(String name, Class type) { 60 if (props.containsKey(name)) { 61 throw new IllegalArgumentException("Duplicate property name \"" + name + "\""); 62 } 63 props.put(name, Type.getType(type)); 64 } 65 66 protected ClassLoader getDefaultClassLoader() { 67 if (superclass != null) { 68 return superclass.getClassLoader(); 69 } else { 70 return null; 71 } 72 } 73 74 public Object create() { 75 classOnly = false; 76 return createHelper(); 77 } 78 79 public Object createClass() { 80 classOnly = true; 81 return createHelper(); 82 } 83 84 private Object createHelper() { 85 if (superclass != null) { 86 setNamePrefix(superclass.getName()); 87 } 88 String superName = (superclass != null) ? superclass.getName() : "java.lang.Object"; 89 Object key = KEY_FACTORY.newInstance(superName, props); 90 return super.create(key); 91 } 92 93 public void generateClass(ClassVisitor v) throws Exception { 94 int size = props.size(); 95 String[] names = (String[])props.keySet().toArray(new String[size]); 96 Type[] types = new Type[size]; 97 for (int i = 0; i < size; i++) { 98 types[i] = (Type)props.get(names[i]); 99 } 100 ClassEmitter ce = new ClassEmitter(v); 101 ce.begin_class(Constants.V1_2, 102 Constants.ACC_PUBLIC, 103 getClassName(), 104 superclass != null ? Type.getType(superclass) : Constants.TYPE_OBJECT, 105 null, 106 null); 107 EmitUtils.null_constructor(ce); 108 EmitUtils.add_properties(ce, names, types); 109 ce.end_class(); 110 } 111 112 protected Object firstInstance(Class type) { 113 if (classOnly) { 114 return type; 115 } else { 116 return ReflectUtils.newInstance(type); 117 } 118 } 119 120 protected Object nextInstance(Object instance) { 121 Class protoclass = (instance instanceof Class) ? (Class)instance : instance.getClass(); 122 if (classOnly) { 123 return protoclass; 124 } else { 125 return ReflectUtils.newInstance(protoclass); 126 } 127 } 128 129 public static void addProperties(BeanGenerator gen, Map props) { 130 for (Iterator it = props.keySet().iterator(); it.hasNext();) { 131 String name = (String)it.next(); 132 gen.addProperty(name, (Class)props.get(name)); 133 } 134 } 135 136 public static void addProperties(BeanGenerator gen, Class type) { 137 addProperties(gen, ReflectUtils.getBeanProperties(type)); 138 } 139 140 public static void addProperties(BeanGenerator gen, PropertyDescriptor[] descriptors) { 141 for (int i = 0; i < descriptors.length; i++) { 142 gen.addProperty(descriptors[i].getName(), descriptors[i].getPropertyType()); 143 } 144 } 145} 146