src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/UnmarshallerImpl.java

Thu, 31 Aug 2017 15:18:52 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:18:52 +0800
changeset 637
9c07ef4934dd
parent 368
0989ad8c0860
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

     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  */
    26 package com.sun.xml.internal.bind.v2.runtime.unmarshaller;
    28 import java.io.IOException;
    29 import java.io.InputStream;
    31 import javax.xml.bind.JAXBContext;
    32 import javax.xml.bind.JAXBElement;
    33 import javax.xml.bind.JAXBException;
    34 import javax.xml.bind.PropertyException;
    35 import javax.xml.bind.UnmarshalException;
    36 import javax.xml.bind.Unmarshaller;
    37 import javax.xml.bind.UnmarshallerHandler;
    38 import javax.xml.bind.ValidationEvent;
    39 import javax.xml.bind.ValidationEventHandler;
    40 import javax.xml.bind.annotation.adapters.XmlAdapter;
    41 import javax.xml.bind.attachment.AttachmentUnmarshaller;
    42 import javax.xml.bind.helpers.AbstractUnmarshallerImpl;
    43 import javax.xml.stream.XMLEventReader;
    44 import javax.xml.stream.XMLStreamConstants;
    45 import javax.xml.stream.XMLStreamException;
    46 import javax.xml.stream.XMLStreamReader;
    47 import javax.xml.stream.events.XMLEvent;
    48 import javax.xml.transform.Source;
    49 import javax.xml.transform.dom.DOMSource;
    50 import javax.xml.transform.sax.SAXSource;
    51 import javax.xml.transform.stream.StreamSource;
    52 import javax.xml.validation.Schema;
    54 import com.sun.xml.internal.bind.IDResolver;
    55 import com.sun.xml.internal.bind.api.ClassResolver;
    56 import com.sun.xml.internal.bind.unmarshaller.DOMScanner;
    57 import com.sun.xml.internal.bind.unmarshaller.InfosetScanner;
    58 import com.sun.xml.internal.bind.unmarshaller.Messages;
    59 import com.sun.xml.internal.bind.v2.ClassFactory;
    60 import com.sun.xml.internal.bind.v2.runtime.AssociationMap;
    61 import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
    62 import com.sun.xml.internal.bind.v2.runtime.JaxBeanInfo;
    63 import com.sun.xml.internal.bind.v2.util.XmlFactory;
    65 import java.io.Closeable;
    66 import javax.xml.parsers.ParserConfigurationException;
    67 import javax.xml.parsers.SAXParserFactory;
    68 import org.w3c.dom.Document;
    69 import org.w3c.dom.Element;
    70 import org.w3c.dom.Node;
    71 import org.xml.sax.InputSource;
    72 import org.xml.sax.SAXException;
    73 import org.xml.sax.XMLReader;
    74 import org.xml.sax.helpers.DefaultHandler;
    76 /**
    77  * Default Unmarshaller implementation.
    78  *
    79  * <p>
    80  * This class can be extended by the generated code to provide
    81  * type-safe unmarshall methods.
    82  *
    83  * @author
    84  *  <a href="mailto:kohsuke.kawaguchi@sun.com">Kohsuke KAWAGUCHI</a>
    85  */
    86  public final class UnmarshallerImpl extends AbstractUnmarshallerImpl implements ValidationEventHandler, Closeable
    87 {
    88     /** Owning {@link JAXBContext} */
    89     protected final JAXBContextImpl context;
    91     /**
    92      * schema which will be used to validate during calls to unmarshal
    93      */
    94     private Schema schema;
    96     public final UnmarshallingContext coordinator;
    98     /** Unmarshaller.Listener */
    99     private Listener externalListener;
   101     /**
   102      * The attachment unmarshaller used to support MTOM and swaRef.
   103      */
   104     private AttachmentUnmarshaller attachmentUnmarshaller;
   105     private IDResolver idResolver = new DefaultIDResolver();
   107     public UnmarshallerImpl( JAXBContextImpl context, AssociationMap assoc ) {
   108         this.context = context;
   109         this.coordinator = new UnmarshallingContext( this, assoc );
   111         try {
   112             setEventHandler(this);
   113         } catch (JAXBException e) {
   114             throw new AssertionError(e);    // impossible
   115         }
   116     }
   118     public UnmarshallerHandler getUnmarshallerHandler() {
   119         return getUnmarshallerHandler(true,null);
   120     }
   122     private XMLReader reader = null;
   124     /**
   125      * Obtains a configured XMLReader.
   126      *
   127      * This method is used when the client-specified
   128      * {@link SAXSource} object doesn't have XMLReader.
   129      *
   130      * {@link Unmarshaller} is not re-entrant, so we will
   131      * only use one instance of XMLReader.
   132      *
   133      * Overriden in order to fix potential security issue.
   134      */
   135      @Override
   136     protected XMLReader getXMLReader() throws JAXBException {
   137          if (reader == null) {
   138              try {
   139                  SAXParserFactory parserFactory = XmlFactory.createParserFactory(context.disableSecurityProcessing);
   140                  // there is no point in asking a validation because
   141                  // there is no guarantee that the document will come with
   142                  // a proper schemaLocation.
   143                  parserFactory.setValidating(false);
   144                  reader = parserFactory.newSAXParser().getXMLReader();
   145              } catch (ParserConfigurationException e) {
   146                  throw new JAXBException(e);
   147              } catch (SAXException e) {
   148                  throw new JAXBException(e);
   149              }
   150          }
   151          return reader;
   152      }
   154     private SAXConnector getUnmarshallerHandler( boolean intern, JaxBeanInfo expectedType ) {
   155         XmlVisitor h = createUnmarshallerHandler(null, false, expectedType);
   156         if (intern) {
   157             h = new InterningXmlVisitor(h);
   158         }
   159         return new SAXConnector(h,null);
   160     }
   162     /**
   163      * Creates and configures a new unmarshalling pipe line.
   164      * Depending on the setting, we put a validator as a filter.
   165      *
   166      * @return
   167      *      A component that implements both {@link UnmarshallerHandler}
   168      *      and {@link ValidationEventHandler}. All the parsing errors
   169      *      should be reported to this error handler for the unmarshalling
   170      *      process to work correctly.
   171      *
   172      *      Also, returned handler expects all the XML names to be interned.
   173      *
   174      */
   175     public final XmlVisitor createUnmarshallerHandler(InfosetScanner scanner, boolean inplace, JaxBeanInfo expectedType ) {
   177         coordinator.reset(scanner,inplace,expectedType,idResolver);
   178         XmlVisitor unmarshaller = coordinator;
   180         // delegate to JAXP 1.3 for validation if the client provided a schema
   181         if (schema != null) {
   182             unmarshaller = new ValidatingUnmarshaller(schema,unmarshaller);
   183         }
   185         if(attachmentUnmarshaller!=null && attachmentUnmarshaller.isXOPPackage()) {
   186             unmarshaller = new MTOMDecorator(this,unmarshaller,attachmentUnmarshaller);
   187         }
   189         return unmarshaller;
   190     }
   192     private static final DefaultHandler dummyHandler = new DefaultHandler();
   194     public static boolean needsInterning( XMLReader reader ) {
   195         // attempt to set it to true, which could fail
   196         try {
   197             reader.setFeature("http://xml.org/sax/features/string-interning",true);
   198         } catch (SAXException e) {
   199             // if it fails that's fine. we'll work around on our side
   200         }
   202         try {
   203             if (reader.getFeature("http://xml.org/sax/features/string-interning")) {
   204                 return false;   // no need for intern
   205             }
   206         } catch (SAXException e) {
   207             // unrecognized/unsupported
   208         }
   209         // otherwise we need intern
   210         return true;
   211     }
   213     protected Object unmarshal( XMLReader reader, InputSource source ) throws JAXBException {
   214         return unmarshal0(reader,source,null);
   215     }
   217     protected <T> JAXBElement<T> unmarshal( XMLReader reader, InputSource source, Class<T> expectedType ) throws JAXBException {
   218         if(expectedType==null) {
   219             throw new IllegalArgumentException();
   220         }
   221         return (JAXBElement)unmarshal0(reader,source,getBeanInfo(expectedType));
   222     }
   224     private Object unmarshal0( XMLReader reader, InputSource source, JaxBeanInfo expectedType ) throws JAXBException {
   226         SAXConnector connector = getUnmarshallerHandler(needsInterning(reader),expectedType);
   228         reader.setContentHandler(connector);
   229         // saxErrorHandler will be set by the getUnmarshallerHandler method.
   230         // configure XMLReader so that the error will be sent to it.
   231         // This is essential for the UnmarshallerHandler to be able to abort
   232         // unmarshalling when an error is found.
   233         //
   234         // Note that when this XMLReader is provided by the client code,
   235         // it might be already configured to call a client error handler.
   236         // This will clobber such handler, if any.
   237         //
   238         // Ryan noted that we might want to report errors to such a client
   239         // error handler as well.
   240         reader.setErrorHandler(coordinator);
   242         try {
   243             reader.parse(source);
   244         } catch( IOException e ) {
   245             coordinator.clearStates();
   246             throw new UnmarshalException(e);
   247         } catch( SAXException e ) {
   248             coordinator.clearStates();
   249             throw createUnmarshalException(e);
   250         }
   252         Object result = connector.getResult();
   254         // avoid keeping unnecessary references too long to let the GC
   255         // reclaim more memory.
   256         // setting null upsets some parsers, so use a dummy instance instead.
   257         reader.setContentHandler(dummyHandler);
   258         reader.setErrorHandler(dummyHandler);
   260         return result;
   261     }
   263     @Override
   264     public <T> JAXBElement<T> unmarshal( Source source, Class<T> expectedType ) throws JAXBException {
   265         if (source instanceof SAXSource) {
   266             SAXSource ss = (SAXSource) source;
   268             XMLReader locReader = ss.getXMLReader();
   269             if (locReader == null) {
   270                 locReader = getXMLReader();
   271             }
   273             return unmarshal(locReader, ss.getInputSource(), expectedType);
   274         }
   275         if (source instanceof StreamSource) {
   276             return unmarshal(getXMLReader(), streamSourceToInputSource((StreamSource) source), expectedType);
   277         }
   278         if (source instanceof DOMSource) {
   279             return unmarshal(((DOMSource) source).getNode(), expectedType);
   280         }
   282         // we don't handle other types of Source
   283         throw new IllegalArgumentException();
   284     }
   286     public Object unmarshal0( Source source, JaxBeanInfo expectedType ) throws JAXBException {
   287         if (source instanceof SAXSource) {
   288             SAXSource ss = (SAXSource) source;
   290             XMLReader locReader = ss.getXMLReader();
   291             if (locReader == null) {
   292                 locReader = getXMLReader();
   293             }
   295             return unmarshal0(locReader, ss.getInputSource(), expectedType);
   296         }
   297         if (source instanceof StreamSource) {
   298             return unmarshal0(getXMLReader(), streamSourceToInputSource((StreamSource) source), expectedType);
   299         }
   300         if (source instanceof DOMSource) {
   301             return unmarshal0(((DOMSource) source).getNode(), expectedType);
   302         }
   304         // we don't handle other types of Source
   305         throw new IllegalArgumentException();
   306     }
   309     @Override
   310     public final ValidationEventHandler getEventHandler() {
   311         try {
   312             return super.getEventHandler();
   313         } catch (JAXBException e) {
   314             // impossible
   315             throw new AssertionError();
   316         }
   317     }
   319     /**
   320      * Returns true if an event handler is installed.
   321      * <p>
   322      * The default handler ignores any errors, and for that this method returns false.
   323      */
   324     public final boolean hasEventHandler() {
   325         return getEventHandler()!=this;
   326     }
   328     @Override
   329     public <T> JAXBElement<T> unmarshal(Node node, Class<T> expectedType) throws JAXBException {
   330         if (expectedType == null) {
   331             throw new IllegalArgumentException();
   332         }
   333         return (JAXBElement)unmarshal0(node,getBeanInfo(expectedType));
   334     }
   336     public final Object unmarshal( Node node ) throws JAXBException {
   337         return unmarshal0(node,null);
   338     }
   340     // just to make the the test harness happy by making this method accessible
   341     @Deprecated
   342     public final Object unmarshal( SAXSource source ) throws JAXBException {
   343         return super.unmarshal(source);
   344     }
   346     public final Object unmarshal0( Node node, JaxBeanInfo expectedType ) throws JAXBException {
   347         try {
   348             final DOMScanner scanner = new DOMScanner();
   350             InterningXmlVisitor handler = new InterningXmlVisitor(createUnmarshallerHandler(null,false,expectedType));
   351             scanner.setContentHandler(new SAXConnector(handler,scanner));
   353             if(node.getNodeType() == Node.ELEMENT_NODE) {
   354                 scanner.scan((Element)node);
   355             } else if(node.getNodeType() == Node.DOCUMENT_NODE) {
   356                 scanner.scan((Document)node);
   357             } else {
   358                 throw new IllegalArgumentException("Unexpected node type: "+node);
   359             }
   361             Object retVal = handler.getContext().getResult();
   362             handler.getContext().clearResult();
   363             return retVal;
   364         } catch( SAXException e ) {
   365             throw createUnmarshalException(e);
   366         }
   367     }
   369     @Override
   370     public Object unmarshal(XMLStreamReader reader) throws JAXBException {
   371         return unmarshal0(reader,null);
   372     }
   374     @Override
   375     public <T> JAXBElement<T> unmarshal(XMLStreamReader reader, Class<T> expectedType) throws JAXBException {
   376         if (expectedType==null) {
   377             throw new IllegalArgumentException();
   378         }
   379         return (JAXBElement)unmarshal0(reader,getBeanInfo(expectedType));
   380     }
   382     public Object unmarshal0(XMLStreamReader reader, JaxBeanInfo expectedType) throws JAXBException {
   383         if (reader == null) {
   384             throw new IllegalArgumentException(
   385                 Messages.format(Messages.NULL_READER));
   386         }
   388         int eventType = reader.getEventType();
   389         if (eventType != XMLStreamConstants.START_ELEMENT
   390             && eventType != XMLStreamConstants.START_DOCUMENT) {
   391             // TODO: convert eventType into event name
   392             throw new IllegalStateException(
   393                 Messages.format(Messages.ILLEGAL_READER_STATE,eventType));
   394         }
   396         XmlVisitor h = createUnmarshallerHandler(null,false,expectedType);
   397         StAXConnector connector=StAXStreamConnector.create(reader,h);
   399         try {
   400             connector.bridge();
   401         } catch (XMLStreamException e) {
   402             throw handleStreamException(e);
   403         }
   405         Object retVal = h.getContext().getResult();
   406         h.getContext().clearResult();
   407         return retVal;
   408     }
   410     @Override
   411     public <T> JAXBElement<T> unmarshal(XMLEventReader reader, Class<T> expectedType) throws JAXBException {
   412         if(expectedType==null) {
   413             throw new IllegalArgumentException();
   414         }
   415         return (JAXBElement)unmarshal0(reader,getBeanInfo(expectedType));
   416     }
   418     @Override
   419     public Object unmarshal(XMLEventReader reader) throws JAXBException {
   420         return unmarshal0(reader,null);
   421     }
   423     private Object unmarshal0(XMLEventReader reader,JaxBeanInfo expectedType) throws JAXBException {
   424         if (reader == null) {
   425             throw new IllegalArgumentException(
   426                     Messages.format(Messages.NULL_READER));
   427         }
   429         try {
   430             XMLEvent event = reader.peek();
   432             if (!event.isStartElement() && !event.isStartDocument()) {
   433                 // TODO: convert event into event name
   434                 throw new IllegalStateException(
   435                     Messages.format(
   436                         Messages.ILLEGAL_READER_STATE,event.getEventType()));
   437             }
   439             // Quick hack until SJSXP fixes 6270116
   440             boolean isZephyr = reader.getClass().getName().equals("com.sun.xml.internal.stream.XMLReaderImpl");
   441             XmlVisitor h = createUnmarshallerHandler(null,false,expectedType);
   442             if(!isZephyr) {
   443                 h = new InterningXmlVisitor(h);
   444             }
   445             new StAXEventConnector(reader,h).bridge();
   446             return h.getContext().getResult();
   447         } catch (XMLStreamException e) {
   448             throw handleStreamException(e);
   449         }
   450     }
   452     public Object unmarshal0( InputStream input, JaxBeanInfo expectedType ) throws JAXBException {
   453         return unmarshal0(getXMLReader(),new InputSource(input),expectedType);
   454     }
   456     private static JAXBException handleStreamException(XMLStreamException e) {
   457         // StAXStreamConnector wraps SAXException to XMLStreamException.
   458         // XMLStreamException doesn't print its nested stack trace when it prints
   459         // its stack trace, so if we wrap XMLStreamException in JAXBException,
   460         // it becomes harder to find out the real problem.
   461         // So we unwrap them here. But we don't want to unwrap too eagerly, because
   462         // that could throw away some meaningful exception information.
   463         Throwable ne = e.getNestedException();
   464         if(ne instanceof JAXBException) {
   465             return (JAXBException)ne;
   466         }
   467         if(ne instanceof SAXException) {
   468             return new UnmarshalException(ne);
   469         }
   470         return new UnmarshalException(e);
   471     }
   473     @Override
   474     public Object getProperty(String name) throws PropertyException {
   475         if(name.equals(IDResolver.class.getName())) {
   476             return idResolver;
   477         }
   478         return super.getProperty(name);
   479     }
   481     @Override
   482     public void setProperty(String name, Object value) throws PropertyException {
   483         if(name.equals(FACTORY)) {
   484             coordinator.setFactories(value);
   485             return;
   486         }
   487         if(name.equals(IDResolver.class.getName())) {
   488             idResolver = (IDResolver)value;
   489             return;
   490         }
   491         if(name.equals(ClassResolver.class.getName())) {
   492             coordinator.classResolver = (ClassResolver)value;
   493             return;
   494         }
   495         if(name.equals(ClassLoader.class.getName())) {
   496             coordinator.classLoader = (ClassLoader)value;
   497             return;
   498         }
   499         super.setProperty(name, value);
   500     }
   502     public static final String FACTORY = "com.sun.xml.internal.bind.ObjectFactory";
   504     @Override
   505     public void setSchema(Schema schema) {
   506         this.schema = schema;
   507     }
   509     @Override
   510     public Schema getSchema() {
   511         return schema;
   512     }
   514     @Override
   515     public AttachmentUnmarshaller getAttachmentUnmarshaller() {
   516         return attachmentUnmarshaller;
   517     }
   519     @Override
   520     public void setAttachmentUnmarshaller(AttachmentUnmarshaller au) {
   521         this.attachmentUnmarshaller = au;
   522     }
   524     /**
   525      * @deprecated since 2.0
   526      */
   527     @Override
   528     public boolean isValidating() {
   529         throw new UnsupportedOperationException();
   530     }
   532     /**
   533      * @deprecated since 2.0
   534      */
   535     @Override
   536     public void setValidating(boolean validating) {
   537         throw new UnsupportedOperationException();
   538     }
   540     @Override
   541     public <A extends XmlAdapter> void setAdapter(Class<A> type, A adapter) {
   542         if (type==null) {
   543             throw new IllegalArgumentException();
   544         }
   545         coordinator.putAdapter(type,adapter);
   546     }
   548     @Override
   549     public <A extends XmlAdapter> A getAdapter(Class<A> type) {
   550         if(type==null) {
   551             throw new IllegalArgumentException();
   552         }
   553         if(coordinator.containsAdapter(type)) {
   554             return coordinator.getAdapter(type);
   555         } else {
   556             return null;
   557         }
   558     }
   560     // opening up for public use
   561     @Override
   562     public UnmarshalException createUnmarshalException( SAXException e ) {
   563         return super.createUnmarshalException(e);
   564     }
   567     /**
   568      * Default error handling behavior for {@link Unmarshaller}.
   569      */
   570     public boolean handleEvent(ValidationEvent event) {
   571         return event.getSeverity()!=ValidationEvent.FATAL_ERROR;
   572     }
   574     private static InputSource streamSourceToInputSource( StreamSource ss ) {
   575         InputSource is = new InputSource();
   576         is.setSystemId( ss.getSystemId() );
   577         is.setByteStream( ss.getInputStream() );
   578         is.setCharacterStream( ss.getReader() );
   580         return is;
   581     }
   583     public <T> JaxBeanInfo<T> getBeanInfo(Class<T> clazz) throws JAXBException {
   584         return context.getBeanInfo(clazz,true);
   585     }
   587     @Override
   588     public Listener getListener() {
   589         return externalListener;
   590     }
   592     @Override
   593     public void setListener(Listener listener) {
   594         externalListener = listener;
   595     }
   597     public UnmarshallingContext getContext() {
   598         return coordinator;
   599     }
   601     @Override
   602     @SuppressWarnings("FinalizeDeclaration")
   603     protected void finalize() throws Throwable {
   604         try {
   605             ClassFactory.cleanCache();
   606         } finally {
   607             super.finalize();
   608         }
   609     }
   611     /**
   612      *  Must be called from same thread which created the UnmarshallerImpl instance.
   613      * @throws IOException
   614      */
   615     public void close() throws IOException {
   616         ClassFactory.cleanCache();
   617     }
   619 }

mercurial