1 /* 2 * Copyright (c) 1997, 2011, 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 26 package com.sun.xml.internal.bind.v2.model.impl; 27 28 import java.lang.reflect.Field; 29 import java.lang.reflect.Method; 30 import java.lang.reflect.Type; 31 import java.util.Map; 32 33 import javax.activation.MimeType; 34 35 import com.sun.xml.internal.bind.WhiteSpaceProcessor; 36 import com.sun.xml.internal.bind.api.AccessorException; 37 import com.sun.xml.internal.bind.v2.model.annotation.Locatable; 38 import com.sun.xml.internal.bind.v2.model.annotation.RuntimeAnnotationReader; 39 import com.sun.xml.internal.bind.v2.model.core.ID; 40 import com.sun.xml.internal.bind.v2.model.nav.Navigator; 41 import com.sun.xml.internal.bind.v2.model.runtime.RuntimeNonElement; 42 import com.sun.xml.internal.bind.v2.model.runtime.RuntimeNonElementRef; 43 import com.sun.xml.internal.bind.v2.model.runtime.RuntimePropertyInfo; 44 import com.sun.xml.internal.bind.v2.model.runtime.RuntimeTypeInfoSet; 45 import com.sun.xml.internal.bind.v2.runtime.FilterTransducer; 46 import com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationException; 47 import com.sun.xml.internal.bind.v2.runtime.InlineBinaryTransducer; 48 import com.sun.xml.internal.bind.v2.runtime.MimeTypedTransducer; 49 import com.sun.xml.internal.bind.v2.runtime.SchemaTypeTransducer; 50 import com.sun.xml.internal.bind.v2.runtime.Transducer; 51 import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl; 52 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext; 53 import com.sun.istack.internal.Nullable; 54 55 import com.sun.xml.internal.bind.v2.WellKnownNamespace; 56 import javax.xml.namespace.QName; 57 import org.xml.sax.SAXException; 58 59 /** 60 * {@link ModelBuilder} that works at the run-time by using 61 * the {@code java.lang.reflect} package. 62 * 63 * <p> 64 * This extends {@link ModelBuilder} by providing more functionalities such 65 * as accessing the fields and classes. 66 * 67 * @author Kohsuke Kawaguchi (kk@kohsuke.org) 68 */ 69 public class RuntimeModelBuilder extends ModelBuilder<Type,Class,Field,Method> { 70 /** 71 * The {@link JAXBContextImpl} for which the model is built. 72 * Null when created for reflection. 73 */ 74 public final @Nullable JAXBContextImpl context; 75 RuntimeModelBuilder(JAXBContextImpl context, RuntimeAnnotationReader annotationReader, Map<Class, Class> subclassReplacements, String defaultNamespaceRemap)76 public RuntimeModelBuilder(JAXBContextImpl context, RuntimeAnnotationReader annotationReader, Map<Class, Class> subclassReplacements, String defaultNamespaceRemap) { 77 super(annotationReader, Utils.REFLECTION_NAVIGATOR, subclassReplacements, defaultNamespaceRemap); 78 this.context = context; 79 } 80 81 @Override getClassInfo( Class clazz, Locatable upstream )82 public RuntimeNonElement getClassInfo( Class clazz, Locatable upstream ) { 83 return (RuntimeNonElement)super.getClassInfo(clazz,upstream); 84 } 85 86 @Override getClassInfo( Class clazz, boolean searchForSuperClass, Locatable upstream )87 public RuntimeNonElement getClassInfo( Class clazz, boolean searchForSuperClass, Locatable upstream ) { 88 return (RuntimeNonElement)super.getClassInfo(clazz,searchForSuperClass,upstream); 89 } 90 91 @Override createEnumLeafInfo(Class clazz, Locatable upstream)92 protected RuntimeEnumLeafInfoImpl createEnumLeafInfo(Class clazz, Locatable upstream) { 93 return new RuntimeEnumLeafInfoImpl(this,upstream,clazz); 94 } 95 96 @Override createClassInfo( Class clazz, Locatable upstream )97 protected RuntimeClassInfoImpl createClassInfo( Class clazz, Locatable upstream ) { 98 return new RuntimeClassInfoImpl(this,upstream,clazz); 99 } 100 101 @Override createElementInfo(RegistryInfoImpl<Type,Class,Field,Method> registryInfo, Method method)102 public RuntimeElementInfoImpl createElementInfo(RegistryInfoImpl<Type,Class,Field,Method> registryInfo, Method method) throws IllegalAnnotationException { 103 return new RuntimeElementInfoImpl(this,registryInfo, method); 104 } 105 106 @Override createArrayInfo(Locatable upstream, Type arrayType)107 public RuntimeArrayInfoImpl createArrayInfo(Locatable upstream, Type arrayType) { 108 return new RuntimeArrayInfoImpl(this, upstream, (Class)arrayType); 109 } 110 111 @Override createTypeInfoSet()112 protected RuntimeTypeInfoSetImpl createTypeInfoSet() { 113 return new RuntimeTypeInfoSetImpl(reader); 114 } 115 116 @Override link()117 public RuntimeTypeInfoSet link() { 118 return (RuntimeTypeInfoSet)super.link(); 119 } 120 121 /** 122 * Creates a {@link Transducer} given a reference. 123 * 124 * Used to implement {@link RuntimeNonElementRef#getTransducer()}. 125 * Shouldn't be called from anywhere else. 126 * 127 * TODO: this is not the proper place for this class to be in. 128 */ createTransducer(RuntimeNonElementRef ref)129 public static Transducer createTransducer(RuntimeNonElementRef ref) { 130 Transducer t = ref.getTarget().getTransducer(); 131 RuntimePropertyInfo src = ref.getSource(); 132 ID id = src.id(); 133 134 if(id==ID.IDREF) 135 return RuntimeBuiltinLeafInfoImpl.STRING; 136 137 if(id==ID.ID) 138 t = new IDTransducerImpl(t); 139 140 MimeType emt = src.getExpectedMimeType(); 141 if(emt!=null) 142 t = new MimeTypedTransducer(t,emt); 143 144 if(src.inlineBinaryData()) 145 t = new InlineBinaryTransducer(t); 146 147 if(src.getSchemaType()!=null) { 148 if (src.getSchemaType().equals(createXSSimpleType())) { 149 return RuntimeBuiltinLeafInfoImpl.STRING; 150 } 151 t = new SchemaTypeTransducer(t,src.getSchemaType()); 152 } 153 154 return t; 155 } 156 createXSSimpleType()157 private static QName createXSSimpleType() { 158 return new QName(WellKnownNamespace.XML_SCHEMA,"anySimpleType"); 159 } 160 161 /** 162 * Transducer implementation for ID. 163 * 164 * This transducer wraps another {@link Transducer} and adds 165 * handling for ID. 166 */ 167 private static final class IDTransducerImpl<ValueT> extends FilterTransducer<ValueT> { IDTransducerImpl(Transducer<ValueT> core)168 public IDTransducerImpl(Transducer<ValueT> core) { 169 super(core); 170 } 171 172 @Override parse(CharSequence lexical)173 public ValueT parse(CharSequence lexical) throws AccessorException, SAXException { 174 String value = WhiteSpaceProcessor.trim(lexical).toString(); 175 UnmarshallingContext.getInstance().addToIdTable(value); 176 return core.parse(value); 177 } 178 } 179 } 180