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

Print this page


   1 /*
   2  * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


  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;
  53 
  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 
  64 import java.io.Closeable;


  65 import org.w3c.dom.Document;
  66 import org.w3c.dom.Element;
  67 import org.w3c.dom.Node;
  68 import org.xml.sax.InputSource;
  69 import org.xml.sax.SAXException;
  70 import org.xml.sax.XMLReader;
  71 import org.xml.sax.helpers.DefaultHandler;
  72 
  73 /**
  74  * Default Unmarshaller implementation.
  75  *
  76  * <p>
  77  * This class can be extended by the generated code to provide
  78  * type-safe unmarshall methods.
  79  *
  80  * @author
  81  *  <a href="mailto:kohsuke.kawaguchi@sun.com">Kohsuke KAWAGUCHI</a>
  82  */
  83 public final class UnmarshallerImpl extends AbstractUnmarshallerImpl implements ValidationEventHandler, Closeable
  84 {
  85     /** Owning {@link JAXBContext} */
  86     protected final JAXBContextImpl context;
  87 
  88     /**
  89      * schema which will be used to validate during calls to unmarshal
  90      */
  91     private Schema schema;
  92 
  93     public final UnmarshallingContext coordinator;
  94 
  95     /** Unmarshaller.Listener */
  96     private Listener externalListener;
  97 
  98     /**
  99      * The attachment unmarshaller used to support MTOM and swaRef.
 100      */
 101     private AttachmentUnmarshaller attachmentUnmarshaller;
 102     private IDResolver idResolver = new DefaultIDResolver();
 103 
 104     public UnmarshallerImpl( JAXBContextImpl context, AssociationMap assoc ) {
 105         this.context = context;
 106         this.coordinator = new UnmarshallingContext( this, assoc );
 107 
 108         try {
 109             setEventHandler(this);
 110         } catch (JAXBException e) {
 111             throw new AssertionError(e);    // impossible
 112         }
 113     }
 114 
 115     public UnmarshallerHandler getUnmarshallerHandler() {
 116         return getUnmarshallerHandler(true,null);
 117     }
 118 
































 119     private SAXConnector getUnmarshallerHandler( boolean intern, JaxBeanInfo expectedType ) {
 120         XmlVisitor h = createUnmarshallerHandler(null,false,expectedType);
 121         if(intern)
 122             h = new InterningXmlVisitor(h);

 123         return new SAXConnector(h,null);
 124     }
 125 
 126     /**
 127      * Creates and configures a new unmarshalling pipe line.
 128      * Depending on the setting, we put a validator as a filter.
 129      *
 130      * @return
 131      *      A component that implements both {@link UnmarshallerHandler}
 132      *      and {@link ValidationEventHandler}. All the parsing errors
 133      *      should be reported to this error handler for the unmarshalling
 134      *      process to work correctly.
 135      *
 136      *      Also, returned handler expects all the XML names to be interned.
 137      *
 138      */
 139     public final XmlVisitor createUnmarshallerHandler(InfosetScanner scanner, boolean inplace, JaxBeanInfo expectedType ) {
 140 
 141         coordinator.reset(scanner,inplace,expectedType,idResolver);
 142         XmlVisitor unmarshaller = coordinator;
 143 
 144         // delegate to JAXP 1.3 for validation if the client provided a schema
 145         if (schema != null)
 146             unmarshaller = new ValidatingUnmarshaller(schema,unmarshaller);

 147 
 148         if(attachmentUnmarshaller!=null && attachmentUnmarshaller.isXOPPackage())
 149             unmarshaller = new MTOMDecorator(this,unmarshaller,attachmentUnmarshaller);

 150 
 151         return unmarshaller;
 152     }
 153 
 154     private static final DefaultHandler dummyHandler = new DefaultHandler();
 155 
 156     public static boolean needsInterning( XMLReader reader ) {
 157         // attempt to set it to true, which could fail
 158         try {
 159             reader.setFeature("http://xml.org/sax/features/string-interning",true);
 160         } catch (SAXException e) {
 161             // if it fails that's fine. we'll work around on our side
 162         }
 163 
 164         try {
 165             if( reader.getFeature("http://xml.org/sax/features/string-interning") )
 166                 return false;   // no need for intern

 167         } catch (SAXException e) {
 168             // unrecognized/unsupported
 169         }
 170         // otherwise we need intern
 171         return true;
 172     }
 173 
 174     protected Object unmarshal( XMLReader reader, InputSource source ) throws JAXBException {
 175         return unmarshal0(reader,source,null);
 176     }
 177 
 178     protected <T> JAXBElement<T> unmarshal( XMLReader reader, InputSource source, Class<T> expectedType ) throws JAXBException {
 179         if(expectedType==null)
 180             throw new IllegalArgumentException();

 181         return (JAXBElement)unmarshal0(reader,source,getBeanInfo(expectedType));
 182     }
 183 
 184     private Object unmarshal0( XMLReader reader, InputSource source, JaxBeanInfo expectedType ) throws JAXBException {
 185 
 186         SAXConnector connector = getUnmarshallerHandler(needsInterning(reader),expectedType);
 187 
 188         reader.setContentHandler(connector);
 189         // saxErrorHandler will be set by the getUnmarshallerHandler method.
 190         // configure XMLReader so that the error will be sent to it.
 191         // This is essential for the UnmarshallerHandler to be able to abort
 192         // unmarshalling when an error is found.
 193         //
 194         // Note that when this XMLReader is provided by the client code,
 195         // it might be already configured to call a client error handler.
 196         // This will clobber such handler, if any.
 197         //
 198         // Ryan noted that we might want to report errors to such a client
 199         // error handler as well.
 200         reader.setErrorHandler(coordinator);


 205             coordinator.clearStates();
 206             throw new UnmarshalException(e);
 207         } catch( SAXException e ) {
 208             coordinator.clearStates();
 209             throw createUnmarshalException(e);
 210         }
 211 
 212         Object result = connector.getResult();
 213 
 214         // avoid keeping unnecessary references too long to let the GC
 215         // reclaim more memory.
 216         // setting null upsets some parsers, so use a dummy instance instead.
 217         reader.setContentHandler(dummyHandler);
 218         reader.setErrorHandler(dummyHandler);
 219 
 220         return result;
 221     }
 222 
 223     @Override
 224     public <T> JAXBElement<T> unmarshal( Source source, Class<T> expectedType ) throws JAXBException {
 225         if(source instanceof SAXSource) {
 226             SAXSource ss = (SAXSource)source;
 227 
 228             XMLReader reader = ss.getXMLReader();
 229             if( reader == null )
 230                 reader = getXMLReader();

 231 
 232             return unmarshal( reader, ss.getInputSource(), expectedType );



 233         }
 234         if(source instanceof StreamSource) {
 235             return unmarshal( getXMLReader(), streamSourceToInputSource((StreamSource)source), expectedType );
 236         }
 237         if(source instanceof DOMSource)
 238             return unmarshal( ((DOMSource)source).getNode(), expectedType );
 239 
 240         // we don't handle other types of Source
 241         throw new IllegalArgumentException();
 242     }
 243 
 244     public Object unmarshal0( Source source, JaxBeanInfo expectedType ) throws JAXBException {
 245         if(source instanceof SAXSource) {
 246             SAXSource ss = (SAXSource)source;
 247 
 248             XMLReader reader = ss.getXMLReader();
 249             if( reader == null )
 250                 reader = getXMLReader();

 251 
 252             return unmarshal0( reader, ss.getInputSource(), expectedType );



 253         }
 254         if(source instanceof StreamSource) {
 255             return unmarshal0( getXMLReader(), streamSourceToInputSource((StreamSource)source), expectedType );
 256         }
 257         if(source instanceof DOMSource)
 258             return unmarshal0( ((DOMSource)source).getNode(), expectedType );
 259 
 260         // we don't handle other types of Source
 261         throw new IllegalArgumentException();
 262     }
 263 
 264 
 265     @Override
 266     public final ValidationEventHandler getEventHandler() {
 267         try {
 268             return super.getEventHandler();
 269         } catch (JAXBException e) {
 270             // impossible
 271             throw new AssertionError();
 272         }
 273     }
 274 
 275     /**
 276      * Returns true if an event handler is installed.
 277      * <p>
 278      * The default handler ignores any errors, and for that this method returns false.
 279      */
 280     public final boolean hasEventHandler() {
 281         return getEventHandler()!=this;
 282     }
 283 
 284     @Override
 285     public <T> JAXBElement<T> unmarshal(Node node, Class<T> expectedType) throws JAXBException {
 286         if(expectedType==null)
 287             throw new IllegalArgumentException();

 288         return (JAXBElement)unmarshal0(node,getBeanInfo(expectedType));
 289     }
 290 
 291     public final Object unmarshal( Node node ) throws JAXBException {
 292         return unmarshal0(node,null);
 293     }
 294 
 295     // just to make the the test harness happy by making this method accessible
 296     @Deprecated
 297     public final Object unmarshal( SAXSource source ) throws JAXBException {
 298         return super.unmarshal(source);
 299     }
 300 
 301     public final Object unmarshal0( Node node, JaxBeanInfo expectedType ) throws JAXBException {
 302         try {
 303             final DOMScanner scanner = new DOMScanner();
 304 
 305             InterningXmlVisitor handler = new InterningXmlVisitor(createUnmarshallerHandler(null,false,expectedType));
 306             scanner.setContentHandler(new SAXConnector(handler,scanner));
 307 
 308             if(node.getNodeType() == Node.ELEMENT_NODE)
 309                 scanner.scan((Element)node);
 310             else
 311             if(node.getNodeType() == Node.DOCUMENT_NODE)
 312                 scanner.scan((Document)node);
 313             else
 314                 // no other type of input is supported
 315                 throw new IllegalArgumentException("Unexpected node type: "+node);

 316 
 317             Object retVal = handler.getContext().getResult();
 318             handler.getContext().clearResult();
 319             return retVal;
 320         } catch( SAXException e ) {
 321             throw createUnmarshalException(e);
 322         }
 323     }
 324 
 325     @Override
 326     public Object unmarshal(XMLStreamReader reader) throws JAXBException {
 327         return unmarshal0(reader,null);
 328     }
 329 
 330     @Override
 331     public <T> JAXBElement<T> unmarshal(XMLStreamReader reader, Class<T> expectedType) throws JAXBException {
 332         if(expectedType==null)
 333             throw new IllegalArgumentException();

 334         return (JAXBElement)unmarshal0(reader,getBeanInfo(expectedType));
 335     }
 336 
 337     public Object unmarshal0(XMLStreamReader reader, JaxBeanInfo expectedType) throws JAXBException {
 338         if (reader == null) {
 339             throw new IllegalArgumentException(
 340                 Messages.format(Messages.NULL_READER));
 341         }
 342 
 343         int eventType = reader.getEventType();
 344         if (eventType != XMLStreamConstants.START_ELEMENT
 345             && eventType != XMLStreamConstants.START_DOCUMENT) {
 346             // TODO: convert eventType into event name
 347             throw new IllegalStateException(
 348                 Messages.format(Messages.ILLEGAL_READER_STATE,eventType));
 349         }
 350 
 351         XmlVisitor h = createUnmarshallerHandler(null,false,expectedType);
 352         StAXConnector connector=StAXStreamConnector.create(reader,h);
 353 
 354         try {
 355             connector.bridge();
 356         } catch (XMLStreamException e) {
 357             throw handleStreamException(e);
 358         }
 359 
 360         Object retVal = h.getContext().getResult();
 361         h.getContext().clearResult();
 362         return retVal;
 363     }
 364 
 365     @Override
 366     public <T> JAXBElement<T> unmarshal(XMLEventReader reader, Class<T> expectedType) throws JAXBException {
 367         if(expectedType==null)
 368             throw new IllegalArgumentException();

 369         return (JAXBElement)unmarshal0(reader,getBeanInfo(expectedType));
 370     }
 371 
 372     @Override
 373     public Object unmarshal(XMLEventReader reader) throws JAXBException {
 374         return unmarshal0(reader,null);
 375     }
 376 
 377     private Object unmarshal0(XMLEventReader reader,JaxBeanInfo expectedType) throws JAXBException {
 378         if (reader == null) {
 379             throw new IllegalArgumentException(
 380                     Messages.format(Messages.NULL_READER));
 381         }
 382 
 383         try {
 384             XMLEvent event = reader.peek();
 385 
 386             if (!event.isStartElement() && !event.isStartDocument()) {
 387                 // TODO: convert event into event name
 388                 throw new IllegalStateException(
 389                     Messages.format(
 390                         Messages.ILLEGAL_READER_STATE,event.getEventType()));
 391             }
 392 
 393             // Quick hack until SJSXP fixes 6270116
 394             boolean isZephyr = reader.getClass().getName().equals("com.sun.xml.internal.stream.XMLReaderImpl");
 395             XmlVisitor h = createUnmarshallerHandler(null,false,expectedType);
 396             if(!isZephyr)
 397                 h = new InterningXmlVisitor(h);

 398             new StAXEventConnector(reader,h).bridge();
 399             return h.getContext().getResult();
 400         } catch (XMLStreamException e) {
 401             throw handleStreamException(e);
 402         }
 403     }
 404 
 405     public Object unmarshal0( InputStream input, JaxBeanInfo expectedType ) throws JAXBException {
 406         return unmarshal0(getXMLReader(),new InputSource(input),expectedType);
 407     }
 408 
 409     private static JAXBException handleStreamException(XMLStreamException e) {
 410         // StAXStreamConnector wraps SAXException to XMLStreamException.
 411         // XMLStreamException doesn't print its nested stack trace when it prints
 412         // its stack trace, so if we wrap XMLStreamException in JAXBException,
 413         // it becomes harder to find out the real problem.
 414         // So we unwrap them here. But we don't want to unwrap too eagerly, because
 415         // that could throw away some meaningful exception information.
 416         Throwable ne = e.getNestedException();
 417         if(ne instanceof JAXBException)
 418             return (JAXBException)ne;
 419         if(ne instanceof SAXException)

 420             return new UnmarshalException(ne);

 421         return new UnmarshalException(e);
 422     }
 423 
 424     @Override
 425     public Object getProperty(String name) throws PropertyException {
 426         if(name.equals(IDResolver.class.getName())) {
 427             return idResolver;
 428         }
 429         return super.getProperty(name);
 430     }
 431 
 432     @Override
 433     public void setProperty(String name, Object value) throws PropertyException {
 434         if(name.equals(FACTORY)) {
 435             coordinator.setFactories(value);
 436             return;
 437         }
 438         if(name.equals(IDResolver.class.getName())) {
 439             idResolver = (IDResolver)value;
 440             return;


 473     }
 474 
 475     /**
 476      * @deprecated since 2.0
 477      */
 478     @Override
 479     public boolean isValidating() {
 480         throw new UnsupportedOperationException();
 481     }
 482 
 483     /**
 484      * @deprecated since 2.0
 485      */
 486     @Override
 487     public void setValidating(boolean validating) {
 488         throw new UnsupportedOperationException();
 489     }
 490 
 491     @Override
 492     public <A extends XmlAdapter> void setAdapter(Class<A> type, A adapter) {
 493         if(type==null)
 494             throw new IllegalArgumentException();

 495         coordinator.putAdapter(type,adapter);
 496     }
 497 
 498     @Override
 499     public <A extends XmlAdapter> A getAdapter(Class<A> type) {
 500         if(type==null)
 501             throw new IllegalArgumentException();
 502         if(coordinator.containsAdapter(type))
 503             // so as not to create a new instance when this method is called
 504             return coordinator.getAdapter(type);
 505         else
 506             return null;

 507     }
 508 
 509     // opening up for public use
 510     @Override
 511     public UnmarshalException createUnmarshalException( SAXException e ) {
 512         return super.createUnmarshalException(e);
 513     }
 514 
 515 
 516     /**
 517      * Default error handling behavior for {@link Unmarshaller}.
 518      */
 519     public boolean handleEvent(ValidationEvent event) {
 520         return event.getSeverity()!=ValidationEvent.FATAL_ERROR;
 521     }
 522 
 523     private static InputSource streamSourceToInputSource( StreamSource ss ) {
 524         InputSource is = new InputSource();
 525         is.setSystemId( ss.getSystemId() );
 526         is.setByteStream( ss.getInputStream() );


   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


  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;
  53 
  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;
  64 
  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;
  75 
  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;
  90 
  91     /**
  92      * schema which will be used to validate during calls to unmarshal
  93      */
  94     private Schema schema;
  95 
  96     public final UnmarshallingContext coordinator;
  97 
  98     /** Unmarshaller.Listener */
  99     private Listener externalListener;
 100 
 101     /**
 102      * The attachment unmarshaller used to support MTOM and swaRef.
 103      */
 104     private AttachmentUnmarshaller attachmentUnmarshaller;
 105     private IDResolver idResolver = new DefaultIDResolver();
 106 
 107     public UnmarshallerImpl( JAXBContextImpl context, AssociationMap assoc ) {
 108         this.context = context;
 109         this.coordinator = new UnmarshallingContext( this, assoc );
 110 
 111         try {
 112             setEventHandler(this);
 113         } catch (JAXBException e) {
 114             throw new AssertionError(e);    // impossible
 115         }
 116     }
 117 
 118     public UnmarshallerHandler getUnmarshallerHandler() {
 119         return getUnmarshallerHandler(true,null);
 120     }
 121 
 122     private XMLReader reader = null;
 123 
 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      }
 153 
 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     }
 161 
 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 ) {
 176 
 177         coordinator.reset(scanner,inplace,expectedType,idResolver);
 178         XmlVisitor unmarshaller = coordinator;
 179 
 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         }
 184 
 185         if(attachmentUnmarshaller!=null && attachmentUnmarshaller.isXOPPackage()) {
 186             unmarshaller = new MTOMDecorator(this,unmarshaller,attachmentUnmarshaller);
 187         }
 188 
 189         return unmarshaller;
 190     }
 191 
 192     private static final DefaultHandler dummyHandler = new DefaultHandler();
 193 
 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         }
 201 
 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     }
 212 
 213     protected Object unmarshal( XMLReader reader, InputSource source ) throws JAXBException {
 214         return unmarshal0(reader,source,null);
 215     }
 216 
 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     }
 223 
 224     private Object unmarshal0( XMLReader reader, InputSource source, JaxBeanInfo expectedType ) throws JAXBException {
 225 
 226         SAXConnector connector = getUnmarshallerHandler(needsInterning(reader),expectedType);
 227 
 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);


 245             coordinator.clearStates();
 246             throw new UnmarshalException(e);
 247         } catch( SAXException e ) {
 248             coordinator.clearStates();
 249             throw createUnmarshalException(e);
 250         }
 251 
 252         Object result = connector.getResult();
 253 
 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);
 259 
 260         return result;
 261     }
 262 
 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;
 267 
 268             XMLReader locReader = ss.getXMLReader();
 269             if (locReader == null) {
 270                 locReader = getXMLReader();
 271             }
 272 
 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         }


 281 
 282         // we don't handle other types of Source
 283         throw new IllegalArgumentException();
 284     }
 285 
 286     public Object unmarshal0( Source source, JaxBeanInfo expectedType ) throws JAXBException {
 287         if (source instanceof SAXSource) {
 288             SAXSource ss = (SAXSource) source;
 289 
 290             XMLReader locReader = ss.getXMLReader();
 291             if (locReader == null) {
 292                 locReader = getXMLReader();
 293             }
 294 
 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         }


 303 
 304         // we don't handle other types of Source
 305         throw new IllegalArgumentException();
 306     }
 307 
 308 
 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     }
 318 
 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     }
 327 
 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     }
 335 
 336     public final Object unmarshal( Node node ) throws JAXBException {
 337         return unmarshal0(node,null);
 338     }
 339 
 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     }
 345 
 346     public final Object unmarshal0( Node node, JaxBeanInfo expectedType ) throws JAXBException {
 347         try {
 348             final DOMScanner scanner = new DOMScanner();
 349 
 350             InterningXmlVisitor handler = new InterningXmlVisitor(createUnmarshallerHandler(null,false,expectedType));
 351             scanner.setContentHandler(new SAXConnector(handler,scanner));
 352 
 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             }
 360 
 361             Object retVal = handler.getContext().getResult();
 362             handler.getContext().clearResult();
 363             return retVal;
 364         } catch( SAXException e ) {
 365             throw createUnmarshalException(e);
 366         }
 367     }
 368 
 369     @Override
 370     public Object unmarshal(XMLStreamReader reader) throws JAXBException {
 371         return unmarshal0(reader,null);
 372     }
 373 
 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     }
 381 
 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         }
 387 
 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         }
 395 
 396         XmlVisitor h = createUnmarshallerHandler(null,false,expectedType);
 397         StAXConnector connector=StAXStreamConnector.create(reader,h);
 398 
 399         try {
 400             connector.bridge();
 401         } catch (XMLStreamException e) {
 402             throw handleStreamException(e);
 403         }
 404 
 405         Object retVal = h.getContext().getResult();
 406         h.getContext().clearResult();
 407         return retVal;
 408     }
 409 
 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     }
 417 
 418     @Override
 419     public Object unmarshal(XMLEventReader reader) throws JAXBException {
 420         return unmarshal0(reader,null);
 421     }
 422 
 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         }
 428 
 429         try {
 430             XMLEvent event = reader.peek();
 431 
 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             }
 438 
 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     }
 451 
 452     public Object unmarshal0( InputStream input, JaxBeanInfo expectedType ) throws JAXBException {
 453         return unmarshal0(getXMLReader(),new InputSource(input),expectedType);
 454     }
 455 
 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     }
 472 
 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     }
 480 
 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;


 522     }
 523 
 524     /**
 525      * @deprecated since 2.0
 526      */
 527     @Override
 528     public boolean isValidating() {
 529         throw new UnsupportedOperationException();
 530     }
 531 
 532     /**
 533      * @deprecated since 2.0
 534      */
 535     @Override
 536     public void setValidating(boolean validating) {
 537         throw new UnsupportedOperationException();
 538     }
 539 
 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     }
 547 
 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     }
 559 
 560     // opening up for public use
 561     @Override
 562     public UnmarshalException createUnmarshalException( SAXException e ) {
 563         return super.createUnmarshalException(e);
 564     }
 565 
 566 
 567     /**
 568      * Default error handling behavior for {@link Unmarshaller}.
 569      */
 570     public boolean handleEvent(ValidationEvent event) {
 571         return event.getSeverity()!=ValidationEvent.FATAL_ERROR;
 572     }
 573 
 574     private static InputSource streamSourceToInputSource( StreamSource ss ) {
 575         InputSource is = new InputSource();
 576         is.setSystemId( ss.getSystemId() );
 577         is.setByteStream( ss.getInputStream() );