/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2013 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 jaxb1.impl.runtime;
import java.io.IOException;
import javax.xml.bind.JAXBException;
import javax.xml.bind.UnmarshallerHandler;
import javax.xml.bind.helpers.AbstractUnmarshallerImpl;
import javax.xml.transform.sax.SAXSource;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import com.sun.xml.bind.unmarshaller.DOMScanner;
import com.sun.xml.bind.unmarshaller.InterningXMLReader;
import com.sun.xml.bind.validator.DOMLocator;
import com.sun.xml.bind.validator.Locator;
import com.sun.xml.bind.validator.SAXLocator;
/**
* Default Unmarshall implementation.
*
* <p>
* This class can be extended by the generated code to provide
* type-safe unmarshall methods.
*
* @author
* <a href="mailto:kohsuke.kawaguchi@sun.com">Kohsuke KAWAGUCHI</a>
*/
public class UnmarshallerImpl extends AbstractUnmarshallerImpl
{
/** parent JAXBContext object that created this unmarshaller */
private DefaultJAXBContextImpl context = null;
private final GrammarInfo grammarInfo;
public UnmarshallerImpl( DefaultJAXBContextImpl context, GrammarInfo gi ) {
this.context = context;
this.grammarInfo = gi;
// initialize datatype converter with ours
// DatatypeConverter.setDatatypeConverter(DatatypeConverterImpl.theInstance); NOT ALLOWED any more for the security reasons
}
public void setValidating(boolean validating) throws JAXBException {
super.setValidating(validating);
if(validating==true)
// make sure that we can actually load the grammar.
// this could be a lengthy operation if your schema is big.
context.getGrammar();
}
public UnmarshallerHandler getUnmarshallerHandler() {
// use InterningUnmarshallerHandler since we don't know
// if the caller will intern Strings before firing SAX events.
// we don't know the Locator to be used,
// but SAXLocator would always be a good default,
// as the source of SAX2 events can always set org.xml.sax.Locator.
return new InterningUnmarshallerHandler(
createUnmarshallerHandler(new SAXLocator()));
}
/**
* Creates and configures a new unmarshalling pipe line.
* Depending on the setting, we put a validator as a filter.
*
* @return
* A component that implements both UnmarshallerHandler
* and ValidationEventHandler. All the parsing errors
* should be reported to this error handler for the unmarshalling
* process to work correctly.
*
* @param locator
* The object that is responsible to obtain the source
* location information for {@link ValidationEvent}s.
*/
private SAXUnmarshallerHandler createUnmarshallerHandler( Locator locator ) {
SAXUnmarshallerHandler unmarshaller =
new SAXUnmarshallerHandlerImpl( this, grammarInfo );
try {
// use the simple check to determine if validation is on
if( isValidating() ) {
// if the validation is turned on, insert another
// component into the event pipe line.
unmarshaller = ValidatingUnmarshaller.create(
context.getGrammar(), unmarshaller, locator );
}
} catch( JAXBException e ) {
// impossible since we've already made sure that a grammar is accessible.
e.printStackTrace();
}
return unmarshaller;
}
protected Object unmarshal( XMLReader reader, InputSource source ) throws JAXBException {
SAXLocator locator = new SAXLocator();
SAXUnmarshallerHandler handler = createUnmarshallerHandler(locator);
reader = InterningXMLReader.adapt(reader);
reader.setContentHandler(handler);
// saxErrorHandler will be set by the createUnmarshallerHandler method.
// configure XMLReader so that the error will be sent to it.
// This is essential for the UnmarshallerHandler to be able to abort
// unmarshalling when an error is found.
//
// Note that when this XMLReader is provided by the client code,
// it might be already configured to call a client error handler.
// This will clobber such handler, if any.
//
// Ryan noted that we might want to report errors to such a client
// error handler as well.
reader.setErrorHandler(
new ErrorHandlerAdaptor(handler,locator));
try {
reader.parse(source);
} catch( IOException e ) {
throw new JAXBException(e);
} catch( SAXException e ) {
throw createUnmarshalException(e);
}
Object result = handler.getResult();
// avoid keeping unnecessary references too long to let the GC
// reclaim more memory.
// setting null upsets some parsers, so use a dummy instance instead.
reader.setContentHandler(dummyHandler);
reader.setErrorHandler(dummyHandler);
return result;
}
public final Object unmarshal( Node node ) throws JAXBException {
try {
DOMScanner scanner = new DOMScanner();
UnmarshallerHandler handler = new InterningUnmarshallerHandler(
createUnmarshallerHandler(new DOMLocator(scanner)));
if(node instanceof Element)
scanner.parse((Element)node,handler);
else
if(node instanceof Document)
scanner.parse(((Document)node).getDocumentElement(),handler);
else
// no other type of input is supported
throw new IllegalArgumentException();
return handler.getResult();
} catch( SAXException e ) {
throw createUnmarshalException(e);
}
}
// just to make the the test harness happy by making this method accessible
public final Object unmarshal( SAXSource source ) throws JAXBException {
return super.unmarshal(source);
}
private static final DefaultHandler dummyHandler = new DefaultHandler();
}