com.sun.xml.bind.unmarshaller.SAXUnmarshallerHandlerImpl Maven / Gradle / Ivy
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2011 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.unmarshaller;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;
import java.util.StringTokenizer;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBException;
import javax.xml.bind.UnmarshalException;
import javax.xml.bind.ValidationEvent;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import com.sun.xml.bind.TypeRegistry;
import com.sun.xml.bind.util.AttributesImpl;
/**
* Implementation of {@link UnmarshallerHandler}.
*
* This object converts SAX events into unmarshaller events and
* cooridnates the entire unmarshalling process.
*
* @author
* =0; i-=2 ) {
if(prefix.equals(nsBind[i]))
return nsBind[i+1];
}
return null;
}
//
// NamespaceContext2 implementation
//
public Iterator getPrefixes(String uri) {
// TODO: could be implemented much faster
// wrap it into unmodifiable list so that the remove method
// will throw UnsupportedOperationException.
return Collections.unmodifiableList(
getAllPrefixesInList(uri)).iterator();
}
private List getAllPrefixesInList(String uri) {
List a = new ArrayList();
if( uri.equals(XMLConstants.XML_NS_URI) ) {
a.add(XMLConstants.XML_NS_PREFIX);
return a;
}
if( uri.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI) ) {
a.add(XMLConstants.XMLNS_ATTRIBUTE);
return a;
}
if( uri==null )
throw new IllegalArgumentException();
for( int i=nsLen-2; i>=0; i-=2 )
if(uri.equals(nsBind[i+1]))
if( getNamespaceURI(nsBind[i]).equals(nsBind[i+1]) )
// make sure that this prefix is still effective.
a.add(nsBind[i]);
return a;
}
public String getPrefix(String uri) {
if( uri.equals(XMLConstants.XML_NS_URI) )
return XMLConstants.XML_NS_PREFIX;
if( uri.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI) )
return XMLConstants.XMLNS_ATTRIBUTE;
if( uri==null )
throw new IllegalArgumentException();
for( int i=idxStack[idxStackTop]-2; i>=0; i-=2 )
if(uri.equals(nsBind[i+1]))
if( getNamespaceURI(nsBind[i]).equals(nsBind[i+1]) )
// make sure that this prefix is still effective.
return nsBind[i];
return null;
}
public String getNamespaceURI(String prefix) {
if( prefix.equals(XMLConstants.XMLNS_ATTRIBUTE) )
return XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
if( prefix==null )
throw new IllegalArgumentException();
return resolveNamespacePrefix(prefix);
}
//
//
// Attribute handling
//
//
// TODO: implementation can be more efficient
private final Stack attStack = new Stack();
public void pushAttributes( Attributes atts ) {
// since Attributes object is mutable, it is criticall important
// to make a copy.
// also symbolize attribute names
AttributesImpl a = new AttributesImpl();
for( int i=0; isome value is a valid fragment, however
// we need a look ahead to correctly handle this case.
// (because when we process @xsi:nil, we don't know what the value is,
// and by the time we read "false", we can't cancel this attribute anymore.)
//
// as a quick workaround, we remove @xsi:nil if the value is false.
int idx = a.getIndex("http://www.w3.org/2001/XMLSchema-instance","nil");
if(idx!=-1) {
String v = a.getValue(idx).trim();
if(v.equals("false") || v.equals("0"))
a.removeAttribute(idx);
}
attStack.push(a);
// start a new namespace scope
if( ++idxStackTop==idxStack.length ) {
// reallocation
int[] newBuf = new int[idxStack.length*2];
System.arraycopy(idxStack,0,newBuf,0,idxStack.length);
idxStack = newBuf;
}
idxStack[idxStackTop] = nsLen;
}
public void popAttributes() {
attStack.pop();
idxStackTop--;
}
public Attributes getUnconsumedAttributes() {
return (Attributes)attStack.peek();
}
public int getAttribute( String uri, String local ) {
// Consider a class that corresponds to the root element.
// if this class has a transition from final state by an attribute,
// then this attribute transitions are checked when the final
// leaveElement event is consumed.
//
// to handle this case, return "not found" if there is no active
// attribute scope
if(attStack.isEmpty()) return -1;
Attributes a = (Attributes)attStack.peek();
return a.getIndex(uri,local);
}
public void consumeAttribute( int idx ) throws UnreportedException {
AttributesImpl a = (AttributesImpl)attStack.peek();
String uri = a.getURI(idx).intern();
String local = a.getLocalName(idx).intern();
String value = a.getValue(idx).intern();
// mark the attribute as consumed
// we need to remove the attribute before we process it
// because the event handler might access attributes.
a.removeAttribute(idx);
getCurrentHandler().enterAttribute(uri,local);
consumeText(value,false);
getCurrentHandler().leaveAttribute(uri,local);
}
//
//
// ID/IDREF related code
//
//
/**
* Submitted patchers in the order they've submitted.
* Many XML vocabulary doesn't use ID/IDREF at all, so we
* initialize it with null.
*/
private Runnable[] patchers = null;
private int patchersLen = 0;
public void addPatcher( Runnable job ) {
// re-allocate buffer if necessary
if( patchers==null )
patchers = new Runnable[32];
if( patchers.length == patchersLen ) {
Runnable[] buf = new Runnable[patchersLen*2];
System.arraycopy(patchers,0,buf,0,patchersLen);
patchers = buf;
}
patchers[patchersLen++] = job;
}
/** Executes all the patchers. */
private void runPatchers() {
if( patchers!=null ) {
for( int i=0; iObject map. */
private Hashtable idmap = null;
public String addToIdTable( String id ) {
if(idmap==null) idmap = new Hashtable();
idmap.put( id, getCurrentHandler().owner() );
return id;
}
public UnmarshallableObject getObjectFromId( String id ) {
if(idmap==null) return null;
return (UnmarshallableObject)idmap.get(id);
}
//
//
// Other SAX callbacks
//
//
public void skippedEntity( String name ) {
// TODO: throw an exception, perhaps?
}
public void processingInstruction( String target, String data ) {
// just ignore
}
public void setDocumentLocator( Locator loc ) {
locator = loc;
}
public Locator getLocator() { return locator; }
private Locator locator;
//
//
// error handling
//
//
private final UnmarshallerImpl parent;
private boolean aborted = false;
public boolean handleEvent(ValidationEvent event) {
try {
// if the handler says "abort", we will not return
// the object.
boolean recover = parent.getEventHandler().handleEvent(event);
if(!recover) aborted = true;
return recover;
} catch( JAXBException e ) {
// we are not allowed to throw an exception from this method.
return false;
} catch( RuntimeException re ) {
// if client event handler causes a runtime exception, then we
// have to return false.
return false;
}
}
public void reportAndThrow( UnreportedException e ) throws SAXException {
handleEvent(e.createValidationEvent());
// rewrap it into UnmarshalException.
// we further re-wrap it into SAXException again so that
// it can be tunneled through SAX Parser.
throw new SAXException( e.createUnmarshalException() );
}
//
//
// ValidationContext implementation
//
//
public String getBaseUri() { return null; }
public boolean isUnparsedEntity(String s) { return true; }
public boolean isNotation(String s) { return true; }
//
//
// debug trace methods
//
//
private Tracer tracer;
public void setTracer( Tracer t ) {
this.tracer = t;
}
public Tracer getTracer() {
if(tracer==null)
tracer = new Tracer.Standard();
return tracer;
}
}