diff --git a/.gitignore b/.gitignore index 67145cd..3ddc59a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ +*.iml .classpath +.idea .project .settings target diff --git a/README.md b/README.md index e862a2d..2b8630b 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ -Android JAXB 2.2.7 +Android JAXB 2.3.1 ================== Description ----------- -This project creates an Android compatible JAXB 2.2.7 jar. +This project creates an Android compatible JAXB 2.3.1 jar. Conflicting classes in java.awt and javax.activation have been removed from the baseline. An uber-jar containing jaxb-api, jaxb-core, and jaxb-impl is packaged using the Maven shade plugin. diff --git a/pom.xml b/pom.xml index 5611b2a..aac60d3 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,9 @@ UTF-8 - 2.2.7 + 2.3.1 + 1.7 + 1.7 @@ -21,7 +23,7 @@ org.apache.maven.plugins maven-shade-plugin - 2.3 + 3.2.1 @@ -57,13 +59,13 @@ com.sun.xml.bind - jaxb-core + jaxb-impl ${jaxb.version} - provided + compile - com.sun.xml.bind - jaxb-impl + org.glassfish.jaxb + jaxb-runtime ${jaxb.version} compile diff --git a/src/main/java/com/sun/xml/bind/v2/model/impl/RuntimeBuiltinLeafInfoImpl.java b/src/main/java/com/sun/xml/bind/v2/model/impl/RuntimeBuiltinLeafInfoImpl.java index 5c1a4df..6068345 100644 --- a/src/main/java/com/sun/xml/bind/v2/model/impl/RuntimeBuiltinLeafInfoImpl.java +++ b/src/main/java/com/sun/xml/bind/v2/model/impl/RuntimeBuiltinLeafInfoImpl.java @@ -1,19 +1,19 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright (c) 1997-2013 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997-2017 Oracle and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can * obtain a copy of the License at - * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html - * or packager/legal/LICENSE.txt. See the License for the specific + * https://oss.oracle.com/licenses/CDDL+GPL-1.1 + * or LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each - * file and include the License file at packager/legal/LICENSE.txt. + * file and include the License file at LICENSE.txt. * * GPL Classpath Exception: * Oracle designates this particular file as subject to the "Classpath" @@ -49,6 +49,8 @@ import java.net.URI; import java.net.URISyntaxException; import java.net.URL; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; @@ -61,9 +63,7 @@ import javax.xml.bind.ValidationEvent; import javax.xml.bind.helpers.ValidationEventImpl; -import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeConstants; -import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.Duration; import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.namespace.QName; @@ -81,6 +81,9 @@ import com.sun.xml.bind.v2.runtime.output.Pcdata; import com.sun.xml.bind.v2.runtime.unmarshaller.Base64Data; import com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext; +import java.util.logging.Logger; +import com.sun.xml.bind.Util; +import java.util.logging.Level; import org.xml.sax.SAXException; @@ -93,7 +96,9 @@ * @author Kohsuke Kawaguchi */ public abstract class RuntimeBuiltinLeafInfoImpl extends BuiltinLeafInfoImpl - implements RuntimeBuiltinLeafInfo, Transducer { + implements RuntimeBuiltinLeafInfo, Transducer { + + private static final Logger logger = Util.getClassLogger(); private RuntimeBuiltinLeafInfoImpl(Class type, QName... typeNames) { super(type, typeNames); @@ -113,10 +118,6 @@ public boolean useNamespace() { return false; } - public final boolean isDefault() { - return true; - } - public void declareNamespace(T o, XMLSerializer w) throws AccessorException { } @@ -175,7 +176,7 @@ private static QName createXS(String typeName) { public static final RuntimeBuiltinLeafInfoImpl STRING; private static final String DATE = "date"; - + /** * List of all {@link RuntimeBuiltinLeafInfoImpl}s. * @@ -186,31 +187,40 @@ private static QName createXS(String typeName) { public static final List> builtinBeanInfos; public static final String MAP_ANYURI_TO_URI = "mapAnyUriToUri"; - + public static final String USE_OLD_GMONTH_MAPPING = "jaxb.ri.useOldGmonthMapping"; + static { - QName[] qnames = (System.getProperty(MAP_ANYURI_TO_URI) == null) ? new QName[] { - createXS("string"), - createXS("anySimpleType"), - createXS("normalizedString"), - createXS("anyURI"), - createXS("token"), - createXS("language"), - createXS("Name"), - createXS("NCName"), - createXS("NMTOKEN"), - createXS("ENTITY")} - : - new QName[] { - createXS("string"), - createXS("anySimpleType"), - createXS("normalizedString"), - createXS("token"), - createXS("language"), - createXS("Name"), - createXS("NCName"), - createXS("NMTOKEN"), - createXS("ENTITY")}; + String MAP_ANYURI_TO_URI_VALUE = AccessController.doPrivileged( + new PrivilegedAction() { + @Override + public String run() { + return System.getProperty(MAP_ANYURI_TO_URI); + } + } + ); + QName[] qnames = (MAP_ANYURI_TO_URI_VALUE == null) ? new QName[] { + createXS("string"), + createXS("anySimpleType"), + createXS("normalizedString"), + createXS("anyURI"), + createXS("token"), + createXS("language"), + createXS("Name"), + createXS("NCName"), + createXS("NMTOKEN"), + createXS("ENTITY")} + : + new QName[] { + createXS("string"), + createXS("anySimpleType"), + createXS("normalizedString"), + createXS("token"), + createXS("language"), + createXS("Name"), + createXS("NCName"), + createXS("NMTOKEN"), + createXS("ENTITY")}; STRING = new StringImplImpl(String.class, qnames); @@ -233,238 +243,239 @@ private static QName createXS(String typeName) { secondary bindings */ secondaryList.add( - new StringImpl(Character.class, createXS("unsignedShort")) { - public Character parse(CharSequence text) { - // TODO.checkSpec("default mapping for char is not defined yet"); - return (char)DatatypeConverterImpl._parseInt(text); - } - public String print(Character v) { - return Integer.toString(v); - } - }); - secondaryList.add( - new StringImpl(Calendar.class, DatatypeConstants.DATETIME) { - public Calendar parse(CharSequence text) { - return DatatypeConverterImpl._parseDateTime(text.toString()); - } - public String print(Calendar v) { - return DatatypeConverterImpl._printDateTime(v); - } - }); + new StringImpl(Character.class, createXS("unsignedShort")) { + public Character parse(CharSequence text) { + // TODO.checkSpec("default mapping for char is not defined yet"); + return (char)DatatypeConverterImpl._parseInt(text); + } + public String print(Character v) { + return Integer.toString(v); + } + }); secondaryList.add( - new StringImpl(GregorianCalendar.class, DatatypeConstants.DATETIME) { - public GregorianCalendar parse(CharSequence text) { - return DatatypeConverterImpl._parseDateTime(text.toString()); - } - public String print(GregorianCalendar v) { - return DatatypeConverterImpl._printDateTime(v); - } - }); + new StringImpl(Calendar.class, DatatypeConstants.DATETIME) { + public Calendar parse(CharSequence text) { + return DatatypeConverterImpl._parseDateTime(text.toString()); + } + public String print(Calendar v) { + return DatatypeConverterImpl._printDateTime(v); + } + }); secondaryList.add( - new StringImpl(Date.class, DatatypeConstants.DATETIME) { - public Date parse(CharSequence text) { - return DatatypeConverterImpl._parseDateTime(text.toString()).getTime(); - } - public String print(Date v) { - XMLSerializer xs = XMLSerializer.getInstance(); - QName type = xs.getSchemaType(); - GregorianCalendar cal = new GregorianCalendar(0,0,0); - cal.setTime(v); - if ((type != null) && (WellKnownNamespace.XML_SCHEMA.equals(type.getNamespaceURI())) && - DATE.equals(type.getLocalPart())) { - return DatatypeConverterImpl._printDate(cal); - } else { - return DatatypeConverterImpl._printDateTime(cal); + new StringImpl(GregorianCalendar.class, DatatypeConstants.DATETIME) { + public GregorianCalendar parse(CharSequence text) { + return DatatypeConverterImpl._parseDateTime(text.toString()); } - } - }); + public String print(GregorianCalendar v) { + return DatatypeConverterImpl._printDateTime(v); + } + }); secondaryList.add( - new StringImpl(File.class, createXS("string")) { - public File parse(CharSequence text) { - return new File(WhiteSpaceProcessor.trim(text).toString()); - } - public String print(File v) { - return v.getPath(); - } - }); + new StringImpl(Date.class, DatatypeConstants.DATETIME) { + public Date parse(CharSequence text) { + return DatatypeConverterImpl._parseDateTime(text.toString()).getTime(); + } + public String print(Date v) { + XMLSerializer xs = XMLSerializer.getInstance(); + QName type = xs.getSchemaType(); + GregorianCalendar cal = new GregorianCalendar(0,0,0); + cal.setTime(v); + if ((type != null) && (WellKnownNamespace.XML_SCHEMA.equals(type.getNamespaceURI())) && + DATE.equals(type.getLocalPart())) { + return DatatypeConverterImpl._printDate(cal); + } else { + return DatatypeConverterImpl._printDateTime(cal); + } + } + }); secondaryList.add( - new StringImpl(URL.class, createXS("anyURI")) { - public URL parse(CharSequence text) throws SAXException { - TODO.checkSpec("JSR222 Issue #42"); - try { - return new URL(WhiteSpaceProcessor.trim(text).toString()); - } catch (MalformedURLException e) { - UnmarshallingContext.getInstance().handleError(e); - return null; + new StringImpl(File.class, createXS("string")) { + public File parse(CharSequence text) { + return new File(WhiteSpaceProcessor.trim(text).toString()); } - } - public String print(URL v) { - return v.toExternalForm(); - } - }); - if (System.getProperty(MAP_ANYURI_TO_URI) == null) { - secondaryList.add( - new StringImpl(URI.class, createXS("string")) { - public URI parse(CharSequence text) throws SAXException { + public String print(File v) { + return v.getPath(); + } + }); + secondaryList.add( + new StringImpl(URL.class, createXS("anyURI")) { + public URL parse(CharSequence text) throws SAXException { + TODO.checkSpec("JSR222 Issue #42"); try { - return new URI(text.toString()); - } catch (URISyntaxException e) { + return new URL(WhiteSpaceProcessor.trim(text).toString()); + } catch (MalformedURLException e) { UnmarshallingContext.getInstance().handleError(e); return null; } } - - public String print(URI v) { - return v.toString(); + public String print(URL v) { + return v.toExternalForm(); } }); + if (MAP_ANYURI_TO_URI_VALUE == null) { + secondaryList.add( + new StringImpl(URI.class, createXS("string")) { + public URI parse(CharSequence text) throws SAXException { + try { + return new URI(text.toString()); + } catch (URISyntaxException e) { + UnmarshallingContext.getInstance().handleError(e); + return null; + } + } + + public String print(URI v) { + return v.toString(); + } + }); } secondaryList.add( - new StringImpl(Class.class, createXS("string")) { - public Class parse(CharSequence text) throws SAXException { - TODO.checkSpec("JSR222 Issue #42"); - try { - String name = WhiteSpaceProcessor.trim(text).toString(); - ClassLoader cl = UnmarshallingContext.getInstance().classLoader; - if(cl==null) - cl = Thread.currentThread().getContextClassLoader(); - - if(cl!=null) - return cl.loadClass(name); - else - return Class.forName(name); - } catch (ClassNotFoundException e) { - UnmarshallingContext.getInstance().handleError(e); - return null; + new StringImpl(Class.class, createXS("string")) { + public Class parse(CharSequence text) throws SAXException { + TODO.checkSpec("JSR222 Issue #42"); + try { + String name = WhiteSpaceProcessor.trim(text).toString(); + ClassLoader cl = UnmarshallingContext.getInstance().classLoader; + if(cl==null) + cl = Thread.currentThread().getContextClassLoader(); + + if(cl!=null) + return cl.loadClass(name); + else + return Class.forName(name); + } catch (ClassNotFoundException e) { + UnmarshallingContext.getInstance().handleError(e); + return null; + } } - } - public String print(Class v) { - return v.getName(); - } - }); + public String print(Class v) { + return v.getName(); + } + }); /* classes that map to base64Binary / MTOM related classes. a part of the secondary binding. */ secondaryList.add( - new StringImpl(XMLGregorianCalendar.class, - createXS("anySimpleType"), - DatatypeConstants.DATE, - DatatypeConstants.DATETIME, - DatatypeConstants.TIME, - DatatypeConstants.GMONTH, - DatatypeConstants.GDAY, - DatatypeConstants.GYEAR, - DatatypeConstants.GYEARMONTH, - DatatypeConstants.GMONTHDAY + new StringImpl(XMLGregorianCalendar.class, + createXS("anySimpleType"), + DatatypeConstants.DATE, + DatatypeConstants.DATETIME, + DatatypeConstants.TIME, + DatatypeConstants.GMONTH, + DatatypeConstants.GDAY, + DatatypeConstants.GYEAR, + DatatypeConstants.GYEARMONTH, + DatatypeConstants.GMONTHDAY ) { - public String print(XMLGregorianCalendar cal) { - XMLSerializer xs = XMLSerializer.getInstance(); - - QName type = xs.getSchemaType(); - if (type != null) { - try { - checkXmlGregorianCalendarFieldRef(type, cal); - String format = xmlGregorianCalendarFormatString.get(type); - if (format != null) { - return format(format, cal); + public String print(XMLGregorianCalendar cal) { + XMLSerializer xs = XMLSerializer.getInstance(); + + QName type = xs.getSchemaType(); + if (type != null) { + try { + checkXmlGregorianCalendarFieldRef(type, cal); + String format = xmlGregorianCalendarFormatString.get(type); + if (format != null) { + return format(format, cal); + } + } catch (javax.xml.bind.MarshalException e) { + // see issue 649 + xs.handleEvent(new ValidationEventImpl(ValidationEvent.WARNING, e.getMessage(), + xs.getCurrentLocation(null) )); + return ""; } - } catch (javax.xml.bind.MarshalException e) { - // see issue 649 - xs.handleEvent(new ValidationEventImpl(ValidationEvent.WARNING, e.getMessage(), - xs.getCurrentLocation(null) )); - return ""; } + return cal.toXMLFormat(); } - return cal.toXMLFormat(); - } - public XMLGregorianCalendar parse(CharSequence lexical) throws SAXException { - try { - return datatypeFactory.newXMLGregorianCalendar(lexical.toString().trim()); // (.trim() - issue 396) - } catch (Exception e) { - UnmarshallingContext.getInstance().handleError(e); - return null; + public XMLGregorianCalendar parse(CharSequence lexical) throws SAXException { + try { + return DatatypeConverterImpl.getDatatypeFactory() + .newXMLGregorianCalendar(lexical.toString().trim()); // (.trim() - issue 396) + } catch (Exception e) { + UnmarshallingContext.getInstance().handleError(e); + return null; + } } - } - // code duplicated from JAXP RI 1.3. See 6277586 - private String format( String format, XMLGregorianCalendar value ) { - StringBuilder buf = new StringBuilder(); - int fidx=0,flen=format.length(); + // code duplicated from JAXP RI 1.3. See 6277586 + private String format( String format, XMLGregorianCalendar value ) { + StringBuilder buf = new StringBuilder(); + int fidx=0,flen=format.length(); - while(fidx> primaryList = new ArrayList>(); @@ -474,200 +485,202 @@ public QName getTypeName(XMLGregorianCalendar cal) { primaryList.add(STRING); primaryList.add(new StringImpl(Boolean.class, createXS("boolean") - ) { - public Boolean parse(CharSequence text) { - return DatatypeConverterImpl._parseBoolean(text); - } + ) { + public Boolean parse(CharSequence text) { + return DatatypeConverterImpl._parseBoolean(text); + } - public String print(Boolean v) { - return v.toString(); - } - }); + public String print(Boolean v) { + return v.toString(); + } + }); primaryList.add(new PcdataImpl(byte[].class, createXS("base64Binary"), createXS("hexBinary") - ) { - public byte[] parse(CharSequence text) { - return decodeBase64(text); - } + ) { + public byte[] parse(CharSequence text) { + return decodeBase64(text); + } - public Base64Data print(byte[] v) { - XMLSerializer w = XMLSerializer.getInstance(); - Base64Data bd = new Base64Data(); - String mimeType = w.getXMIMEContentType(); - bd.set(v,mimeType); - return bd; - } - }); + public Base64Data print(byte[] v) { + XMLSerializer w = XMLSerializer.getInstance(); + Base64Data bd = new Base64Data(); + String mimeType = w.getXMIMEContentType(); + bd.set(v,mimeType); + return bd; + } + }); primaryList.add(new StringImpl(Byte.class, createXS("byte") - ) { - public Byte parse(CharSequence text) { - return DatatypeConverterImpl._parseByte(text); - } + ) { + public Byte parse(CharSequence text) { + return DatatypeConverterImpl._parseByte(text); + } - public String print(Byte v) { - return DatatypeConverterImpl._printByte(v); - } - }); + public String print(Byte v) { + return DatatypeConverterImpl._printByte(v); + } + }); primaryList.add(new StringImpl(Short.class, createXS("short"), createXS("unsignedByte") - ) { - public Short parse(CharSequence text) { - return DatatypeConverterImpl._parseShort(text); - } + ) { + public Short parse(CharSequence text) { + return DatatypeConverterImpl._parseShort(text); + } - public String print(Short v) { - return DatatypeConverterImpl._printShort(v); - } - }); + public String print(Short v) { + return DatatypeConverterImpl._printShort(v); + } + }); primaryList.add(new StringImpl(Integer.class, createXS("int"), createXS("unsignedShort") - ) { - public Integer parse(CharSequence text) { - return DatatypeConverterImpl._parseInt(text); - } + ) { + public Integer parse(CharSequence text) { + return DatatypeConverterImpl._parseInt(text); + } - public String print(Integer v) { - return DatatypeConverterImpl._printInt(v); - } - }); + public String print(Integer v) { + return DatatypeConverterImpl._printInt(v); + } + }); primaryList.add( - new StringImpl(Long.class, - createXS("long"), - createXS("unsignedInt") + new StringImpl(Long.class, + createXS("long"), + createXS("unsignedInt") ) { - public Long parse(CharSequence text) { - return DatatypeConverterImpl._parseLong(text); - } + public Long parse(CharSequence text) { + return DatatypeConverterImpl._parseLong(text); + } - public String print(Long v) { - return DatatypeConverterImpl._printLong(v); - } - }); + public String print(Long v) { + return DatatypeConverterImpl._printLong(v); + } + }); primaryList.add( - new StringImpl(Float.class, - createXS("float") + new StringImpl(Float.class, + createXS("float") ) { - public Float parse(CharSequence text) { - return DatatypeConverterImpl._parseFloat(text.toString()); - } + public Float parse(CharSequence text) { + return DatatypeConverterImpl._parseFloat(text.toString()); + } - public String print(Float v) { - return DatatypeConverterImpl._printFloat(v); - } - }); + public String print(Float v) { + return DatatypeConverterImpl._printFloat(v); + } + }); primaryList.add( - new StringImpl(Double.class, - createXS("double") + new StringImpl(Double.class, + createXS("double") ) { - public Double parse(CharSequence text) { - return DatatypeConverterImpl._parseDouble(text); - } + public Double parse(CharSequence text) { + return DatatypeConverterImpl._parseDouble(text); + } - public String print(Double v) { - return DatatypeConverterImpl._printDouble(v); - } - }); + public String print(Double v) { + return DatatypeConverterImpl._printDouble(v); + } + }); primaryList.add( - new StringImpl(BigInteger.class, - createXS("integer"), - createXS("positiveInteger"), - createXS("negativeInteger"), - createXS("nonPositiveInteger"), - createXS("nonNegativeInteger"), - createXS("unsignedLong") + new StringImpl(BigInteger.class, + createXS("integer"), + createXS("positiveInteger"), + createXS("negativeInteger"), + createXS("nonPositiveInteger"), + createXS("nonNegativeInteger"), + createXS("unsignedLong") ) { - public BigInteger parse(CharSequence text) { - return DatatypeConverterImpl._parseInteger(text); - } + public BigInteger parse(CharSequence text) { + return DatatypeConverterImpl._parseInteger(text); + } - public String print(BigInteger v) { - return DatatypeConverterImpl._printInteger(v); - } - }); + public String print(BigInteger v) { + return DatatypeConverterImpl._printInteger(v); + } + }); primaryList.add( - new StringImpl(BigDecimal.class, - createXS("decimal") + new StringImpl(BigDecimal.class, + createXS("decimal") ) { - public BigDecimal parse(CharSequence text) { - return DatatypeConverterImpl._parseDecimal(text.toString()); - } + public BigDecimal parse(CharSequence text) { + return DatatypeConverterImpl._parseDecimal(text.toString()); + } - public String print(BigDecimal v) { - return DatatypeConverterImpl._printDecimal(v); + public String print(BigDecimal v) { + return DatatypeConverterImpl._printDecimal(v); + } } - }); + ); primaryList.add( - new StringImpl(QName.class, - createXS("QName") + new StringImpl(QName.class, + createXS("QName") ) { - public QName parse(CharSequence text) throws SAXException { - try { - return DatatypeConverterImpl._parseQName(text.toString(),UnmarshallingContext.getInstance()); - } catch (IllegalArgumentException e) { - UnmarshallingContext.getInstance().handleError(e); - return null; - } - } - - public String print(QName v) { - return DatatypeConverterImpl._printQName(v,XMLSerializer.getInstance().getNamespaceContext()); - } - - @Override - public boolean useNamespace() { - return true; - } - - @Override - public void declareNamespace(QName v, XMLSerializer w) { - w.getNamespaceContext().declareNamespace(v.getNamespaceURI(),v.getPrefix(),false); - } - }); - if (System.getProperty(MAP_ANYURI_TO_URI) != null) { - primaryList.add( - new StringImpl(URI.class, createXS("anyURI")) { - public URI parse(CharSequence text) throws SAXException { + public QName parse(CharSequence text) throws SAXException { try { - return new URI(text.toString()); - } catch (URISyntaxException e) { + return DatatypeConverterImpl._parseQName(text.toString(),UnmarshallingContext.getInstance()); + } catch (IllegalArgumentException e) { UnmarshallingContext.getInstance().handleError(e); return null; } } - public String print(URI v) { - return v.toString(); + public String print(QName v) { + return DatatypeConverterImpl._printQName(v,XMLSerializer.getInstance().getNamespaceContext()); + } + + @Override + public boolean useNamespace() { + return true; + } + + @Override + public void declareNamespace(QName v, XMLSerializer w) { + w.getNamespaceContext().declareNamespace(v.getNamespaceURI(),v.getPrefix(),false); } }); + if (MAP_ANYURI_TO_URI_VALUE != null) { + primaryList.add( + new StringImpl(URI.class, createXS("anyURI")) { + public URI parse(CharSequence text) throws SAXException { + try { + return new URI(text.toString()); + } catch (URISyntaxException e) { + UnmarshallingContext.getInstance().handleError(e); + return null; + } + } + + public String print(URI v) { + return v.toString(); + } + }); } primaryList.add( - new StringImpl(Duration.class, createXS("duration")) { - public String print(Duration duration) { - return duration.toString(); - } + new StringImpl(Duration.class, createXS("duration")) { + public String print(Duration duration) { + return duration.toString(); + } - public Duration parse(CharSequence lexical) { - TODO.checkSpec("JSR222 Issue #42"); - return datatypeFactory.newDuration(lexical.toString()); + public Duration parse(CharSequence lexical) { + TODO.checkSpec("JSR222 Issue #42"); + return DatatypeConverterImpl.getDatatypeFactory().newDuration(lexical.toString()); + } } - }); + ); primaryList.add( - new StringImpl(Void.class) { - // 'void' binding isn't defined by the spec, but when the JAX-RPC processes user-defined - // methods like "int actionFoo()", they need this pseudo-void property. + new StringImpl(Void.class) { + // 'void' binding isn't defined by the spec, but when the JAX-RPC processes user-defined + // methods like "int actionFoo()", they need this pseudo-void property. - public String print(Void value) { - return ""; - } + public String print(Void value) { + return ""; + } - public Void parse(CharSequence lexical) { - return null; - } - }); + public Void parse(CharSequence lexical) { + return null; + } + }); List> l = new ArrayList>(secondaryList.size()+primaryList.size()+1); l.addAll(secondaryList); @@ -693,76 +706,61 @@ private static byte[] decodeBase64(CharSequence text) { } } - - /** - * Cached instance of {@link DatatypeFactory} to create - * {@link XMLGregorianCalendar} and {@link Duration}. - */ - private static final DatatypeFactory datatypeFactory = init(); - - private static DatatypeFactory init() { - try { - return DatatypeFactory.newInstance(); - } catch (DatatypeConfigurationException e) { - throw new Error(Messages.FAILED_TO_INITIALE_DATATYPE_FACTORY.format(),e); + private static void checkXmlGregorianCalendarFieldRef(QName type, + XMLGregorianCalendar cal)throws javax.xml.bind.MarshalException{ + StringBuilder buf = new StringBuilder(); + int bitField = xmlGregorianCalendarFieldRef.get(type); + final int l = 0x1; + int pos = 0; + while (bitField != 0x0){ + int bit = bitField & l; + bitField >>>= 4; + pos++; + + if (bit == 1) { + switch(pos){ + case 1: + if (cal.getSecond() == DatatypeConstants.FIELD_UNDEFINED){ + buf.append(" ").append(Messages.XMLGREGORIANCALENDAR_SEC); + } + break; + case 2: + if (cal.getMinute() == DatatypeConstants.FIELD_UNDEFINED){ + buf.append(" ").append(Messages.XMLGREGORIANCALENDAR_MIN); + } + break; + case 3: + if (cal.getHour() == DatatypeConstants.FIELD_UNDEFINED){ + buf.append(" ").append(Messages.XMLGREGORIANCALENDAR_HR); + } + break; + case 4: + if (cal.getDay() == DatatypeConstants.FIELD_UNDEFINED){ + buf.append(" ").append(Messages.XMLGREGORIANCALENDAR_DAY); + } + break; + case 5: + if (cal.getMonth() == DatatypeConstants.FIELD_UNDEFINED){ + buf.append(" ").append(Messages.XMLGREGORIANCALENDAR_MONTH); + } + break; + case 6: + if (cal.getYear() == DatatypeConstants.FIELD_UNDEFINED){ + buf.append(" ").append(Messages.XMLGREGORIANCALENDAR_YEAR); + } + break; + case 7: // ignore timezone setting + break; + } + } + } + if (buf.length() > 0){ + throw new javax.xml.bind.MarshalException( + Messages.XMLGREGORIANCALENDAR_INVALID.format(type.getLocalPart()) + + buf.toString()); } } - private static void checkXmlGregorianCalendarFieldRef(QName type, - XMLGregorianCalendar cal)throws javax.xml.bind.MarshalException{ - StringBuilder buf = new StringBuilder(); - int bitField = xmlGregorianCalendarFieldRef.get(type); - final int l = 0x1; - int pos = 0; - while (bitField != 0x0){ - int bit = bitField & l; - bitField >>>= 4; - pos++; - - if (bit == 1) { - switch(pos){ - case 1: - if (cal.getSecond() == DatatypeConstants.FIELD_UNDEFINED){ - buf.append(" ").append(Messages.XMLGREGORIANCALENDAR_SEC); - } - break; - case 2: - if (cal.getMinute() == DatatypeConstants.FIELD_UNDEFINED){ - buf.append(" ").append(Messages.XMLGREGORIANCALENDAR_MIN); - } - break; - case 3: - if (cal.getHour() == DatatypeConstants.FIELD_UNDEFINED){ - buf.append(" ").append(Messages.XMLGREGORIANCALENDAR_HR); - } - break; - case 4: - if (cal.getDay() == DatatypeConstants.FIELD_UNDEFINED){ - buf.append(" ").append(Messages.XMLGREGORIANCALENDAR_DAY); - } - break; - case 5: - if (cal.getMonth() == DatatypeConstants.FIELD_UNDEFINED){ - buf.append(" ").append(Messages.XMLGREGORIANCALENDAR_MONTH); - } - break; - case 6: - if (cal.getYear() == DatatypeConstants.FIELD_UNDEFINED){ - buf.append(" ").append(Messages.XMLGREGORIANCALENDAR_YEAR); - } - break; - case 7: // ignore timezone setting - break; - } - } - } - if (buf.length() > 0){ - throw new javax.xml.bind.MarshalException( - Messages.XMLGREGORIANCALENDAR_INVALID.format(type.getLocalPart()) - + buf.toString()); - } - } - /** * Format string for the {@link XMLGregorianCalendar}. */ @@ -774,37 +772,50 @@ private static void checkXmlGregorianCalendarFieldRef(QName type, m.put(DatatypeConstants.DATETIME, "%Y-%M-%DT%h:%m:%s"+ "%z"); m.put(DatatypeConstants.DATE, "%Y-%M-%D" +"%z"); m.put(DatatypeConstants.TIME, "%h:%m:%s"+ "%z"); - m.put(DatatypeConstants.GMONTH, "--%M--%z"); + final String oldGmonthMappingProperty = AccessController.doPrivileged(new PrivilegedAction() { + @Override + public String run() { + return System.getProperty(USE_OLD_GMONTH_MAPPING); + } + }); + if (oldGmonthMappingProperty == null) { + m.put(DatatypeConstants.GMONTH, "--%M%z"); // E2-12 Error. http://www.w3.org/2001/05/xmlschema-errata#e2-12 + } else { // backw. compatibility + if (logger.isLoggable(Level.FINE)) { + logger.log(Level.FINE, "Old GMonth mapping used."); + } + m.put(DatatypeConstants.GMONTH, "--%M--%z"); + } m.put(DatatypeConstants.GDAY, "---%D" + "%z"); m.put(DatatypeConstants.GYEAR, "%Y" + "%z"); m.put(DatatypeConstants.GYEARMONTH, "%Y-%M" + "%z"); m.put(DatatypeConstants.GMONTHDAY, "--%M-%D" +"%z"); } - /** - * Field designations for XMLGregorianCalendar format string. - * sec 0x0000001 - * min 0x0000010 - * hrs 0x0000100 - * day 0x0001000 - * month 0x0010000 - * year 0x0100000 - * timezone 0x1000000 - */ - private static final Map xmlGregorianCalendarFieldRef = - new HashMap(); - static { - Map f = xmlGregorianCalendarFieldRef; - f.put(DatatypeConstants.DATETIME, 0x1111111); - f.put(DatatypeConstants.DATE, 0x1111000); - f.put(DatatypeConstants.TIME, 0x1000111); - f.put(DatatypeConstants.GDAY, 0x1001000); - f.put(DatatypeConstants.GMONTH, 0x1010000); - f.put(DatatypeConstants.GYEAR, 0x1100000); - f.put(DatatypeConstants.GYEARMONTH, 0x1110000); - f.put(DatatypeConstants.GMONTHDAY, 0x1011000); - } - + /** + * Field designations for XMLGregorianCalendar format string. + * sec 0x0000001 + * min 0x0000010 + * hrs 0x0000100 + * day 0x0001000 + * month 0x0010000 + * year 0x0100000 + * timezone 0x1000000 + */ + private static final Map xmlGregorianCalendarFieldRef = + new HashMap(); + static { + Map f = xmlGregorianCalendarFieldRef; + f.put(DatatypeConstants.DATETIME, 0x1111111); + f.put(DatatypeConstants.DATE, 0x1111000); + f.put(DatatypeConstants.TIME, 0x1000111); + f.put(DatatypeConstants.GDAY, 0x1001000); + f.put(DatatypeConstants.GMONTH, 0x1010000); + f.put(DatatypeConstants.GYEAR, 0x1100000); + f.put(DatatypeConstants.GYEARMONTH, 0x1110000); + f.put(DatatypeConstants.GMONTHDAY, 0x1011000); + } + /** * {@link RuntimeBuiltinLeafInfoImpl} for {@link UUID}. * diff --git a/src/main/java/com/sun/xml/bind/v2/runtime/JAXBContextImpl.java b/src/main/java/com/sun/xml/bind/v2/runtime/JAXBContextImpl.java deleted file mode 100644 index bed49c4..0000000 --- a/src/main/java/com/sun/xml/bind/v2/runtime/JAXBContextImpl.java +++ /dev/null @@ -1,1179 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common Development - * and Distribution License("CDDL") (collectively, the "License"). You - * may not use this file except in compliance with the License. You can - * obtain a copy of the License at - * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html - * or packager/legal/LICENSE.txt. See the License for the specific - * language governing permissions and limitations under the License. - * - * When distributing the software, include this License Header Notice in each - * file and include the License file at packager/legal/LICENSE.txt. - * - * GPL Classpath Exception: - * Oracle designates this particular file as subject to the "Classpath" - * exception as provided by Oracle in the GPL Version 2 section of the License - * file that accompanied this code. - * - * Modifications: - * If applicable, add the following below the License Header, with the fields - * enclosed by brackets [] replaced by your own identifying information: - * "Portions Copyright [year] [name of copyright owner]" - * - * Contributor(s): - * If you wish your version of this file to be governed by only the CDDL or - * only the GPL Version 2, indicate your decision by adding "[Contributor] - * elects to include this software in this distribution under the [CDDL or GPL - * Version 2] license." If you don't indicate a single choice of license, a - * recipient has the option to distribute your version of this file under - * either the CDDL, the GPL Version 2 or to extend the choice of license to - * its licensees as provided above. However, if you add GPL Version 2 code - * and therefore, elected the GPL Version 2 license, then the option applies - * only if the new code is made subject to such option by the copyright - * holder. - */ - -package com.sun.xml.bind.v2.runtime; - -import java.io.IOException; -import java.lang.ref.WeakReference; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Type; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.TreeSet; -import javax.xml.bind.Binder; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBElement; -import javax.xml.bind.JAXBException; -import javax.xml.bind.JAXBIntrospector; -import javax.xml.bind.Marshaller; -import javax.xml.bind.SchemaOutputResolver; -import javax.xml.bind.Unmarshaller; -import javax.xml.bind.Validator; -import javax.xml.bind.annotation.XmlAttachmentRef; -import javax.xml.bind.annotation.XmlList; -import javax.xml.bind.annotation.XmlNs; -import javax.xml.bind.annotation.XmlSchema; -import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; -import javax.xml.namespace.QName; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.FactoryConfigurationError; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.Result; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerConfigurationException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.sax.SAXResult; -import javax.xml.transform.sax.SAXTransformerFactory; -import javax.xml.transform.sax.TransformerHandler; - -import com.sun.istack.NotNull; -import com.sun.istack.Pool; -import com.sun.xml.bind.v2.WellKnownNamespace; -import com.sun.xml.bind.api.AccessorException; -import com.sun.xml.bind.api.Bridge; -import com.sun.xml.bind.api.BridgeContext; -import com.sun.xml.bind.api.CompositeStructure; -import com.sun.xml.bind.api.ErrorListener; -import com.sun.xml.bind.api.JAXBRIContext; -import com.sun.xml.bind.api.RawAccessor; -import com.sun.xml.bind.api.TypeReference; -import com.sun.xml.bind.unmarshaller.DOMScanner; -import com.sun.xml.bind.util.Which; -import com.sun.xml.bind.v2.model.annotation.RuntimeAnnotationReader; -import com.sun.xml.bind.v2.model.annotation.RuntimeInlineAnnotationReader; -import com.sun.xml.bind.v2.model.core.Adapter; -import com.sun.xml.bind.v2.model.core.NonElement; -import com.sun.xml.bind.v2.model.core.Ref; -import com.sun.xml.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl; -import com.sun.xml.bind.v2.model.impl.RuntimeModelBuilder; -import com.sun.xml.bind.v2.model.nav.Navigator; -import com.sun.xml.bind.v2.model.nav.ReflectionNavigator; -import com.sun.xml.bind.v2.model.runtime.RuntimeArrayInfo; -import com.sun.xml.bind.v2.model.runtime.RuntimeBuiltinLeafInfo; -import com.sun.xml.bind.v2.model.runtime.RuntimeClassInfo; -import com.sun.xml.bind.v2.model.runtime.RuntimeElementInfo; -import com.sun.xml.bind.v2.model.runtime.RuntimeEnumLeafInfo; -import com.sun.xml.bind.v2.model.runtime.RuntimeLeafInfo; -import com.sun.xml.bind.v2.model.runtime.RuntimeTypeInfo; -import com.sun.xml.bind.v2.model.runtime.RuntimeTypeInfoSet; -import com.sun.xml.bind.v2.runtime.output.Encoded; -import com.sun.xml.bind.v2.runtime.property.AttributeProperty; -import com.sun.xml.bind.v2.runtime.property.Property; -import com.sun.xml.bind.v2.runtime.reflect.Accessor; -import com.sun.xml.bind.v2.runtime.unmarshaller.Loader; -import com.sun.xml.bind.v2.runtime.unmarshaller.TagName; -import com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl; -import com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext; -import com.sun.xml.bind.v2.schemagen.XmlSchemaGenerator; -import com.sun.xml.bind.v2.util.EditDistance; -import com.sun.xml.bind.v2.util.QNameMap; -import com.sun.xml.bind.v2.util.XmlFactory; -import com.sun.xml.txw2.output.ResultFactory; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; -import org.xml.sax.helpers.DefaultHandler; - -/** - * This class provides the implementation of JAXBContext. - * - */ -public final class JAXBContextImpl extends JAXBRIContext { - - /** - * All the bridge classes. - */ - private final Map bridges = new LinkedHashMap(); - - /** - * Shared instance of {@link TransformerFactory}. - * Lock before use, because a {@link TransformerFactory} is not thread-safe - * whereas {@link JAXBContextImpl} is. - * Lazily created. - */ - private volatile static SAXTransformerFactory tf; - - /** - * Shared instance of {@link DocumentBuilder}. - * Lock before use. Lazily created. - */ - private static DocumentBuilder db; - - private final QNameMap rootMap = new QNameMap(); - private final HashMap typeMap = new HashMap(); - - /** - * Map from JAXB-bound {@link Class} to its {@link JaxBeanInfo}. - */ - private final Map beanInfoMap = new LinkedHashMap(); - - /** - * All created {@link JaxBeanInfo}s. - * Updated from each {@link JaxBeanInfo}s constructors to avoid infinite recursion - * for a cyclic reference. - * - *

- * This map is only used while the {@link JAXBContextImpl} is built and set to null - * to avoid keeping references too long. - */ - protected Map beanInfos = new LinkedHashMap(); - - private final Map> elements = new LinkedHashMap>(); - - /** - * Pool of {@link Marshaller}s. - */ - public final Pool marshallerPool = new Pool.Impl() { - protected @NotNull Marshaller create() { - return createMarshaller(); - } - }; - - public final Pool unmarshallerPool = new Pool.Impl() { - protected @NotNull Unmarshaller create() { - return createUnmarshaller(); - } - }; - - /** - * Used to assign indices to known names in this grammar. - * Reset to null once the build phase is completed. - */ - public NameBuilder nameBuilder = new NameBuilder(); - - /** - * Keeps the list of known names. - * This field is set once the build pahse is completed. - */ - public final NameList nameList; - - /** - * Input to the JAXBContext.newInstance, so that we can recreate - * {@link RuntimeTypeInfoSet} whenever we need. - */ - private final String defaultNsUri; - private final Class[] classes; - - /** - * true to reorder attributes lexicographically in preparation of the c14n support. - */ - protected final boolean c14nSupport; - - /** - * Flag that user has provided a custom AccessorFactory for JAXB to use - */ - public final boolean xmlAccessorFactorySupport; - - /** - * @see JAXBRIContext#TREAT_EVERYTHING_NILLABLE - */ - public final boolean allNillable; - - /** - * Store properties, so that they can be recovered in the run (is here because of JSON encoding of Jersey). - */ - public final boolean retainPropertyInfo; - - /** - * Suppress reflection accessor warnings. - */ - public final boolean supressAccessorWarnings; - - /** - * Improved xsi type handling. - */ - public final boolean improvedXsiTypeHandling; - - /** - * Disable security processing. - */ - public final boolean disableSecurityProcessing; - - private WeakReference typeInfoSetCache; - - private @NotNull RuntimeAnnotationReader annotationReader; - - private /*almost final*/ boolean hasSwaRef; - private final @NotNull Map subclassReplacements; - - /** - * If true, we aim for faster {@link JAXBContext} instantiation performance, - * instead of going after efficient sustained unmarshalling/marshalling performance. - * - * @since 2.0.4 - */ - public final boolean fastBoot; - - private Set xmlNsSet = null; - - /** - * Returns declared XmlNs annotations (from package-level annotation XmlSchema - * - * @return set of all present XmlNs annotations - */ - public Set getXmlNsSet() { - return xmlNsSet; - } - - private JAXBContextImpl(JAXBContextBuilder builder) throws JAXBException { - - this.defaultNsUri = builder.defaultNsUri; - this.retainPropertyInfo = builder.retainPropertyInfo; - this.annotationReader = builder.annotationReader; - this.subclassReplacements = builder.subclassReplacements; - this.c14nSupport = builder.c14nSupport; - this.classes = builder.classes; - this.xmlAccessorFactorySupport = builder.xmlAccessorFactorySupport; - this.allNillable = builder.allNillable; - this.supressAccessorWarnings = builder.supressAccessorWarnings; - this.improvedXsiTypeHandling = builder.improvedXsiTypeHandling; - this.disableSecurityProcessing = builder.disableSecurityProcessing; - - Collection typeRefs = builder.typeRefs; - - boolean fastB; - try { - fastB = Boolean.getBoolean(JAXBContextImpl.class.getName()+".fastBoot"); - } catch (SecurityException e) { - fastB = false; - } - this.fastBoot = fastB; - - RuntimeTypeInfoSet typeSet = getTypeInfoSet(); - - // at least prepare the empty table so that we don't have to check for null later - elements.put(null,new LinkedHashMap()); - - // recognize leaf bean infos - for( RuntimeBuiltinLeafInfo leaf : RuntimeBuiltinLeafInfoImpl.builtinBeanInfos ) { - LeafBeanInfoImpl bi = new LeafBeanInfoImpl(this,leaf); - beanInfoMap.put(leaf.getClazz(),bi); - for( QName t : bi.getTypeNames() ) - typeMap.put(t,bi); - } - - for (RuntimeEnumLeafInfo e : typeSet.enums().values()) { - JaxBeanInfo bi = getOrCreate(e); - for (QName qn : bi.getTypeNames()) - typeMap.put( qn, bi ); - if(e.isElement()) - rootMap.put( e.getElementName(), bi ); - } - - for (RuntimeArrayInfo a : typeSet.arrays().values()) { - JaxBeanInfo ai = getOrCreate(a); - for (QName qn : ai.getTypeNames()) - typeMap.put( qn, ai ); - } - - for( Entry e : typeSet.beans().entrySet() ) { - ClassBeanInfoImpl bi = getOrCreate(e.getValue()); - - XmlSchema xs = this.annotationReader.getPackageAnnotation(XmlSchema.class, e.getKey(), null); - if(xs != null) { - if(xs.xmlns() != null && xs.xmlns().length > 0) { - if(xmlNsSet == null) - xmlNsSet = new HashSet(); - xmlNsSet.addAll(Arrays.asList(xs.xmlns())); - } - } - - if(bi.isElement()) - rootMap.put( e.getValue().getElementName(), bi ); - - for (QName qn : bi.getTypeNames()) - typeMap.put( qn, bi ); - } - - // fill in element mappings - for( RuntimeElementInfo n : typeSet.getAllElements() ) { - ElementBeanInfoImpl bi = getOrCreate(n); - if(n.getScope()==null) - rootMap.put(n.getElementName(),bi); - - RuntimeClassInfo scope = n.getScope(); - Class scopeClazz = scope==null?null:scope.getClazz(); - Map m = elements.get(scopeClazz); - if(m==null) { - m = new LinkedHashMap(); - elements.put(scopeClazz,m); - } - m.put(n.getElementName(),bi); - } - - // this one is so that we can handle plain JAXBElements. - beanInfoMap.put(JAXBElement.class,new ElementBeanInfoImpl(this)); - // another special BeanInfoImpl just for marshalling - beanInfoMap.put(CompositeStructure.class,new CompositeStructureBeanInfo(this)); - - getOrCreate(typeSet.getAnyTypeInfo()); - - // then link them all! - for (JaxBeanInfo bi : beanInfos.values()) - bi.link(this); - - // register primitives for boxed types just to make GrammarInfo fool-proof - for( Map.Entry e : RuntimeUtil.primitiveToBox.entrySet() ) - beanInfoMap.put( e.getKey(), beanInfoMap.get(e.getValue()) ); - - // build bridges - ReflectionNavigator nav = typeSet.getNavigator(); - - for (TypeReference tr : typeRefs) { - XmlJavaTypeAdapter xjta = tr.get(XmlJavaTypeAdapter.class); - Adapter a=null; - XmlList xl = tr.get(XmlList.class); - - // eventually compute the in-memory type - Class erasedType = nav.erasure(tr.type); - - if(xjta!=null) { - a = new Adapter(xjta.value(),nav); - } - if(tr.get(XmlAttachmentRef.class)!=null) { - a = new Adapter(SwaRefAdapter.class,nav); - hasSwaRef = true; - } - - if(a!=null) { - erasedType = nav.erasure(a.defaultType); - } - - Name name = nameBuilder.createElementName(tr.tagName); - - InternalBridge bridge; - if(xl==null) - bridge = new BridgeImpl(this, name,getBeanInfo(erasedType,true),tr); - else - bridge = new BridgeImpl(this, name,new ValueListBeanInfoImpl(this,erasedType),tr); - - if(a!=null) - bridge = new BridgeAdapter(bridge,a.adapterType); - - bridges.put(tr,bridge); - } - - this.nameList = nameBuilder.conclude(); - - for (JaxBeanInfo bi : beanInfos.values()) - bi.wrapUp(); - - // no use for them now - nameBuilder = null; - beanInfos = null; - } - - /** - * True if this JAXBContext has {@link XmlAttachmentRef}. - */ - public boolean hasSwaRef() { - return hasSwaRef; - } - - public RuntimeTypeInfoSet getRuntimeTypeInfoSet() { - try { - return getTypeInfoSet(); - } catch (IllegalAnnotationsException e) { - // impossible, once the model is constructred - throw new AssertionError(e); - } - } - - /** - * Creates a {@link RuntimeTypeInfoSet}. - */ - public RuntimeTypeInfoSet getTypeInfoSet() throws IllegalAnnotationsException { - - // check cache - if(typeInfoSetCache!=null) { - RuntimeTypeInfoSet r = typeInfoSetCache.get(); - if(r!=null) - return r; - } - - final RuntimeModelBuilder builder = new RuntimeModelBuilder(this,annotationReader,subclassReplacements,defaultNsUri); - - IllegalAnnotationsException.Builder errorHandler = new IllegalAnnotationsException.Builder(); - builder.setErrorHandler(errorHandler); - - for( Class c : classes ) { - if(c==CompositeStructure.class) - // CompositeStructure doesn't have TypeInfo, so skip it. - // We'll add JaxBeanInfo for this later automatically - continue; - builder.getTypeInfo(new Ref(c)); - } - - this.hasSwaRef |= builder.hasSwaRef; - RuntimeTypeInfoSet r = builder.link(); - - errorHandler.check(); - assert r!=null : "if no error was reported, the link must be a success"; - - typeInfoSetCache = new WeakReference(r); - - return r; - } - - - public ElementBeanInfoImpl getElement(Class scope, QName name) { - Map m = elements.get(scope); - if(m!=null) { - ElementBeanInfoImpl bi = m.get(name); - if(bi!=null) - return bi; - } - m = elements.get(null); - return m.get(name); - } - - - - - - private ElementBeanInfoImpl getOrCreate( RuntimeElementInfo rei ) { - JaxBeanInfo bi = beanInfos.get(rei); - if(bi!=null) return (ElementBeanInfoImpl)bi; - - // all elements share the same type, so we can't register them to beanInfoMap - return new ElementBeanInfoImpl(this, rei); - } - - protected JaxBeanInfo getOrCreate( RuntimeEnumLeafInfo eli ) { - JaxBeanInfo bi = beanInfos.get(eli); - if(bi!=null) return bi; - bi = new LeafBeanInfoImpl(this,eli); - beanInfoMap.put(bi.jaxbType,bi); - return bi; - } - - protected ClassBeanInfoImpl getOrCreate( RuntimeClassInfo ci ) { - ClassBeanInfoImpl bi = (ClassBeanInfoImpl)beanInfos.get(ci); - if(bi!=null) return bi; - bi = new ClassBeanInfoImpl(this,ci); - beanInfoMap.put(bi.jaxbType,bi); - return bi; - } - - protected JaxBeanInfo getOrCreate( RuntimeArrayInfo ai ) { - JaxBeanInfo abi = beanInfos.get(ai); - if(abi!=null) return abi; - - abi = new ArrayBeanInfoImpl(this,ai); - - beanInfoMap.put(ai.getType(),abi); - return abi; - } - - public JaxBeanInfo getOrCreate(RuntimeTypeInfo e) { - if(e instanceof RuntimeElementInfo) - return getOrCreate((RuntimeElementInfo)e); - if(e instanceof RuntimeClassInfo) - return getOrCreate((RuntimeClassInfo)e); - if(e instanceof RuntimeLeafInfo) { - JaxBeanInfo bi = beanInfos.get(e); // must have been created - assert bi!=null; - return bi; - } - if(e instanceof RuntimeArrayInfo) - return getOrCreate((RuntimeArrayInfo)e); - if(e.getType()==Object.class) { - // anyType - JaxBeanInfo bi = beanInfoMap.get(Object.class); - if(bi==null) { - bi = new AnyTypeBeanInfo(this,e); - beanInfoMap.put(Object.class,bi); - } - return bi; - } - - throw new IllegalArgumentException(); - } - - /** - * Gets the {@link JaxBeanInfo} object that can handle - * the given JAXB-bound object. - * - *

- * This method traverses the base classes of the given object. - * - * @return null - * if c isn't a JAXB-bound class and fatal==false. - */ - public final JaxBeanInfo getBeanInfo(Object o) { - // don't allow xs:anyType beanInfo to handle all the unbound objects - for( Class c=o.getClass(); c!=Object.class; c=c.getSuperclass()) { - JaxBeanInfo bi = beanInfoMap.get(c); - if(bi!=null) return bi; - } - if(o instanceof Element) - return beanInfoMap.get(Object.class); // return the BeanInfo for xs:anyType - for( Class c : o.getClass().getInterfaces()) { - JaxBeanInfo bi = beanInfoMap.get(c); - if(bi!=null) return bi; - } - return null; - } - - /** - * Gets the {@link JaxBeanInfo} object that can handle - * the given JAXB-bound object. - * - * @param fatal - * if true, the failure to look up will throw an exception. - * Otherwise it will just return null. - */ - public final JaxBeanInfo getBeanInfo(Object o,boolean fatal) throws JAXBException { - JaxBeanInfo bi = getBeanInfo(o); - if(bi!=null) return bi; - if(fatal) { - if(o instanceof Document) - throw new JAXBException(Messages.ELEMENT_NEEDED_BUT_FOUND_DOCUMENT.format(o.getClass())); - throw new JAXBException(Messages.UNKNOWN_CLASS.format(o.getClass())); - } - return null; - } - - /** - * Gets the {@link JaxBeanInfo} object that can handle - * the given JAXB-bound class. - * - *

- * This method doesn't look for base classes. - * - * @return null - * if c isn't a JAXB-bound class and fatal==false. - */ - public final JaxBeanInfo getBeanInfo(Class clazz) { - return (JaxBeanInfo)beanInfoMap.get(clazz); - } - - /** - * Gets the {@link JaxBeanInfo} object that can handle - * the given JAXB-bound class. - * - * @param fatal - * if true, the failure to look up will throw an exception. - * Otherwise it will just return null. - */ - public final JaxBeanInfo getBeanInfo(Class clazz,boolean fatal) throws JAXBException { - JaxBeanInfo bi = getBeanInfo(clazz); - if(bi!=null) return bi; - if(fatal) - throw new JAXBException(clazz.getName()+" is not known to this context"); - return null; - } - - /** - * Based on the tag name, determine what object to unmarshal, - * and then set a new object and its loader to the current unmarshaller state. - * - * @return - * null if the given name pair is not recognized. - */ - public final Loader selectRootLoader( UnmarshallingContext.State state, TagName tag ) { - JaxBeanInfo beanInfo = rootMap.get(tag.uri,tag.local); - if(beanInfo==null) - return null; - - return beanInfo.getLoader(this,true); - } - - /** - * Gets the {@link JaxBeanInfo} for the given named XML Schema type. - * - * @return - * null if the type name is not recognized. For schema - * languages other than XML Schema, this method always - * returns null. - */ - public JaxBeanInfo getGlobalType(QName name) { - return typeMap.get(name); - } - - /** - * Finds a type name that this context recognizes which is - * "closest" to the given type name. - * - *

- * This method is used for error recovery. - */ - public String getNearestTypeName(QName name) { - String[] all = new String[typeMap.size()]; - int i=0; - for (QName qn : typeMap.keySet()) { - if(qn.getLocalPart().equals(name.getLocalPart())) - return qn.toString(); // probably a match, as people often gets confused about namespace. - all[i++] = qn.toString(); - } - - String nearest = EditDistance.findNearest(name.toString(), all); - - if(EditDistance.editDistance(nearest,name.toString())>10) - return null; // too far apart. - - return nearest; - } - - /** - * Returns the set of valid root tag names. - * For diagnostic use. - */ - public Set getValidRootNames() { - Set r = new TreeSet(QNAME_COMPARATOR); - for (QNameMap.Entry e : rootMap.entrySet()) { - r.add(e.createQName()); - } - return r; - } - - /** - * Cache of UTF-8 encoded local names to improve the performance for the marshalling. - */ - private Encoded[] utf8nameTable; - - public synchronized Encoded[] getUTF8NameTable() { - if(utf8nameTable==null) { - Encoded[] x = new Encoded[nameList.localNames.length]; - for( int i=0; i getXmlType(RuntimeTypeInfoSet tis, TypeReference tr) { - if(tr==null) - throw new IllegalArgumentException(); - - XmlJavaTypeAdapter xjta = tr.get(XmlJavaTypeAdapter.class); - XmlList xl = tr.get(XmlList.class); - - Ref ref = new Ref(annotationReader, tis.getNavigator(), tr.type, xjta, xl ); - - return tis.getTypeInfo(ref); - } - - @Override - public void generateEpisode(Result output) { - if(output==null) - throw new IllegalArgumentException(); - createSchemaGenerator().writeEpisodeFile(ResultFactory.createSerializer(output)); - } - - @Override - @SuppressWarnings("ThrowableInitCause") - public void generateSchema(SchemaOutputResolver outputResolver) throws IOException { - if(outputResolver==null) - throw new IOException(Messages.NULL_OUTPUT_RESOLVER.format()); - - final SAXParseException[] e = new SAXParseException[1]; - final SAXParseException[] w = new SAXParseException[1]; - - createSchemaGenerator().write(outputResolver, new ErrorListener() { - public void error(SAXParseException exception) { - e[0] = exception; - } - - public void fatalError(SAXParseException exception) { - e[0] = exception; - } - - public void warning(SAXParseException exception) { - w[0] = exception; - } - - public void info(SAXParseException exception) {} - }); - - if (e[0]!=null) { - IOException x = new IOException(Messages.FAILED_TO_GENERATE_SCHEMA.format()); - x.initCause(e[0]); - throw x; - } - if (w[0]!=null) { - IOException x = new IOException(Messages.ERROR_PROCESSING_SCHEMA.format()); - x.initCause(w[0]); - throw x; - } - } - - private XmlSchemaGenerator createSchemaGenerator() { - RuntimeTypeInfoSet tis; - try { - tis = getTypeInfoSet(); - } catch (IllegalAnnotationsException e) { - // this shouldn't happen because we've already - throw new AssertionError(e); - } - - XmlSchemaGenerator xsdgen = - new XmlSchemaGenerator(tis.getNavigator(),tis); - - // JAX-RPC uses Bridge objects that collide with - // @XmlRootElement. - // we will avoid collision here - Set rootTagNames = new HashSet(); - for (RuntimeElementInfo ei : tis.getAllElements()) { - rootTagNames.add(ei.getElementName()); - } - for (RuntimeClassInfo ci : tis.beans().values()) { - if(ci.isElement()) - rootTagNames.add(ci.asElement().getElementName()); - } - - for (TypeReference tr : bridges.keySet()) { - if(rootTagNames.contains(tr.tagName)) - continue; - - if(tr.type==void.class || tr.type==Void.class) { - xsdgen.add(tr.tagName,false,null); - } else - if(tr.type==CompositeStructure.class) { - // this is a special class we introduced for JAX-WS that we *don't* want in the schema - } else { - NonElement typeInfo = getXmlType(tis,tr); - xsdgen.add(tr.tagName, !Navigator.REFLECTION.isPrimitive(tr.type),typeInfo); - } - } - return xsdgen; - } - - public QName getTypeName(TypeReference tr) { - try { - NonElement xt = getXmlType(getTypeInfoSet(),tr); - if(xt==null) throw new IllegalArgumentException(); - return xt.getTypeName(); - } catch (IllegalAnnotationsException e) { - // impossible given that JAXBRIContext has been successfully built in the first place - throw new AssertionError(e); - } - } - - /** - * Used for testing. - */ - public SchemaOutputResolver createTestResolver() { - return new SchemaOutputResolver() { - public Result createOutput(String namespaceUri, String suggestedFileName) { - SAXResult r = new SAXResult(new DefaultHandler()); - r.setSystemId(suggestedFileName); - return r; - } - }; - } - - @Override - public Binder createBinder(Class domType) { - if(domType==Node.class) - return (Binder)createBinder(); - else - return super.createBinder(domType); - } - - @Override - public Binder createBinder() { - return new BinderImpl(this,new DOMScanner()); - } - - public QName getElementName(Object o) throws JAXBException { - JaxBeanInfo bi = getBeanInfo(o,true); - if(!bi.isElement()) - return null; - return new QName(bi.getElementNamespaceURI(o),bi.getElementLocalName(o)); - } - - public QName getElementName(Class o) throws JAXBException { - JaxBeanInfo bi = getBeanInfo(o,true); - if(!bi.isElement()) - return null; - return new QName(bi.getElementNamespaceURI(o),bi.getElementLocalName(o)); - } - - public Bridge createBridge(TypeReference ref) { - return bridges.get(ref); - } - - public @NotNull BridgeContext createBridgeContext() { - return new BridgeContextImpl(this); - } - - public RawAccessor getElementPropertyAccessor(Class wrapperBean, String nsUri, String localName) throws JAXBException { - JaxBeanInfo bi = getBeanInfo(wrapperBean,true); - if(!(bi instanceof ClassBeanInfoImpl)) - throw new JAXBException(wrapperBean+" is not a bean"); - - for( ClassBeanInfoImpl cb = (ClassBeanInfoImpl) bi; cb!=null; cb=cb.superClazz) { - for (Property p : cb.properties) { - final Accessor acc = p.getElementPropertyAccessor(nsUri,localName); - if(acc!=null) - return new RawAccessor() { - // Accessor.set/get are designed for unmarshaller/marshaller, and hence - // they go through an adapter behind the scene. - // this isn't desirable for JAX-WS, which essentially uses this method - // just as a reflection library. So use the "unadapted" version to - // achieve the desired semantics - public Object get(Object bean) throws AccessorException { - return acc.getUnadapted(bean); - } - - public void set(Object bean, Object value) throws AccessorException { - acc.setUnadapted(bean,value); - } - }; - } - } - throw new JAXBException(new QName(nsUri,localName)+" is not a valid property on "+wrapperBean); - } - - public List getKnownNamespaceURIs() { - return Arrays.asList(nameList.namespaceURIs); - } - - public String getBuildId() { - Package pkg = getClass().getPackage(); - if(pkg==null) return null; - return pkg.getImplementationVersion(); - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder(Which.which(getClass()) + " Build-Id: " + getBuildId()); - buf.append("\nClasses known to this context:\n"); - - Set names = new TreeSet(); // sort them so that it's easy to read - - for (Class key : beanInfoMap.keySet()) - names.add(key.getName()); - - for(String name: names) - buf.append(" ").append(name).append('\n'); - - return buf.toString(); - } - - /** - * Gets the value of the xmime:contentType attribute on the given object, or null - * if for some reason it couldn't be found, including any error. - */ - public String getXMIMEContentType( Object o ) { - JaxBeanInfo bi = getBeanInfo(o); - if(!(bi instanceof ClassBeanInfoImpl)) - return null; - - ClassBeanInfoImpl cb = (ClassBeanInfoImpl) bi; - for (Property p : cb.properties) { - if (p instanceof AttributeProperty) { - AttributeProperty ap = (AttributeProperty) p; - if(ap.attName.equals(WellKnownNamespace.XML_MIME_URI,"contentType")) - try { - return (String)ap.xacc.print(o); - } catch (AccessorException e) { - return null; - } catch (SAXException e) { - return null; - } catch (ClassCastException e) { - return null; - } - } - } - return null; - } - - /** - * Creates a {@link JAXBContextImpl} that includes the specified additional classes. - */ - public JAXBContextImpl createAugmented(Class clazz) throws JAXBException { - Class[] newList = new Class[classes.length+1]; - System.arraycopy(classes,0,newList,0,classes.length); - newList[classes.length] = clazz; - - JAXBContextBuilder builder = new JAXBContextBuilder(this); - builder.setClasses(newList); - return builder.build(); - } - - private static final Comparator QNAME_COMPARATOR = new Comparator() { - public int compare(QName lhs, QName rhs) { - int r = lhs.getLocalPart().compareTo(rhs.getLocalPart()); - if(r!=0) return r; - - return lhs.getNamespaceURI().compareTo(rhs.getNamespaceURI()); - } - }; - - public static class JAXBContextBuilder { - - private boolean retainPropertyInfo = false; - private boolean supressAccessorWarnings = false; - private String defaultNsUri = ""; - private @NotNull RuntimeAnnotationReader annotationReader = new RuntimeInlineAnnotationReader(); - private @NotNull Map subclassReplacements = Collections.emptyMap(); - private boolean c14nSupport = false; - private Class[] classes; - private Collection typeRefs; - private boolean xmlAccessorFactorySupport = false; - private boolean allNillable; - private boolean improvedXsiTypeHandling = true; - private boolean disableSecurityProcessing = true; - - public JAXBContextBuilder() {}; - - public JAXBContextBuilder(JAXBContextImpl baseImpl) { - this.supressAccessorWarnings = baseImpl.supressAccessorWarnings; - this.retainPropertyInfo = baseImpl.retainPropertyInfo; - this.defaultNsUri = baseImpl.defaultNsUri; - this.annotationReader = baseImpl.annotationReader; - this.subclassReplacements = baseImpl.subclassReplacements; - this.c14nSupport = baseImpl.c14nSupport; - this.classes = baseImpl.classes; - this.typeRefs = baseImpl.bridges.keySet(); - this.xmlAccessorFactorySupport = baseImpl.xmlAccessorFactorySupport; - this.allNillable = baseImpl.allNillable; - this.disableSecurityProcessing = baseImpl.disableSecurityProcessing; - } - - public JAXBContextBuilder setRetainPropertyInfo(boolean val) { - this.retainPropertyInfo = val; - return this; - } - - public JAXBContextBuilder setSupressAccessorWarnings(boolean val) { - this.supressAccessorWarnings = val; - return this; - } - - public JAXBContextBuilder setC14NSupport(boolean val) { - this.c14nSupport = val; - return this; - } - - public JAXBContextBuilder setXmlAccessorFactorySupport(boolean val) { - this.xmlAccessorFactorySupport = val; - return this; - } - - public JAXBContextBuilder setDefaultNsUri(String val) { - this.defaultNsUri = val; - return this; - } - - public JAXBContextBuilder setAllNillable(boolean val) { - this.allNillable = val; - return this; - } - - public JAXBContextBuilder setClasses(Class[] val) { - this.classes = val; - return this; - } - - public JAXBContextBuilder setAnnotationReader(RuntimeAnnotationReader val) { - this.annotationReader = val; - return this; - } - - public JAXBContextBuilder setSubclassReplacements(Map val) { - this.subclassReplacements = val; - return this; - } - - public JAXBContextBuilder setTypeRefs(Collection val) { - this.typeRefs = val; - return this; - } - - public JAXBContextBuilder setImprovedXsiTypeHandling(boolean val) { - this.improvedXsiTypeHandling = val; - return this; - } - - public JAXBContextBuilder setDisableSecurityProcessing(boolean val) { - this.disableSecurityProcessing = val; - return this; - } - - public JAXBContextImpl build() throws JAXBException { - - // fool-proof - if (this.defaultNsUri == null) { - this.defaultNsUri = ""; - } - - if (this.subclassReplacements == null) { - this.subclassReplacements = Collections.emptyMap(); - } - - if (this.annotationReader == null) { - this.annotationReader = new RuntimeInlineAnnotationReader(); - } - - if (this.typeRefs == null) { - this.typeRefs = Collections.emptyList(); - } - - return new JAXBContextImpl(this); - } - - } - -} diff --git a/src/main/java/com/sun/xml/bind/v2/runtime/reflect/Accessor.java b/src/main/java/com/sun/xml/bind/v2/runtime/reflect/Accessor.java index 6c33c65..9245ff0 100644 --- a/src/main/java/com/sun/xml/bind/v2/runtime/reflect/Accessor.java +++ b/src/main/java/com/sun/xml/bind/v2/runtime/reflect/Accessor.java @@ -1,19 +1,19 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright (c) 1997-2011 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997-2017 Oracle and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can * obtain a copy of the License at - * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html - * or packager/legal/LICENSE.txt. See the License for the specific + * https://oss.oracle.com/licenses/CDDL+GPL-1.1 + * or LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each - * file and include the License file at packager/legal/LICENSE.txt. + * file and include the License file at LICENSE.txt. * * GPL Classpath Exception: * Oracle designates this particular file as subject to the "Classpath" @@ -61,9 +61,7 @@ import com.sun.xml.bind.api.JAXBRIContext; import com.sun.xml.bind.v2.model.core.Adapter; import com.sun.xml.bind.v2.model.impl.RuntimeModelBuilder; -import com.sun.xml.bind.v2.model.nav.Navigator; import com.sun.xml.bind.v2.runtime.JAXBContextImpl; -import com.sun.xml.bind.v2.runtime.reflect.opt.OptimizedAccessorFactory; import com.sun.xml.bind.v2.runtime.unmarshaller.Loader; import com.sun.xml.bind.v2.runtime.unmarshaller.Receiver; import com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext; @@ -72,13 +70,13 @@ /** * Accesses a particular property of a bean. - *

- *

+ *

+ *

* This interface encapsulates the access to the actual data store. * The intention is to generate implementations for a particular bean * and a property to improve the performance. - *

- *

+ *

+ *

* Accessor can be used as a receiver. Upon receiving an object * it sets that to the field. * @@ -103,7 +101,7 @@ protected Accessor(Class valueType) { * * @param context The {@link JAXBContextImpl} that owns the whole thing. * (See {@link RuntimeModelBuilder#context}.) - * @return At least the implementation can return this. + * @return At least the implementation can return {@code this}. */ public Accessor optimize(@Nullable JAXBContextImpl context) { return this; @@ -135,7 +133,7 @@ public Accessor optimize(@Nullable JAXBContextImpl context) { /** * Sets the value without adapting the value. - *

+ *

* This ugly entry point is only used by JAX-WS. * See {@link JAXBRIContext#getElementPropertyAccessor} */ @@ -145,7 +143,7 @@ public Object getUnadapted(BeanT bean) throws AccessorException { /** * Returns true if this accessor wraps an adapter. - *

+ *

* This method needs to be used with care, but it helps some optimization. */ public boolean isAdapted() { @@ -154,7 +152,7 @@ public boolean isAdapted() { /** * Sets the value without adapting the value. - *

+ *

* This ugly entry point is only used by JAX-WS. * See {@link JAXBRIContext#getElementPropertyAccessor} */ @@ -164,7 +162,7 @@ public void setUnadapted(BeanT bean, Object value) throws AccessorException { public void receive(UnmarshallingContext.State state, Object o) throws SAXException { try { - set((BeanT) state.target, (ValueT) o); + set((BeanT) state.getTarget(), (ValueT) o); } catch (AccessorException e) { Loader.handleGenericException(e, true); } catch (IllegalAccessError iae) { @@ -211,7 +209,7 @@ public final Accessor adapt(Class targetType, final Class Accessor adapt(Adapter adapter) { return new AdaptedAccessor( - (Class) Navigator.REFLECTION.erasure(adapter.defaultType), + (Class) Utils.REFLECTION_NAVIGATOR.erasure(adapter.defaultType), this, adapter.adapterType); } @@ -243,8 +241,7 @@ public FieldReflection(Field f, boolean supressAccessorWarnings) { if (!Modifier.isPublic(mod) || Modifier.isFinal(mod) || !Modifier.isPublic(f.getDeclaringClass().getModifiers())) { try { // attempt to make it accessible, but do so in the security context of the calling application. - // don't do this in the doPrivilege block, as that would create a security hole for anyone - // to make any field accessible. + // don't do this in the doPrivilege block f.setAccessible(true); } catch (SecurityException e) { if ((!accessWarned) && (!supressAccessorWarnings)) { @@ -279,14 +276,7 @@ public void set(BeanT bean, ValueT value) { @Override public Accessor optimize(JAXBContextImpl context) { - if (context != null && context.fastBoot) - // let's not waste time on doing this for the sake of faster boot. - return this; - Accessor acc = OptimizedAccessorFactory.get(f); - if (acc != null) - return acc; - else - return this; + return this; } } @@ -392,25 +382,14 @@ private AccessorException handleInvocationTargetException(InvocationTargetExcept @Override public Accessor optimize(JAXBContextImpl context) { - if (getter == null || setter == null) - // if we aren't complete, OptimizedAccessor won't always work - return this; - if (context != null && context.fastBoot) - // let's not waste time on doing this for the sake of faster boot. - return this; - - Accessor acc = OptimizedAccessorFactory.get(getter, setter); - if (acc != null) - return acc; - else - return this; + return this; } } /** * A version of {@link GetterSetterReflection} that doesn't have any setter. - *

- *

+ *

+ *

* This provides a user-friendly error message. */ public static class GetterOnlyReflection extends GetterSetterReflection { @@ -426,8 +405,8 @@ public void set(BeanT bean, ValueT value) throws AccessorException { /** * A version of {@link GetterSetterReflection} thaat doesn't have any getter. - *

- *

+ *

+ *

* This provides a user-friendly error message. */ public static class SetterOnlyReflection extends GetterSetterReflection {