1/* 2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.xml.internal.bind.v2.runtime.reflect.opt; 27 28import java.lang.reflect.Field; 29import java.lang.reflect.Modifier; 30import java.lang.reflect.Type; 31import java.util.HashMap; 32import java.util.Map; 33import java.util.logging.Level; 34import java.util.logging.Logger; 35 36import com.sun.xml.internal.bind.Util; 37import com.sun.xml.internal.bind.v2.model.core.TypeInfo; 38import com.sun.xml.internal.bind.v2.model.runtime.RuntimeClassInfo; 39import com.sun.xml.internal.bind.v2.model.runtime.RuntimePropertyInfo; 40import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor; 41import com.sun.xml.internal.bind.v2.runtime.reflect.TransducedAccessor; 42 43import static com.sun.xml.internal.bind.v2.bytecode.ClassTailor.toVMClassName; 44 45/** 46 * Prepares optimized {@link TransducedAccessor} from templates. 47 * 48 * @author Kohsuke Kawaguchi 49 */ 50public abstract class OptimizedTransducedAccessorFactory { 51 private OptimizedTransducedAccessorFactory() {} // no instanciation please 52 53 // http://java.sun.com/docs/books/vmspec/2nd-edition/html/ConstantPool.doc.html#75929 54 // "same runtime package" 55 56 private static final Logger logger = Util.getClassLogger(); 57 58 private static final String fieldTemplateName; 59 private static final String methodTemplateName; 60 61 static { 62 String s = TransducedAccessor_field_Byte.class.getName(); 63 fieldTemplateName = s.substring(0,s.length()-"Byte".length()).replace('.','/'); 64 65 s = TransducedAccessor_method_Byte.class.getName(); 66 methodTemplateName = s.substring(0,s.length()-"Byte".length()).replace('.','/'); 67 } 68 69 /** 70 * Gets the optimized {@link TransducedAccessor} if possible. 71 * 72 * @return null 73 * if for some reason it fails to create an optimized version. 74 */ 75 public static final TransducedAccessor get(RuntimePropertyInfo prop) { 76 Accessor acc = prop.getAccessor(); 77 78 // consider using an optimized TransducedAccessor implementations. 79 Class opt=null; 80 81 TypeInfo<Type,Class> parent = prop.parent(); 82 if(!(parent instanceof RuntimeClassInfo)) 83 return null; 84 85 Class dc = ((RuntimeClassInfo)parent).getClazz(); 86 String newClassName = toVMClassName(dc)+"_JaxbXducedAccessor_"+prop.getName(); 87 88 89 if(acc instanceof Accessor.FieldReflection) { 90 // TODO: we also need to make sure that the default xducer is used. 91 Accessor.FieldReflection racc = (Accessor.FieldReflection) acc; 92 Field field = racc.f; 93 94 int mods = field.getModifiers(); 95 if(Modifier.isPrivate(mods) || Modifier.isFinal(mods)) 96 // we can't access private fields. 97 // TODO: think about how to improve this case 98 return null; 99 100 Class<?> t = field.getType(); 101 if(t.isPrimitive()) 102 opt = AccessorInjector.prepare( dc, 103 fieldTemplateName+suffixMap.get(t), 104 newClassName, 105 toVMClassName(Bean.class), 106 toVMClassName(dc), 107 "f_"+t.getName(), 108 field.getName() ); 109 } 110 111 if(acc.getClass()==Accessor.GetterSetterReflection.class) { 112 Accessor.GetterSetterReflection gacc = (Accessor.GetterSetterReflection) acc; 113 114 if(gacc.getter==null || gacc.setter==null) 115 return null; // incomplete 116 117 Class<?> t = gacc.getter.getReturnType(); 118 119 if(Modifier.isPrivate(gacc.getter.getModifiers()) 120 || Modifier.isPrivate(gacc.setter.getModifiers())) 121 // we can't access private methods. 122 return null; 123 124 125 if(t.isPrimitive()) 126 opt = AccessorInjector.prepare( dc, 127 methodTemplateName+suffixMap.get(t), 128 newClassName, 129 toVMClassName(Bean.class), 130 toVMClassName(dc), 131 "get_"+t.getName(), 132 gacc.getter.getName(), 133 "set_"+t.getName(), 134 gacc.setter.getName()); 135 } 136 137 if(opt==null) 138 return null; 139 140 logger.log(Level.FINE,"Using optimized TransducedAccessor for "+prop.displayName()); 141 142 143 try { 144 return (TransducedAccessor)opt.newInstance(); 145 } catch (InstantiationException e) { 146 logger.log(Level.INFO,"failed to load an optimized TransducedAccessor",e); 147 } catch (IllegalAccessException e) { 148 logger.log(Level.INFO,"failed to load an optimized TransducedAccessor",e); 149 } catch (SecurityException e) { 150 logger.log(Level.INFO,"failed to load an optimized TransducedAccessor",e); 151 } 152 return null; 153 } 154 155 private static final Map<Class,String> suffixMap = new HashMap<Class, String>(); 156 157 static { 158 suffixMap.put(Byte.TYPE,"Byte"); 159 suffixMap.put(Short.TYPE,"Short"); 160 suffixMap.put(Integer.TYPE,"Integer"); 161 suffixMap.put(Long.TYPE,"Long"); 162 suffixMap.put(Boolean.TYPE,"Boolean"); 163 suffixMap.put(Float.TYPE,"Float"); 164 suffixMap.put(Double.TYPE,"Double"); 165 } 166 167} 168