View Javadoc
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.*; 57 import java.util.*; 58 import net.sf.cglib.core.*; 59 import org.objectweb.asm.ClassVisitor; 60 import org.objectweb.asm.Label; 61 import org.objectweb.asm.Type; 62 63 class BeanMapEmitter extends ClassEmitter { 64 private static final Signature CSTRUCT_OBJECT = 65 TypeUtils.parseConstructor("Object"); 66 private static final Signature CSTRUCT_STRING_ARRAY = 67 TypeUtils.parseConstructor("String[]"); 68 private static final Signature BEAN_MAP_GET = 69 TypeUtils.parseSignature("Object get(Object, Object)"); 70 private static final Signature BEAN_MAP_PUT = 71 TypeUtils.parseSignature("Object put(Object, Object, Object)"); 72 private static final Signature KEY_SET = 73 TypeUtils.parseSignature("java.util.Set keySet()"); 74 private static final Signature NEW_INSTANCE = 75 TypeUtils.parseSignature("net.sf.cglib.beans.BeanMap newInstance(Object)"); 76 private static final Signature GET_PROPERTY_TYPE = 77 TypeUtils.parseSignature("Class getPropertyType(String)"); 78 private static final Type BEAN_MAP = 79 TypeUtils.parseType("net.sf.cglib.beans.BeanMap"); 80 private static final Type FIXED_KEY_SET = 81 TypeUtils.parseType("net.sf.cglib.beans.FixedKeySet"); 82 83 public BeanMapEmitter(ClassVisitor v, String className, Class type, int require) { 84 super(v); 85 86 begin_class(Constants.ACC_PUBLIC, className, BEAN_MAP, null, Constants.SOURCE_FILE); 87 EmitUtils.null_constructor(this); 88 EmitUtils.factory_method(this, NEW_INSTANCE); 89 generateConstructor(); 90 91 Map getters = makePropertyMap(ReflectUtils.getBeanGetters(type)); 92 Map setters = makePropertyMap(ReflectUtils.getBeanSetters(type)); 93 Map allProps = new HashMap(); 94 allProps.putAll(getters); 95 allProps.putAll(setters); 96 97 if (require != 0) { 98 for (Iterator it = allProps.keySet().iterator(); it.hasNext();) { 99 String name = (String)it.next(); 100 if ((((require & BeanMap.REQUIRE_GETTER) != 0) && !getters.containsKey(name)) || 101 (((require & BeanMap.REQUIRE_SETTER) != 0) && !setters.containsKey(name))) { 102 it.remove(); 103 getters.remove(name); 104 setters.remove(name); 105 } 106 } 107 } 108 generateGet(type, getters); 109 generatePut(type, setters); 110 111 String[] allNames = getNames(allProps); 112 generateKeySet(allNames); 113 generateGetPropertyType(allProps, allNames); 114 end_class(); 115 } 116 117 private Map makePropertyMap(PropertyDescriptor[] props) { 118 Map names = new HashMap(); 119 for (int i = 0; i < props.length; i++) { 120 names.put(((PropertyDescriptor)props[i]).getName(), props[i]); 121 } 122 return names; 123 } 124 125 private String[] getNames(Map propertyMap) { 126 return (String[])propertyMap.keySet().toArray(new String[propertyMap.size()]); 127 } 128 129 private void generateConstructor() { 130 CodeEmitter e = begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT, null, null); 131 e.load_this(); 132 e.load_arg(0); 133 e.super_invoke_constructor(CSTRUCT_OBJECT); 134 e.return_value(); 135 e.end_method(); 136 } 137 138 private void generateGet(Class type, final Map getters) { 139 final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, BEAN_MAP_GET, null, null); 140 e.load_arg(0); 141 e.checkcast(Type.getType(type)); 142 e.load_arg(1); 143 e.checkcast(Constants.TYPE_STRING); 144 EmitUtils.string_switch(e, getNames(getters), Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() { 145 public void processCase(Object key, Label end) { 146 PropertyDescriptor pd = (PropertyDescriptor)getters.get(key); 147 e.invoke(pd.getReadMethod()); 148 e.box(Type.getType(pd.getReadMethod().getReturnType())); 149 e.return_value(); 150 } 151 public void processDefault() { 152 e.aconst_null(); 153 e.return_value(); 154 } 155 }); 156 e.end_method(); 157 } 158 159 private void generatePut(Class type, final Map setters) { 160 final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, BEAN_MAP_PUT, null, null); 161 e.load_arg(0); 162 e.checkcast(Type.getType(type)); 163 e.load_arg(1); 164 e.checkcast(Constants.TYPE_STRING); 165 EmitUtils.string_switch(e, getNames(setters), Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() { 166 public void processCase(Object key, Label end) { 167 PropertyDescriptor pd = (PropertyDescriptor)setters.get(key); 168 if (pd.getReadMethod() == null) { 169 e.aconst_null(); 170 } else { 171 e.dup(); 172 e.invoke(pd.getReadMethod()); 173 e.box(Type.getType(pd.getReadMethod().getReturnType())); 174 } 175 e.swap(); // move old value behind bean 176 e.load_arg(2); // new value 177 e.unbox(Type.getType(pd.getWriteMethod().getParameterTypes()[0])); 178 e.invoke(pd.getWriteMethod()); 179 e.return_value(); 180 } 181 public void processDefault() { 182 // fall-through 183 } 184 }); 185 e.aconst_null(); 186 e.return_value(); 187 e.end_method(); 188 } 189 190 private void generateKeySet(String[] allNames) { 191 // static initializer 192 declare_field(Constants.ACC_STATIC | Constants.ACC_PRIVATE, "keys", FIXED_KEY_SET, null, null); 193 194 CodeEmitter e = begin_static(); 195 e.new_instance(FIXED_KEY_SET); 196 e.dup(); 197 EmitUtils.push_array(e, allNames); 198 e.invoke_constructor(FIXED_KEY_SET, CSTRUCT_STRING_ARRAY); 199 e.putfield("keys"); 200 e.return_value(); 201 e.end_method(); 202 203 // keySet 204 e = begin_method(Constants.ACC_PUBLIC, KEY_SET, null, null); 205 e.load_this(); 206 e.getfield("keys"); 207 e.return_value(); 208 e.end_method(); 209 } 210 211 private void generateGetPropertyType(final Map allProps, String[] allNames) { 212 final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, GET_PROPERTY_TYPE, null, null); 213 e.load_arg(0); 214 EmitUtils.string_switch(e, allNames, Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() { 215 public void processCase(Object key, Label end) { 216 PropertyDescriptor pd = (PropertyDescriptor)allProps.get(key); 217 EmitUtils.load_class(e, Type.getType(pd.getPropertyType())); 218 e.return_value(); 219 } 220 public void processDefault() { 221 e.aconst_null(); 222 e.return_value(); 223 } 224 }); 225 e.end_method(); 226 } 227 }

This page was automatically generated by Maven