001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036:
037: package com.sun.xml.bind.v2.runtime.reflect.opt;
038:
039: import java.lang.reflect.Field;
040: import java.lang.reflect.Modifier;
041: import java.lang.reflect.Type;
042: import java.util.HashMap;
043: import java.util.Map;
044: import java.util.logging.Level;
045: import java.util.logging.Logger;
046:
047: import com.sun.xml.bind.Util;
048: import com.sun.xml.bind.v2.model.core.TypeInfo;
049: import com.sun.xml.bind.v2.model.runtime.RuntimeClassInfo;
050: import com.sun.xml.bind.v2.model.runtime.RuntimePropertyInfo;
051: import com.sun.xml.bind.v2.runtime.reflect.Accessor;
052: import com.sun.xml.bind.v2.runtime.reflect.TransducedAccessor;
053:
054: import static com.sun.xml.bind.v2.bytecode.ClassTailor.toVMClassName;
055:
056: /**
057: * Prepares optimized {@link TransducedAccessor} from templates.
058: *
059: * @author Kohsuke Kawaguchi
060: */
061: public abstract class OptimizedTransducedAccessorFactory {
062: private OptimizedTransducedAccessorFactory() {
063: } // no instanciation please
064:
065: // http://java.sun.com/docs/books/vmspec/2nd-edition/html/ConstantPool.doc.html#75929
066: // "same runtime package"
067:
068: private static final Logger logger = Util.getClassLogger();
069:
070: private static final String fieldTemplateName;
071: private static final String methodTemplateName;
072:
073: static {
074: String s = TransducedAccessor_field_Byte.class.getName();
075: fieldTemplateName = s
076: .substring(0, s.length() - "Byte".length()).replace(
077: '.', '/');
078:
079: s = TransducedAccessor_method_Byte.class.getName();
080: methodTemplateName = s.substring(0,
081: s.length() - "Byte".length()).replace('.', '/');
082: }
083:
084: /**
085: * Gets the optimizd {@link TransducedAccessor} if possible.
086: *
087: * @return null
088: * if for some reason it fails to create an optimized version.
089: */
090: public static final TransducedAccessor get(RuntimePropertyInfo prop) {
091: Accessor acc = prop.getAccessor();
092:
093: // consider using an optimized TransducedAccessor implementations.
094: Class opt = null;
095:
096: TypeInfo<Type, Class> parent = prop.parent();
097: if (!(parent instanceof RuntimeClassInfo))
098: return null;
099:
100: Class dc = ((RuntimeClassInfo) parent).getClazz();
101: String newClassName = toVMClassName(dc)
102: + "_JaxbXducedAccessor_" + prop.getName();
103:
104: if (acc instanceof Accessor.FieldReflection) {
105: // TODO: we also need to make sure that the default xducer is used.
106: Accessor.FieldReflection racc = (Accessor.FieldReflection) acc;
107: Field field = racc.f;
108:
109: int mods = field.getModifiers();
110: if (Modifier.isPrivate(mods) || Modifier.isFinal(mods))
111: // we can't access private fields.
112: // TODO: think about how to improve this case
113: return null;
114:
115: Class<?> t = field.getType();
116: if (t.isPrimitive())
117: opt = AccessorInjector.prepare(dc, fieldTemplateName
118: + suffixMap.get(t), newClassName,
119: toVMClassName(Bean.class), toVMClassName(dc),
120: "f_" + t.getName(), field.getName());
121: }
122:
123: if (acc.getClass() == Accessor.GetterSetterReflection.class) {
124: Accessor.GetterSetterReflection gacc = (Accessor.GetterSetterReflection) acc;
125:
126: if (gacc.getter == null || gacc.setter == null)
127: return null; // incomplete
128:
129: Class<?> t = gacc.getter.getReturnType();
130:
131: if (Modifier.isPrivate(gacc.getter.getModifiers())
132: || Modifier.isPrivate(gacc.setter.getModifiers()))
133: // we can't access private methods.
134: return null;
135:
136: if (t.isPrimitive())
137: opt = AccessorInjector.prepare(dc, methodTemplateName
138: + suffixMap.get(t), newClassName,
139: toVMClassName(Bean.class), toVMClassName(dc),
140: "get_" + t.getName(), gacc.getter.getName(),
141: "set_" + t.getName(), gacc.setter.getName());
142: }
143:
144: if (opt == null)
145: return null;
146:
147: logger.log(Level.FINE,
148: "Using optimized TransducedAccessor for "
149: + prop.displayName());
150:
151: try {
152: return (TransducedAccessor) opt.newInstance();
153: } catch (InstantiationException e) {
154: logger
155: .log(
156: Level.INFO,
157: "failed to load an optimized TransducedAccessor",
158: e);
159: } catch (IllegalAccessException e) {
160: logger
161: .log(
162: Level.INFO,
163: "failed to load an optimized TransducedAccessor",
164: e);
165: } catch (SecurityException e) {
166: logger
167: .log(
168: Level.INFO,
169: "failed to load an optimized TransducedAccessor",
170: e);
171: }
172: return null;
173: }
174:
175: private static final Map<Class, String> suffixMap = new HashMap<Class, String>();
176:
177: static {
178: suffixMap.put(Byte.TYPE, "Byte");
179: suffixMap.put(Short.TYPE, "Short");
180: suffixMap.put(Integer.TYPE, "Integer");
181: suffixMap.put(Long.TYPE, "Long");
182: suffixMap.put(Boolean.TYPE, "Boolean");
183: suffixMap.put(Float.TYPE, "Float");
184: suffixMap.put(Double.TYPE, "Double");
185: }
186:
187: }
|