ohair@286: /* mkos@397: * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. ohair@286: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ohair@286: * ohair@286: * This code is free software; you can redistribute it and/or modify it ohair@286: * under the terms of the GNU General Public License version 2 only, as ohair@286: * published by the Free Software Foundation. Oracle designates this ohair@286: * particular file as subject to the "Classpath" exception as provided ohair@286: * by Oracle in the LICENSE file that accompanied this code. ohair@286: * ohair@286: * This code is distributed in the hope that it will be useful, but WITHOUT ohair@286: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ohair@286: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ohair@286: * version 2 for more details (a copy is included in the LICENSE file that ohair@286: * accompanied this code). ohair@286: * ohair@286: * You should have received a copy of the GNU General Public License version ohair@286: * 2 along with this work; if not, write to the Free Software Foundation, ohair@286: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ohair@286: * ohair@286: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@286: * or visit www.oracle.com if you need additional information or have any ohair@286: * questions. ohair@286: */ ohair@286: ohair@286: package javax.xml.bind.helpers; ohair@286: ohair@286: import org.xml.sax.InputSource; ohair@286: import org.xml.sax.SAXException; ohair@286: import org.xml.sax.XMLReader; ohair@286: import org.w3c.dom.Node; ohair@286: ohair@286: import javax.xml.bind.JAXBException; ohair@286: import javax.xml.bind.PropertyException; ohair@286: import javax.xml.bind.UnmarshalException; ohair@286: import javax.xml.bind.Unmarshaller; ohair@286: import javax.xml.bind.ValidationEventHandler; ohair@286: import javax.xml.bind.JAXBElement; ohair@286: import javax.xml.bind.annotation.adapters.XmlAdapter; ohair@286: import javax.xml.bind.attachment.AttachmentUnmarshaller; ohair@286: import javax.xml.parsers.ParserConfigurationException; ohair@286: import javax.xml.parsers.SAXParserFactory; ohair@286: import javax.xml.stream.XMLEventReader; ohair@286: import javax.xml.stream.XMLStreamReader; ohair@286: import javax.xml.transform.Source; ohair@286: import javax.xml.transform.dom.DOMSource; ohair@286: import javax.xml.transform.sax.SAXSource; ohair@286: import javax.xml.transform.stream.StreamSource; ohair@286: import javax.xml.validation.Schema; ohair@286: import java.io.File; ohair@286: import java.io.Reader; ohair@286: import java.net.MalformedURLException; ohair@286: import java.net.URL; ohair@286: ohair@286: /** ohair@286: * Partial default Unmarshaller implementation. ohair@286: * ohair@286: *

ohair@286: * This class provides a partial default implementation for the ohair@286: * {@link javax.xml.bind.Unmarshaller}interface. ohair@286: * ohair@286: *

ohair@286: * A JAXB Provider has to implement five methods (getUnmarshallerHandler, ohair@286: * unmarshal(Node), unmarshal(XMLReader,InputSource), ohair@286: * unmarshal(XMLStreamReader), and unmarshal(XMLEventReader). ohair@286: * ohair@286: * @author

ohair@286: * @see javax.xml.bind.Unmarshaller ohair@286: * @since JAXB1.0 ohair@286: */ ohair@286: public abstract class AbstractUnmarshallerImpl implements Unmarshaller ohair@286: { ohair@286: /** handler that will be used to process errors and warnings during unmarshal */ ohair@286: private ValidationEventHandler eventHandler = ohair@286: new DefaultValidationEventHandler(); ohair@286: ohair@286: /** whether or not the unmarshaller will validate */ ohair@286: protected boolean validating = false; ohair@286: ohair@286: /** ohair@286: * XMLReader that will be used to parse a document. ohair@286: */ ohair@286: private XMLReader reader = null; ohair@286: ohair@286: /** ohair@286: * Obtains a configured XMLReader. ohair@286: * ohair@286: * This method is used when the client-specified ohair@286: * {@link SAXSource} object doesn't have XMLReader. ohair@286: * ohair@286: * {@link Unmarshaller} is not re-entrant, so we will ohair@286: * only use one instance of XMLReader. ohair@286: */ ohair@286: protected XMLReader getXMLReader() throws JAXBException { ohair@286: if(reader==null) { ohair@286: try { ohair@286: SAXParserFactory parserFactory; ohair@286: parserFactory = SAXParserFactory.newInstance(); ohair@286: parserFactory.setNamespaceAware(true); ohair@286: // there is no point in asking a validation because ohair@286: // there is no guarantee that the document will come with ohair@286: // a proper schemaLocation. ohair@286: parserFactory.setValidating(false); ohair@286: reader = parserFactory.newSAXParser().getXMLReader(); ohair@286: } catch( ParserConfigurationException e ) { ohair@286: throw new JAXBException(e); ohair@286: } catch( SAXException e ) { ohair@286: throw new JAXBException(e); ohair@286: } ohair@286: } ohair@286: return reader; ohair@286: } ohair@286: ohair@286: public Object unmarshal( Source source ) throws JAXBException { ohair@286: if( source == null ) { ohair@286: throw new IllegalArgumentException( ohair@286: Messages.format( Messages.MUST_NOT_BE_NULL, "source" ) ); ohair@286: } ohair@286: ohair@286: if(source instanceof SAXSource) ohair@286: return unmarshal( (SAXSource)source ); ohair@286: if(source instanceof StreamSource) ohair@286: return unmarshal( streamSourceToInputSource((StreamSource)source)); ohair@286: if(source instanceof DOMSource) ohair@286: return unmarshal( ((DOMSource)source).getNode() ); ohair@286: ohair@286: // we don't handle other types of Source ohair@286: throw new IllegalArgumentException(); ohair@286: } ohair@286: ohair@286: // use the client specified XMLReader contained in the SAXSource. ohair@286: private Object unmarshal( SAXSource source ) throws JAXBException { ohair@286: ohair@286: XMLReader r = source.getXMLReader(); ohair@286: if( r == null ) ohair@286: r = getXMLReader(); ohair@286: ohair@286: return unmarshal( r, source.getInputSource() ); ohair@286: } ohair@286: ohair@286: /** ohair@286: * Unmarshals an object by using the specified XMLReader and the InputSource. ohair@286: * ohair@286: * The callee should call the setErrorHandler method of the XMLReader ohair@286: * so that errors are passed to the client-specified ValidationEventHandler. ohair@286: */ ohair@286: protected abstract Object unmarshal( XMLReader reader, InputSource source ) throws JAXBException; ohair@286: ohair@286: public final Object unmarshal( InputSource source ) throws JAXBException { ohair@286: if( source == null ) { ohair@286: throw new IllegalArgumentException( ohair@286: Messages.format( Messages.MUST_NOT_BE_NULL, "source" ) ); ohair@286: } ohair@286: ohair@286: return unmarshal( getXMLReader(), source ); ohair@286: } ohair@286: ohair@286: ohair@286: private Object unmarshal( String url ) throws JAXBException { ohair@286: return unmarshal( new InputSource(url) ); ohair@286: } ohair@286: ohair@286: public final Object unmarshal( URL url ) throws JAXBException { ohair@286: if( url == null ) { ohair@286: throw new IllegalArgumentException( ohair@286: Messages.format( Messages.MUST_NOT_BE_NULL, "url" ) ); ohair@286: } ohair@286: ohair@286: return unmarshal( url.toExternalForm() ); ohair@286: } ohair@286: ohair@286: public final Object unmarshal( File f ) throws JAXBException { ohair@286: if( f == null ) { ohair@286: throw new IllegalArgumentException( ohair@286: Messages.format( Messages.MUST_NOT_BE_NULL, "file" ) ); ohair@286: } ohair@286: ohair@286: try { ohair@286: // copied from JAXP ohair@286: String path = f.getAbsolutePath(); ohair@286: if (File.separatorChar != '/') ohair@286: path = path.replace(File.separatorChar, '/'); ohair@286: if (!path.startsWith("/")) ohair@286: path = "/" + path; ohair@286: if (!path.endsWith("/") && f.isDirectory()) ohair@286: path = path + "/"; ohair@286: return unmarshal(new URL("file", "", path)); ohair@286: } catch( MalformedURLException e ) { ohair@286: throw new IllegalArgumentException(e.getMessage()); ohair@286: } ohair@286: } ohair@286: ohair@286: public final Object unmarshal( java.io.InputStream is ) ohair@286: throws JAXBException { ohair@286: ohair@286: if( is == null ) { ohair@286: throw new IllegalArgumentException( ohair@286: Messages.format( Messages.MUST_NOT_BE_NULL, "is" ) ); ohair@286: } ohair@286: ohair@286: InputSource isrc = new InputSource( is ); ohair@286: return unmarshal( isrc ); ohair@286: } ohair@286: ohair@286: public final Object unmarshal( Reader reader ) throws JAXBException { ohair@286: if( reader == null ) { ohair@286: throw new IllegalArgumentException( ohair@286: Messages.format( Messages.MUST_NOT_BE_NULL, "reader" ) ); ohair@286: } ohair@286: ohair@286: InputSource isrc = new InputSource( reader ); ohair@286: return unmarshal( isrc ); ohair@286: } ohair@286: ohair@286: ohair@286: private static InputSource streamSourceToInputSource( StreamSource ss ) { ohair@286: InputSource is = new InputSource(); ohair@286: is.setSystemId( ss.getSystemId() ); ohair@286: is.setByteStream( ss.getInputStream() ); ohair@286: is.setCharacterStream( ss.getReader() ); ohair@286: ohair@286: return is; ohair@286: } ohair@286: ohair@286: ohair@286: /** ohair@286: * Indicates whether or not the Unmarshaller is configured to validate ohair@286: * during unmarshal operations. ohair@286: *

ohair@286: * Note: I named this method isValidating() to stay in-line ohair@286: * with JAXP, as opposed to naming it getValidating(). ohair@286: * ohair@286: * @return true if the Unmarshaller is configured to validate during ohair@286: * unmarshal operations, false otherwise ohair@286: * @throws JAXBException if an error occurs while retrieving the validating ohair@286: * flag ohair@286: */ ohair@286: public boolean isValidating() throws JAXBException { ohair@286: return validating; ohair@286: } ohair@286: ohair@286: /** ohair@286: * Allow an application to register a validation event handler. ohair@286: *

ohair@286: * The validation event handler will be called by the JAXB Provider if any ohair@286: * validation errors are encountered during calls to any of the ohair@286: * unmarshal methods. If the client application does not register ohair@286: * a validation event handler before invoking the unmarshal methods, then ohair@286: * all validation events will be silently ignored and may result in ohair@286: * unexpected behaviour. ohair@286: * ohair@286: * @param handler the validation event handler ohair@286: * @throws JAXBException if an error was encountered while setting the ohair@286: * event handler ohair@286: */ ohair@286: public void setEventHandler(ValidationEventHandler handler) ohair@286: throws JAXBException { ohair@286: ohair@286: if( handler == null ) { ohair@286: eventHandler = new DefaultValidationEventHandler(); ohair@286: } else { ohair@286: eventHandler = handler; ohair@286: } ohair@286: } ohair@286: ohair@286: /** ohair@286: * Specifies whether or not the Unmarshaller should validate during ohair@286: * unmarshal operations. By default, the Unmarshaller does ohair@286: * not validate. ohair@286: *

ohair@286: * This method may only be invoked before or after calling one of the ohair@286: * unmarshal methods. ohair@286: * ohair@286: * @param validating true if the Unmarshaller should validate during ohair@286: * unmarshal, false otherwise ohair@286: * @throws JAXBException if an error occurred while enabling or disabling ohair@286: * validation at unmarshal time ohair@286: */ ohair@286: public void setValidating(boolean validating) throws JAXBException { ohair@286: this.validating = validating; ohair@286: } ohair@286: ohair@286: /** ohair@286: * Return the current event handler or the default event handler if one ohair@286: * hasn't been set. ohair@286: * ohair@286: * @return the current ValidationEventHandler or the default event handler ohair@286: * if it hasn't been set ohair@286: * @throws JAXBException if an error was encountered while getting the ohair@286: * current event handler ohair@286: */ ohair@286: public ValidationEventHandler getEventHandler() throws JAXBException { ohair@286: return eventHandler; ohair@286: } ohair@286: ohair@286: ohair@286: /** ohair@286: * Creates an UnmarshalException from a SAXException. ohair@286: * ohair@286: * This is an utility method provided for the derived classes. ohair@286: * ohair@286: *

ohair@286: * When a provider-implemented ContentHandler wants to throw a ohair@286: * JAXBException, it needs to wrap the exception by a SAXException. ohair@286: * If the unmarshaller implementation blindly wrap SAXException ohair@286: * by JAXBException, such an exception will be a JAXBException ohair@286: * wrapped by a SAXException wrapped by another JAXBException. ohair@286: * This is silly. ohair@286: * ohair@286: *

ohair@286: * This method checks the nested exception of SAXException ohair@286: * and reduce those excessive wrapping. ohair@286: * ohair@286: * @return the resulting UnmarshalException ohair@286: */ ohair@286: protected UnmarshalException createUnmarshalException( SAXException e ) { ohair@286: // check the nested exception to see if it's an UnmarshalException ohair@286: Exception nested = e.getException(); ohair@286: if(nested instanceof UnmarshalException) ohair@286: return (UnmarshalException)nested; ohair@286: ohair@286: if(nested instanceof RuntimeException) ohair@286: // typically this is an unexpected exception, ohair@286: // just throw it rather than wrap it, so that the full stack ohair@286: // trace can be displayed. ohair@286: throw (RuntimeException)nested; ohair@286: ohair@286: ohair@286: // otherwise simply wrap it ohair@286: if(nested!=null) ohair@286: return new UnmarshalException(nested); ohair@286: else ohair@286: return new UnmarshalException(e); ohair@286: } ohair@286: ohair@286: /** ohair@286: * Default implementation of the setProperty method always ohair@286: * throws PropertyException since there are no required ohair@286: * properties. If a provider needs to handle additional ohair@286: * properties, it should override this method in a derived class. ohair@286: */ ohair@286: public void setProperty( String name, Object value ) ohair@286: throws PropertyException { ohair@286: ohair@286: if( name == null ) { ohair@286: throw new IllegalArgumentException( ohair@286: Messages.format( Messages.MUST_NOT_BE_NULL, "name" ) ); ohair@286: } ohair@286: ohair@286: throw new PropertyException(name, value); ohair@286: } ohair@286: ohair@286: /** ohair@286: * Default implementation of the getProperty method always ohair@286: * throws PropertyException since there are no required ohair@286: * properties. If a provider needs to handle additional ohair@286: * properties, it should override this method in a derived class. ohair@286: */ ohair@286: public Object getProperty( String name ) ohair@286: throws PropertyException { ohair@286: ohair@286: if( name == null ) { ohair@286: throw new IllegalArgumentException( ohair@286: Messages.format( Messages.MUST_NOT_BE_NULL, "name" ) ); ohair@286: } ohair@286: ohair@286: throw new PropertyException(name); ohair@286: } ohair@286: ohair@286: public Object unmarshal(XMLEventReader reader) throws JAXBException { ohair@286: ohair@286: throw new UnsupportedOperationException(); ohair@286: } ohair@286: ohair@286: public Object unmarshal(XMLStreamReader reader) throws JAXBException { ohair@286: ohair@286: throw new UnsupportedOperationException(); ohair@286: } ohair@286: ohair@286: public JAXBElement unmarshal(Node node, Class expectedType) throws JAXBException { ohair@286: throw new UnsupportedOperationException(); ohair@286: } ohair@286: ohair@286: public JAXBElement unmarshal(Source source, Class expectedType) throws JAXBException { ohair@286: throw new UnsupportedOperationException(); ohair@286: } ohair@286: ohair@286: public JAXBElement unmarshal(XMLStreamReader reader, Class expectedType) throws JAXBException { ohair@286: throw new UnsupportedOperationException(); ohair@286: } ohair@286: ohair@286: public JAXBElement unmarshal(XMLEventReader reader, Class expectedType) throws JAXBException { ohair@286: throw new UnsupportedOperationException(); ohair@286: } ohair@286: ohair@286: public void setSchema(Schema schema) { ohair@286: throw new UnsupportedOperationException(); ohair@286: } ohair@286: ohair@286: public Schema getSchema() { ohair@286: throw new UnsupportedOperationException(); ohair@286: } ohair@286: ohair@286: public void setAdapter(XmlAdapter adapter) { ohair@286: if(adapter==null) ohair@286: throw new IllegalArgumentException(); ohair@286: setAdapter((Class)adapter.getClass(),adapter); ohair@286: } ohair@286: ohair@286: public void setAdapter(Class type, A adapter) { ohair@286: throw new UnsupportedOperationException(); ohair@286: } ohair@286: ohair@286: public A getAdapter(Class type) { ohair@286: throw new UnsupportedOperationException(); ohair@286: } ohair@286: ohair@286: public void setAttachmentUnmarshaller(AttachmentUnmarshaller au) { ohair@286: throw new UnsupportedOperationException(); ohair@286: } ohair@286: ohair@286: public AttachmentUnmarshaller getAttachmentUnmarshaller() { ohair@286: throw new UnsupportedOperationException(); ohair@286: } ohair@286: ohair@286: public void setListener(Listener listener) { ohair@286: throw new UnsupportedOperationException(); ohair@286: } ohair@286: ohair@286: public Listener getListener() { ohair@286: throw new UnsupportedOperationException(); ohair@286: } ohair@286: }