KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > cglib > beans > ImmutableBean


1 /*
2  * Copyright 2003,2004 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  */

16 package net.sf.cglib.beans;
17
18 import java.beans.PropertyDescriptor JavaDoc;
19 import java.lang.reflect.Method JavaDoc;
20 import net.sf.cglib.core.*;
21 import org.objectweb.asm.ClassVisitor;
22 import org.objectweb.asm.Type;
23
24 /**
25  * @author Chris Nokleberg
26  */

27 public class ImmutableBean
28 {
29     private static final Type ILLEGAL_STATE_EXCEPTION =
30       TypeUtils.parseType("IllegalStateException");
31     private static final Signature CSTRUCT_OBJECT =
32       TypeUtils.parseConstructor("Object");
33     private static final Class JavaDoc[] OBJECT_CLASSES = { Object JavaDoc.class };
34     private static final String JavaDoc FIELD_NAME = "CGLIB$RWBean";
35
36     private ImmutableBean() {
37     }
38
39     public static Object JavaDoc create(Object JavaDoc bean) {
40         Generator gen = new Generator();
41         gen.setBean(bean);
42         return gen.create();
43     }
44
45     public static class Generator extends AbstractClassGenerator {
46         private static final Source SOURCE = new Source(ImmutableBean.class.getName());
47         private Object JavaDoc bean;
48         private Class JavaDoc target;
49
50         public Generator() {
51             super(SOURCE);
52         }
53
54         public void setBean(Object JavaDoc bean) {
55             this.bean = bean;
56             target = bean.getClass();
57         }
58
59         protected ClassLoader JavaDoc getDefaultClassLoader() {
60             return target.getClassLoader();
61         }
62
63         public Object JavaDoc create() {
64             String JavaDoc name = target.getName();
65             setNamePrefix(name);
66             return super.create(name);
67         }
68
69         public void generateClass(ClassVisitor v) {
70             Type targetType = Type.getType(target);
71             ClassEmitter ce = new ClassEmitter(v);
72             ce.begin_class(Constants.V1_2,
73                            Constants.ACC_PUBLIC,
74                            getClassName(),
75                            targetType,
76                            null,
77                            Constants.SOURCE_FILE);
78
79             ce.declare_field(Constants.ACC_FINAL | Constants.ACC_PRIVATE, FIELD_NAME, targetType, null);
80
81             CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT, null);
82             e.load_this();
83             e.super_invoke_constructor();
84             e.load_this();
85             e.load_arg(0);
86             e.checkcast(targetType);
87             e.putfield(FIELD_NAME);
88             e.return_value();
89             e.end_method();
90
91             PropertyDescriptor JavaDoc[] descriptors = ReflectUtils.getBeanProperties(target);
92             Method JavaDoc[] getters = ReflectUtils.getPropertyMethods(descriptors, true, false);
93             Method JavaDoc[] setters = ReflectUtils.getPropertyMethods(descriptors, false, true);
94
95             for (int i = 0; i < getters.length; i++) {
96                 MethodInfo getter = ReflectUtils.getMethodInfo(getters[i]);
97                 e = EmitUtils.begin_method(ce, getter, Constants.ACC_PUBLIC);
98                 e.load_this();
99                 e.getfield(FIELD_NAME);
100                 e.invoke(getter);
101                 e.return_value();
102                 e.end_method();
103             }
104
105             for (int i = 0; i < setters.length; i++) {
106                 MethodInfo setter = ReflectUtils.getMethodInfo(setters[i]);
107                 e = EmitUtils.begin_method(ce, setter, Constants.ACC_PUBLIC);
108                 e.throw_exception(ILLEGAL_STATE_EXCEPTION, "Bean is immutable");
109                 e.end_method();
110             }
111
112             ce.end_class();
113         }
114
115         protected Object JavaDoc firstInstance(Class JavaDoc type) {
116             return ReflectUtils.newInstance(type, OBJECT_CLASSES, new Object JavaDoc[]{ bean });
117         }
118
119         // TODO: optimize
120
protected Object JavaDoc nextInstance(Object JavaDoc instance) {
121             return firstInstance(instance.getClass());
122         }
123     }
124 }
125
Popular Tags