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.Method;
030: import java.lang.reflect.Modifier;
031: import java.util.logging.Level;
032: import java.util.logging.Logger;
033:
034: import com.sun.xml.internal.bind.Util;
035: import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor;
036:
037: import static com.sun.xml.internal.bind.v2.bytecode.ClassTailor.toVMClassName;
038: import static com.sun.xml.internal.bind.v2.bytecode.ClassTailor.toVMTypeName;
039:
040: /**
041: * @author Kohsuke Kawaguchi
042: */
043: public abstract class OptimizedAccessorFactory {
044: private OptimizedAccessorFactory() {
045: } // no instanciation please
046:
047: private static final Logger logger = Util.getClassLogger();
048:
049: private static final String fieldTemplateName;
050: private static final String methodTemplateName;
051:
052: static {
053: String s = FieldAccessor_Byte.class.getName();
054: fieldTemplateName = s
055: .substring(0, s.length() - "Byte".length()).replace(
056: '.', '/');
057:
058: s = MethodAccessor_Byte.class.getName();
059: methodTemplateName = s.substring(0,
060: s.length() - "Byte".length()).replace('.', '/');
061: }
062:
063: /**
064: * Gets the optimized {@link Accessor} that accesses the given getter/setter.
065: *
066: * @return null
067: * if for some reason it fails to create an optimized version.
068: */
069: public static final <B, V> Accessor<B, V> get(Method getter,
070: Method setter) {
071: // make sure the method signatures are what we expect
072: if (getter.getParameterTypes().length != 0)
073: return null;
074: Class<?>[] sparams = setter.getParameterTypes();
075: if (sparams.length != 1)
076: return null;
077: if (sparams[0] != getter.getReturnType())
078: return null;
079: if (setter.getReturnType() != Void.TYPE)
080: return null;
081: if (getter.getDeclaringClass() != setter.getDeclaringClass())
082: return null;
083: if (Modifier.isPrivate(getter.getModifiers())
084: || Modifier.isPrivate(setter.getModifiers()))
085: // we can't access private fields
086: return null;
087:
088: Class t = sparams[0];
089: String typeName = t.getName().replace('.', '_');
090:
091: String newClassName = toVMClassName(getter.getDeclaringClass())
092: + "$JaxbAccessorM_" + getter.getName() + '_'
093: + setter.getName() + '_' + typeName;
094:
095: Class opt;
096:
097: if (t.isPrimitive())
098: opt = AccessorInjector.prepare(getter.getDeclaringClass(),
099: methodTemplateName + t.getName(), newClassName,
100: toVMClassName(Bean.class), toVMClassName(getter
101: .getDeclaringClass()),
102: "get_" + t.getName(), getter.getName(), "set_"
103: + t.getName(), setter.getName());
104: else
105: opt = AccessorInjector.prepare(getter.getDeclaringClass(),
106: methodTemplateName + "Ref", newClassName,
107: toVMClassName(Bean.class), toVMClassName(getter
108: .getDeclaringClass()),
109: toVMClassName(Ref.class), toVMClassName(t), "()"
110: + toVMTypeName(Ref.class), "()"
111: + toVMTypeName(t), '('
112: + toVMTypeName(Ref.class) + ")V", '('
113: + toVMTypeName(t) + ")V", "get_ref", getter
114: .getName(), "set_ref", setter.getName());
115:
116: if (opt == null)
117: return null;
118:
119: Accessor<B, V> acc = instanciate(opt);
120: if (acc != null)
121: logger.log(Level.FINE, "Using optimized Accessor for "
122: + getter + " and " + setter);
123: return acc;
124: }
125:
126: /**
127: * Gets the optimizd {@link Accessor} that accesses the given field.
128: *
129: * @return null
130: * if for some reason it fails to create an optimized version.
131: */
132: public static final <B, V> Accessor<B, V> get(Field field) {
133: int mods = field.getModifiers();
134: if (Modifier.isPrivate(mods) || Modifier.isFinal(mods))
135: // we can't access private fields
136: return null;
137:
138: String newClassName = toVMClassName(field.getDeclaringClass())
139: + "$JaxbAccessorF_" + field.getName();
140:
141: Class opt;
142:
143: if (field.getType().isPrimitive())
144: opt = AccessorInjector.prepare(field.getDeclaringClass(),
145: fieldTemplateName + field.getType().getName(),
146: newClassName, toVMClassName(Bean.class),
147: toVMClassName(field.getDeclaringClass()), "f_"
148: + field.getType().getName(), field
149: .getName());
150: else
151: opt = AccessorInjector.prepare(field.getDeclaringClass(),
152: fieldTemplateName + "Ref", newClassName,
153: toVMClassName(Bean.class), toVMClassName(field
154: .getDeclaringClass()),
155: toVMClassName(Ref.class), toVMClassName(field
156: .getType()), toVMTypeName(Ref.class),
157: toVMTypeName(field.getType()), "f_ref", field
158: .getName());
159:
160: if (opt == null)
161: return null;
162:
163: Accessor<B, V> acc = instanciate(opt);
164: if (acc != null)
165: logger.log(Level.FINE, "Using optimized Accessor for "
166: + field);
167: return acc;
168: }
169:
170: private static <B, V> Accessor<B, V> instanciate(Class opt) {
171: try {
172: return (Accessor<B, V>) opt.newInstance();
173: } catch (InstantiationException e) {
174: logger.log(Level.INFO,
175: "failed to load an optimized Accessor", e);
176: } catch (IllegalAccessException e) {
177: logger.log(Level.INFO,
178: "failed to load an optimized Accessor", e);
179: } catch (SecurityException e) {
180: logger.log(Level.INFO,
181: "failed to load an optimized Accessor", e);
182: }
183: return null;
184: }
185: }
|