001: /*
002: * Copyright 2003 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package net.sf.cglib.beans;
017:
018: import java.beans.PropertyDescriptor;
019: import java.util.*;
020: import net.sf.cglib.core.*;
021: import org.objectweb.asm.ClassVisitor;
022: import org.objectweb.asm.Type;
023:
024: /**
025: * @author Juozas Baliuka, Chris Nokleberg
026: */
027: public class BeanGenerator extends AbstractClassGenerator {
028: private static final Source SOURCE = new Source(BeanGenerator.class
029: .getName());
030: private static final BeanGeneratorKey KEY_FACTORY = (BeanGeneratorKey) KeyFactory
031: .create(BeanGeneratorKey.class);
032:
033: interface BeanGeneratorKey {
034: public Object newInstance(String super class, Map props);
035: }
036:
037: private Class super class;
038: private Map props = new HashMap();
039: private boolean classOnly;
040:
041: public BeanGenerator() {
042: super (SOURCE);
043: }
044:
045: /**
046: * Set the class which the generated class will extend. The class
047: * must not be declared as final, and must have a non-private
048: * no-argument constructor.
049: * @param superclass class to extend, or null to extend Object
050: */
051: public void setSuperclass(Class super class) {
052: if (super class != null && super class.equals(Object.class)) {
053: super class = null;
054: }
055: this .super class = super class;
056: }
057:
058: public void addProperty(String name, Class type) {
059: if (props.containsKey(name)) {
060: throw new IllegalArgumentException(
061: "Duplicate property name \"" + name + "\"");
062: }
063: props.put(name, Type.getType(type));
064: }
065:
066: protected ClassLoader getDefaultClassLoader() {
067: if (super class != null) {
068: return super class.getClassLoader();
069: } else {
070: return null;
071: }
072: }
073:
074: public Object create() {
075: classOnly = false;
076: return createHelper();
077: }
078:
079: public Object createClass() {
080: classOnly = true;
081: return createHelper();
082: }
083:
084: private Object createHelper() {
085: if (super class != null) {
086: setNamePrefix(super class.getName());
087: }
088: String super Name = (super class != null) ? super class.getName()
089: : "java.lang.Object";
090: Object key = KEY_FACTORY.newInstance(super Name, props);
091: return super .create(key);
092: }
093:
094: public void generateClass(ClassVisitor v) throws Exception {
095: int size = props.size();
096: String[] names = (String[]) props.keySet().toArray(
097: new String[size]);
098: Type[] types = new Type[size];
099: for (int i = 0; i < size; i++) {
100: types[i] = (Type) props.get(names[i]);
101: }
102: ClassEmitter ce = new ClassEmitter(v);
103: ce.begin_class(Constants.V1_2, Constants.ACC_PUBLIC,
104: getClassName(), super class != null ? Type
105: .getType(super class) : Constants.TYPE_OBJECT,
106: null, 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
122: : instance.getClass();
123: if (classOnly) {
124: return protoclass;
125: } else {
126: return ReflectUtils.newInstance(protoclass);
127: }
128: }
129:
130: public static void addProperties(BeanGenerator gen, Map props) {
131: for (Iterator it = props.keySet().iterator(); it.hasNext();) {
132: String name = (String) it.next();
133: gen.addProperty(name, (Class) props.get(name));
134: }
135: }
136:
137: public static void addProperties(BeanGenerator gen, Class type) {
138: addProperties(gen, ReflectUtils.getBeanProperties(type));
139: }
140:
141: public static void addProperties(BeanGenerator gen,
142: PropertyDescriptor[] descriptors) {
143: for (int i = 0; i < descriptors.length; i++) {
144: gen.addProperty(descriptors[i].getName(), descriptors[i]
145: .getPropertyType());
146: }
147: }
148: }
|