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.beans;
55
56 import java.beans.PropertyDescriptor;
57 import java.lang.reflect.Method;
58 import net.sf.cglib.core.*;
59 import org.objectweb.asm.ClassVisitor;
60 import org.objectweb.asm.Type;
61
62 /***
63 * @author Chris Nokleberg
64 */
65 public class ImmutableBean
66 {
67 private static final Type ILLEGAL_STATE_EXCEPTION =
68 TypeUtils.parseType("IllegalStateException");
69 private static final Signature CSTRUCT_OBJECT =
70 TypeUtils.parseConstructor("Object");
71 private static final Class[] OBJECT_CLASSES = { Object.class };
72 private static final String FIELD_NAME = "CGLIB$RWBean";
73
74 private ImmutableBean() {
75 }
76
77 public static Object create(Object bean) {
78 Generator gen = new Generator();
79 gen.setBean(bean);
80 return gen.create();
81 }
82
83 public static class Generator extends AbstractClassGenerator {
84 private static final Source SOURCE = new Source(ImmutableBean.class.getName());
85 private Object bean;
86 private Class target;
87
88 public Generator() {
89 super(SOURCE);
90 }
91
92 public void setBean(Object bean) {
93 this.bean = bean;
94 target = bean.getClass();
95 }
96
97 protected ClassLoader getDefaultClassLoader() {
98 return target.getClassLoader();
99 }
100
101 public Object create() {
102 String name = target.getName();
103 setNamePrefix(name);
104 return super.create(name);
105 }
106
107 public void generateClass(ClassVisitor v) {
108 Type targetType = Type.getType(target);
109 ClassEmitter ce = new ClassEmitter(v);
110 ce.begin_class(Constants.ACC_PUBLIC,
111 getClassName(),
112 targetType,
113 null,
114 Constants.SOURCE_FILE);
115
116 ce.declare_field(Constants.ACC_FINAL | Constants.ACC_PRIVATE, FIELD_NAME, targetType, null, null);
117
118 CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT, null, null);
119 e.load_this();
120 e.super_invoke_constructor();
121 e.load_this();
122 e.load_arg(0);
123 e.checkcast(targetType);
124 e.putfield(FIELD_NAME);
125 e.return_value();
126 e.end_method();
127
128 PropertyDescriptor[] descriptors = ReflectUtils.getBeanProperties(target);
129 Method[] getters = ReflectUtils.getPropertyMethods(descriptors, true, false);
130 Method[] setters = ReflectUtils.getPropertyMethods(descriptors, false, true);
131
132 for (int i = 0; i < getters.length; i++) {
133 e = ce.begin_method(Constants.ACC_PUBLIC,
134 ReflectUtils.getSignature(getters[i]),
135 TypeUtils.getTypes(getters[i].getExceptionTypes()),
136 null);
137 e.load_this();
138 e.getfield(FIELD_NAME);
139 e.invoke(getters[i]);
140 e.return_value();
141 e.end_method();
142 }
143
144 for (int i = 0; i < setters.length; i++) {
145 e = ce.begin_method(Constants.ACC_PUBLIC,
146 ReflectUtils.getSignature(setters[i]),
147 null,
148 null);
149 e.throw_exception(ILLEGAL_STATE_EXCEPTION, "Bean is immutable");
150 e.end_method();
151 }
152
153 ce.end_class();
154 }
155
156 protected Object firstInstance(Class type) {
157 return ReflectUtils.newInstance(type, OBJECT_CLASSES, new Object[]{ bean });
158 }
159
160 // TODO: optimize
161 protected Object nextInstance(Object instance) {
162 return firstInstance(instance.getClass());
163 }
164 }
165 }
This page was automatically generated by Maven