001: /*
002: * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.xml.internal.bind.v2.runtime.reflect.opt;
027:
028: import java.lang.reflect.Field;
029: import java.lang.reflect.Modifier;
030: import java.lang.reflect.Type;
031: import java.util.HashMap;
032: import java.util.Map;
033: import java.util.logging.Level;
034: import java.util.logging.Logger;
035:
036: import com.sun.xml.internal.bind.Util;
037: import com.sun.xml.internal.bind.v2.model.core.TypeInfo;
038: import com.sun.xml.internal.bind.v2.model.runtime.RuntimeClassInfo;
039: import com.sun.xml.internal.bind.v2.model.runtime.RuntimePropertyInfo;
040: import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor;
041: import com.sun.xml.internal.bind.v2.runtime.reflect.TransducedAccessor;
042:
043: import static com.sun.xml.internal.bind.v2.bytecode.ClassTailor.toVMClassName;
044:
045: /**
046: * Prepares optimized {@link TransducedAccessor} from templates.
047: *
048: * @author Kohsuke Kawaguchi
049: */
050: public abstract class OptimizedTransducedAccessorFactory {
051: private OptimizedTransducedAccessorFactory() {
052: } // no instanciation please
053:
054: // http://java.sun.com/docs/books/vmspec/2nd-edition/html/ConstantPool.doc.html#75929
055: // "same runtime package"
056:
057: private static final Logger logger = Util.getClassLogger();
058:
059: private static final String fieldTemplateName;
060: private static final String methodTemplateName;
061:
062: static {
063: String s = TransducedAccessor_field_Byte.class.getName();
064: fieldTemplateName = s
065: .substring(0, s.length() - "Byte".length()).replace(
066: '.', '/');
067:
068: s = TransducedAccessor_method_Byte.class.getName();
069: methodTemplateName = s.substring(0,
070: s.length() - "Byte".length()).replace('.', '/');
071: }
072:
073: /**
074: * Gets the optimizd {@link TransducedAccessor} if possible.
075: *
076: * @return null
077: * if for some reason it fails to create an optimized version.
078: */
079: public static final TransducedAccessor get(RuntimePropertyInfo prop) {
080: Accessor acc = prop.getAccessor();
081:
082: // consider using an optimized TransducedAccessor implementations.
083: Class opt = null;
084:
085: TypeInfo<Type, Class> parent = prop.parent();
086: if (!(parent instanceof RuntimeClassInfo))
087: return null;
088:
089: Class dc = ((RuntimeClassInfo) parent).getClazz();
090: String newClassName = toVMClassName(dc)
091: + "_JaxbXducedAccessor_" + prop.getName();
092:
093: if (acc instanceof Accessor.FieldReflection) {
094: // TODO: we also need to make sure that the default xducer is used.
095: Accessor.FieldReflection racc = (Accessor.FieldReflection) acc;
096: Field field = racc.f;
097:
098: int mods = field.getModifiers();
099: if (Modifier.isPrivate(mods) || Modifier.isFinal(mods))
100: // we can't access private fields.
101: // TODO: think about how to improve this case
102: return null;
103:
104: Class<?> t = field.getType();
105: if (t.isPrimitive())
106: opt = AccessorInjector.prepare(dc, fieldTemplateName
107: + suffixMap.get(t), newClassName,
108: toVMClassName(Bean.class), toVMClassName(dc),
109: "f_" + t.getName(), field.getName());
110: }
111:
112: if (acc.getClass() == Accessor.GetterSetterReflection.class) {
113: Accessor.GetterSetterReflection gacc = (Accessor.GetterSetterReflection) acc;
114:
115: if (gacc.getter == null || gacc.setter == null)
116: return null; // incomplete
117:
118: Class<?> t = gacc.getter.getReturnType();
119:
120: if (Modifier.isPrivate(gacc.getter.getModifiers())
121: || Modifier.isPrivate(gacc.setter.getModifiers()))
122: // we can't access private methods.
123: return null;
124:
125: if (t.isPrimitive())
126: opt = AccessorInjector.prepare(dc, methodTemplateName
127: + suffixMap.get(t), newClassName,
128: toVMClassName(Bean.class), toVMClassName(dc),
129: "get_" + t.getName(), gacc.getter.getName(),
130: "set_" + t.getName(), gacc.setter.getName());
131: }
132:
133: if (opt == null)
134: return null;
135:
136: logger.log(Level.FINE,
137: "Using optimized TransducedAccessor for "
138: + prop.displayName());
139:
140: try {
141: return (TransducedAccessor) opt.newInstance();
142: } catch (InstantiationException e) {
143: logger
144: .log(
145: Level.INFO,
146: "failed to load an optimized TransducedAccessor",
147: e);
148: } catch (IllegalAccessException e) {
149: logger
150: .log(
151: Level.INFO,
152: "failed to load an optimized TransducedAccessor",
153: e);
154: } catch (SecurityException e) {
155: logger
156: .log(
157: Level.INFO,
158: "failed to load an optimized TransducedAccessor",
159: e);
160: }
161: return null;
162: }
163:
164: private static final Map<Class, String> suffixMap = new HashMap<Class, String>();
165:
166: static {
167: suffixMap.put(Byte.TYPE, "Byte");
168: suffixMap.put(Short.TYPE, "Short");
169: suffixMap.put(Integer.TYPE, "Integer");
170: suffixMap.put(Long.TYPE, "Long");
171: suffixMap.put(Boolean.TYPE, "Boolean");
172: suffixMap.put(Float.TYPE, "Float");
173: suffixMap.put(Double.TYPE, "Double");
174: }
175:
176: }
|