001: /*
002: * Copyright 2003,2004 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.lang.reflect.Constructor;
019: import java.lang.reflect.Method;
020: import java.lang.reflect.Modifier;
021: import java.util.*;
022: import net.sf.cglib.core.*;
023: import org.objectweb.asm.ClassVisitor;
024: import org.objectweb.asm.Type;
025:
026: class BulkBeanEmitter extends ClassEmitter {
027: private static final Signature GET_PROPERTY_VALUES = TypeUtils
028: .parseSignature("void getPropertyValues(Object, Object[])");
029: private static final Signature SET_PROPERTY_VALUES = TypeUtils
030: .parseSignature("void setPropertyValues(Object, Object[])");
031: private static final Signature CSTRUCT_EXCEPTION = TypeUtils
032: .parseConstructor("Throwable, int");
033: private static final Type BULK_BEAN = TypeUtils
034: .parseType("net.sf.cglib.beans.BulkBean");
035: private static final Type BULK_BEAN_EXCEPTION = TypeUtils
036: .parseType("net.sf.cglib.beans.BulkBeanException");
037:
038: public BulkBeanEmitter(ClassVisitor v, String className,
039: Class target, String[] getterNames, String[] setterNames,
040: Class[] types) {
041: super (v);
042:
043: Method[] getters = new Method[getterNames.length];
044: Method[] setters = new Method[setterNames.length];
045: validate(target, getterNames, setterNames, types, getters,
046: setters);
047:
048: begin_class(Constants.V1_2, Constants.ACC_PUBLIC, className,
049: BULK_BEAN, null, Constants.SOURCE_FILE);
050: EmitUtils.null_constructor(this );
051: generateGet(target, getters);
052: generateSet(target, setters);
053: end_class();
054: }
055:
056: private void generateGet(final Class target, final Method[] getters) {
057: CodeEmitter e = begin_method(Constants.ACC_PUBLIC,
058: GET_PROPERTY_VALUES, null);
059: if (getters.length >= 0) {
060: e.load_arg(0);
061: e.checkcast(Type.getType(target));
062: Local bean = e.make_local();
063: e.store_local(bean);
064: for (int i = 0; i < getters.length; i++) {
065: if (getters[i] != null) {
066: MethodInfo getter = ReflectUtils
067: .getMethodInfo(getters[i]);
068: e.load_arg(1);
069: e.push(i);
070: e.load_local(bean);
071: e.invoke(getter);
072: e.box(getter.getSignature().getReturnType());
073: e.aastore();
074: }
075: }
076: }
077: e.return_value();
078: e.end_method();
079: }
080:
081: private void generateSet(final Class target, final Method[] setters) {
082: // setPropertyValues
083: CodeEmitter e = begin_method(Constants.ACC_PUBLIC,
084: SET_PROPERTY_VALUES, null);
085: if (setters.length > 0) {
086: Local index = e.make_local(Type.INT_TYPE);
087: e.push(0);
088: e.store_local(index);
089: e.load_arg(0);
090: e.checkcast(Type.getType(target));
091: e.load_arg(1);
092: Block handler = e.begin_block();
093: int lastIndex = 0;
094: for (int i = 0; i < setters.length; i++) {
095: if (setters[i] != null) {
096: MethodInfo setter = ReflectUtils
097: .getMethodInfo(setters[i]);
098: int diff = i - lastIndex;
099: if (diff > 0) {
100: e.iinc(index, diff);
101: lastIndex = i;
102: }
103: e.dup2();
104: e.aaload(i);
105: e
106: .unbox(setter.getSignature()
107: .getArgumentTypes()[0]);
108: e.invoke(setter);
109: }
110: }
111: handler.end();
112: e.return_value();
113: e.catch_exception(handler, Constants.TYPE_THROWABLE);
114: e.new_instance(BULK_BEAN_EXCEPTION);
115: e.dup_x1();
116: e.swap();
117: e.load_local(index);
118: e
119: .invoke_constructor(BULK_BEAN_EXCEPTION,
120: CSTRUCT_EXCEPTION);
121: e.athrow();
122: } else {
123: e.return_value();
124: }
125: e.end_method();
126: }
127:
128: private static void validate(Class target, String[] getters,
129: String[] setters, Class[] types, Method[] getters_out,
130: Method[] setters_out) {
131: int i = -1;
132: if (setters.length != types.length
133: || getters.length != types.length) {
134: throw new BulkBeanException(
135: "accessor array length must be equal type array length",
136: i);
137: }
138: try {
139: for (i = 0; i < types.length; i++) {
140: if (getters[i] != null) {
141: Method method = ReflectUtils.findDeclaredMethod(
142: target, getters[i], null);
143: if (method.getReturnType() != types[i]) {
144: throw new BulkBeanException("Specified type "
145: + types[i]
146: + " does not match declared type "
147: + method.getReturnType(), i);
148: }
149: if (Modifier.isPrivate(method.getModifiers())) {
150: throw new BulkBeanException(
151: "Property is private", i);
152: }
153: getters_out[i] = method;
154: }
155: if (setters[i] != null) {
156: Method method = ReflectUtils.findDeclaredMethod(
157: target, setters[i],
158: new Class[] { types[i] });
159: if (Modifier.isPrivate(method.getModifiers())) {
160: throw new BulkBeanException(
161: "Property is private", i);
162: }
163: setters_out[i] = method;
164: }
165: }
166: } catch (NoSuchMethodException e) {
167: throw new BulkBeanException(
168: "Cannot find specified property", i);
169: }
170: }
171: }
|