| /* Copyright 2004 The Apache Software Foundation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.xmlbeans.impl.newstore2; |
| |
| import org.xml.sax.Locator; |
| import org.xml.sax.Attributes; |
| import org.xml.sax.ContentHandler; |
| import org.xml.sax.EntityResolver; |
| import org.xml.sax.ErrorHandler; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.ext.LexicalHandler; |
| import org.xml.sax.SAXParseException; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.XMLReader; |
| import org.xml.sax.SAXException; |
| |
| import java.util.HashMap; |
| |
| import java.lang.ref.ReferenceQueue; |
| import java.lang.ref.Reference; |
| import java.lang.ref.PhantomReference; |
| |
| import java.lang.reflect.Method; |
| |
| import javax.xml.parsers.SAXParserFactory; |
| |
| import java.io.InputStream; |
| import java.io.Reader; |
| import java.io.StringReader; |
| import java.io.IOException; |
| |
| import javax.xml.stream.XMLStreamReader; |
| |
| import org.apache.xmlbeans.xml.stream.XMLInputStream; |
| import org.apache.xmlbeans.xml.stream.XMLStreamException; |
| |
| import org.w3c.dom.DOMImplementation; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.DocumentType; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.Element; |
| |
| import javax.xml.namespace.QName; |
| |
| import org.apache.xmlbeans.impl.common.QNameHelper; |
| import org.apache.xmlbeans.impl.common.XmlLocale; |
| import org.apache.xmlbeans.impl.common.ResolverUtil; |
| |
| import org.apache.xmlbeans.impl.newstore2.Saaj.SaajCallback; |
| |
| import org.apache.xmlbeans.impl.newstore2.DomImpl.Dom; |
| import org.apache.xmlbeans.impl.newstore2.DomImpl.TextNode; |
| import org.apache.xmlbeans.impl.newstore2.DomImpl.CdataNode; |
| import org.apache.xmlbeans.impl.newstore2.DomImpl.SaajTextNode; |
| import org.apache.xmlbeans.impl.newstore2.DomImpl.SaajCdataNode; |
| |
| import org.apache.xmlbeans.impl.newstore2.Cur.Locations; |
| |
| import org.apache.xmlbeans.XmlBeans; |
| import org.apache.xmlbeans.XmlSaxHandler; |
| import org.apache.xmlbeans.XmlException; |
| import org.apache.xmlbeans.XmlObject; |
| import org.apache.xmlbeans.XmlOptions; |
| import org.apache.xmlbeans.SchemaType; |
| import org.apache.xmlbeans.SchemaTypeLoader; |
| import org.apache.xmlbeans.XmlTokenSource; |
| import org.apache.xmlbeans.XmlOptions; |
| import org.apache.xmlbeans.QNameSet; |
| import org.apache.xmlbeans.QNameCache; |
| import org.apache.xmlbeans.XmlBeans; |
| import org.apache.xmlbeans.XmlError; |
| import org.apache.xmlbeans.XmlRuntimeException; |
| import org.apache.xmlbeans.XmlDocumentProperties; |
| |
| import javax.xml.namespace.QName; |
| |
| import org.apache.xmlbeans.impl.values.TypeStore; |
| import org.apache.xmlbeans.impl.values.TypeStoreUser; |
| import org.apache.xmlbeans.impl.values.TypeStoreUserFactory; |
| |
| public final class Locale implements DOMImplementation, SaajCallback, XmlLocale |
| { |
| static final int ROOT = Cur.ROOT; |
| static final int ELEM = Cur.ELEM; |
| static final int ATTR = Cur.ATTR; |
| static final int COMMENT = Cur.COMMENT; |
| static final int PROCINST = Cur.PROCINST; |
| static final int TEXT = Cur.TEXT; |
| |
| static final int WS_UNSPECIFIED = TypeStore.WS_UNSPECIFIED; |
| static final int WS_PRESERVE = TypeStore.WS_PRESERVE; |
| static final int WS_REPLACE = TypeStore.WS_REPLACE; |
| static final int WS_COLLAPSE = TypeStore.WS_COLLAPSE; |
| |
| static final String _xsi = "http://www.w3.org/2001/XMLSchema-instance"; |
| static final String _schema = "http://www.w3.org/2001/XMLSchema"; |
| static final String _openFragUri = "http://www.openuri.org/fragment"; |
| static final String _xml1998Uri = "http://www.w3.org/XML/1998/namespace"; |
| static final String _xmlnsUri = "http://www.w3.org/2000/xmlns/"; |
| |
| static final QName _xsiNil = new QName( _xsi, "nil", "xsi" ); |
| static final QName _xsiType = new QName( _xsi, "type", "xsi" ); |
| static final QName _xsiLoc = new QName( _xsi, "schemaLocation", "xsi" ); |
| static final QName _xsiNoLoc = new QName( _xsi, "noNamespaceSchemaLocation", "xsi" ); |
| static final QName _openuriFragment = new QName( _openFragUri, "fragment", "frag" ); |
| static final QName _xmlFragment = new QName( "xml-fragment" ); |
| |
| private Locale ( SchemaTypeLoader stl, XmlOptions options ) |
| { |
| options = XmlOptions.maskNull( options ); |
| |
| // |
| // |
| // |
| |
| // TODO - add option for no=sync, or make it all thread safe |
| // |
| // Also - have a thread local setting for thread safety? .. Perhaps something |
| // in the type loader which defines whether ot not sync is on???? |
| |
| _noSync = true; |
| |
| _tempFrames = new Cur [ _numTempFramesLeft = 8 ]; |
| |
| // BUGBUG - this cannot be thread locale .... |
| // BUGBUG - this cannot be thread locale .... |
| // BUGBUG - this cannot be thread locale .... |
| // |
| // Lazy create this (loading up a locale should use the thread locale one) |
| // same goes for the qname factory .. use thread local for hte most part when loading |
| |
| _charUtil = CharUtil.getThreadLocalCharUtil(); |
| |
| _qnameFactory = new DefaultQNameFactory(); |
| |
| _locations = new Locations(); |
| |
| _schemaTypeLoader = stl; |
| |
| _validateOnSet = options.hasOption( XmlOptions.VALIDATE_ON_SET ); |
| |
| // |
| // Check for Saaj implementation request |
| // |
| |
| Object saajObj = options.get( Public2.SAAJ_IMPL ); |
| |
| if (saajObj != null) |
| { |
| if (!(saajObj instanceof Saaj)) |
| throw new IllegalStateException( "Saaj impl not correct type: " + saajObj ); |
| |
| _saaj = (Saaj) saajObj; |
| |
| _saaj.setCallback( this ); |
| } |
| } |
| |
| // |
| // |
| // |
| |
| public static final String USE_SAME_LOCALE = "USE_SAME_LOCALE"; |
| |
| static Locale getLocale ( SchemaTypeLoader stl, XmlOptions options ) |
| { |
| if (stl == null) |
| stl = XmlBeans.getContextTypeLoader(); |
| |
| options = XmlOptions.maskNull( options ); |
| |
| Locale l = null; |
| |
| if (options.hasOption( USE_SAME_LOCALE )) |
| { |
| Object source = options.get( USE_SAME_LOCALE ); |
| |
| if (source instanceof Locale) |
| l = (Locale) source; |
| else if (source instanceof XmlTokenSource) |
| l = (Locale) ((XmlTokenSource) source).monitor(); |
| else |
| throw new IllegalArgumentException( "Source locale not understood: " + source ); |
| |
| if (l._schemaTypeLoader != stl) |
| throw new IllegalArgumentException( "Source locale does not support same schema type loader" ); |
| |
| if (l._saaj != null && l._saaj != options.get( Public2.SAAJ_IMPL )) |
| throw new IllegalArgumentException( "Source locale does not support same saaj" ); |
| |
| if (l._validateOnSet && !options.hasOption( XmlOptions.VALIDATE_ON_SET )) |
| throw new IllegalArgumentException( "Source locale does not support same validate on set" ); |
| |
| // TODO - other things to check? |
| } |
| else |
| l = new Locale( stl, options ); |
| |
| return l; |
| } |
| |
| // |
| // |
| // |
| |
| private void autoTypeDocument ( Cur c, SchemaType requestedType, XmlOptions options ) |
| throws XmlException |
| { |
| assert c.isRoot(); |
| |
| // The type in the options overrides all sniffing |
| |
| options = XmlOptions.maskNull( options ); |
| |
| SchemaType optionType = (SchemaType) options.get( XmlOptions.DOCUMENT_TYPE ); |
| |
| if (optionType != null) |
| { |
| c.setType( optionType ); |
| return; |
| } |
| |
| SchemaType type = null; |
| |
| // An xsi:type can be used to pick a type out of the loader, or used to refine |
| // a type with a name. |
| |
| if (requestedType == null || requestedType.getName() != null) |
| { |
| QName xsiTypeName = c.getXsiTypeName(); |
| |
| SchemaType xsiSchemaType = |
| xsiTypeName == null ? null : _schemaTypeLoader.findType( xsiTypeName ); |
| |
| if (requestedType == null || requestedType.isAssignableFrom( xsiSchemaType )) |
| type = xsiSchemaType; |
| } |
| |
| // Look for a document element to establish type |
| |
| if (type == null && (requestedType == null || requestedType.isDocumentType())) |
| { |
| assert c.isRoot(); |
| |
| c.push(); |
| |
| QName docElemName = |
| !c.hasAttrs() && Locale.toFirstChildElement( c ) && |
| !Locale.toNextSiblingElement( c ) |
| ? c.getName() : null; |
| |
| c.pop(); |
| |
| if (docElemName != null) |
| { |
| type = _schemaTypeLoader.findDocumentType( docElemName ); |
| |
| if (type != null && requestedType != null) |
| { |
| QName requesteddocElemNameName = requestedType.getDocumentElementName(); |
| |
| if (!requesteddocElemNameName.equals( docElemName ) && |
| !requestedType.isValidSubstitution( docElemName )) |
| { |
| throw |
| new XmlException( |
| "Element " + QNameHelper.pretty( docElemName ) + |
| " is not a valid " + QNameHelper.pretty( requesteddocElemNameName ) + |
| " document or a valid substitution."); |
| } |
| } |
| } |
| } |
| |
| if (type == null && requestedType == null) |
| { |
| c.push(); |
| |
| type = |
| Locale.toFirstNormalAttr( c ) && !Locale.toNextNormalAttr( c ) |
| ? _schemaTypeLoader.findAttributeType( c.getName() ) : null; |
| |
| c.pop(); |
| } |
| |
| if (type == null) |
| type = requestedType; |
| |
| if (type == null) |
| type = XmlBeans.NO_TYPE; |
| |
| c.setType( type ); |
| |
| if (requestedType != null) |
| { |
| if (type.isDocumentType()) |
| verifyDocumentType( c, type.getDocumentElementName() ); |
| else if (type.isAttributeType()) |
| verifyAttributeType( c, type.getAttributeTypeAttributeName() ); |
| } |
| } |
| |
| private boolean namespacesSame ( QName n1, QName n2 ) |
| { |
| if (n1 == n2) |
| return true; |
| |
| if (n1 == null || n2 == null) |
| return false; |
| |
| if (n1.getNamespaceURI() == n2.getNamespaceURI()) |
| return true; |
| |
| if (n1.getNamespaceURI() == null || n2.getNamespaceURI() == null) |
| return false; |
| |
| return n1.getNamespaceURI().equals( n2.getNamespaceURI() ); |
| } |
| |
| private void addNamespace ( StringBuffer sb, QName name ) |
| { |
| if (name.getNamespaceURI() == null) |
| sb.append( "<no namespace>" ); |
| else |
| { |
| sb.append( "\"" ); |
| sb.append( name.getNamespaceURI() ); |
| sb.append( "\"" ); |
| } |
| } |
| |
| private void verifyDocumentType ( Cur c, QName docElemName ) throws XmlException |
| { |
| assert c.isRoot(); |
| |
| c.push(); |
| |
| try |
| { |
| StringBuffer sb = null; |
| |
| if (!Locale.toFirstChildElement( c ) || Locale.toNextSiblingElement( c )) |
| { |
| sb = new StringBuffer(); |
| |
| sb.append( "The document is not a " ); |
| sb.append( QNameHelper.pretty( docElemName ) ); |
| sb.append( c.isRoot() ? ": no document element" : ": multiple document elements" ); |
| } |
| else |
| { |
| QName name = c.getName(); |
| |
| if (!name.equals( docElemName )) |
| { |
| sb = new StringBuffer(); |
| |
| sb.append( "The document is not a " ); |
| sb.append( QNameHelper.pretty( docElemName ) ); |
| |
| if (docElemName.getLocalPart().equals( name.getLocalPart() )) |
| { |
| sb.append( ": document element namespace mismatch " ); |
| sb.append( "expected " ); |
| addNamespace( sb, docElemName ); |
| sb.append( " got " ); |
| addNamespace(sb, name ); |
| } |
| else if (namespacesSame( docElemName, name )) |
| { |
| sb.append( ": document element local name mismatch " ); |
| sb.append( "expected " + docElemName.getLocalPart() ); |
| sb.append( " got " + name.getLocalPart() ); |
| } |
| else |
| { |
| sb.append( ": document element mismatch " ); |
| sb.append( "got " ); |
| sb.append( QNameHelper.pretty( name ) ); |
| } |
| } |
| } |
| |
| if (sb != null) |
| { |
| XmlError err = XmlError.forCursor( sb.toString(), new Cursor( c ) ); |
| throw new XmlException( err.toString(), null, err ); |
| } |
| } |
| finally |
| { |
| c.pop(); |
| } |
| } |
| |
| private void verifyAttributeType ( Cur c, QName attrName ) throws XmlException |
| { |
| assert c.isRoot(); |
| |
| c.push(); |
| |
| try |
| { |
| StringBuffer sb = null; |
| |
| if (!Locale.toFirstNormalAttr( c ) || Locale.toNextNormalAttr( c )) |
| { |
| sb = new StringBuffer(); |
| |
| sb.append( "The document is not a " ); |
| sb.append( QNameHelper.pretty( attrName ) ); |
| sb.append( c.isRoot() ? ": no attributes" : ": multiple attributes" ); |
| } |
| else |
| { |
| QName name = c.getName(); |
| |
| if (!name.equals( attrName )) |
| { |
| sb = new StringBuffer(); |
| |
| sb.append( "The document is not a " ); |
| sb.append( QNameHelper.pretty( attrName ) ); |
| |
| if (attrName.getLocalPart().equals( name.getLocalPart() )) |
| { |
| sb.append( ": attribute namespace mismatch " ); |
| sb.append( "expected " ); |
| addNamespace( sb, attrName ); |
| sb.append( " got " ); |
| addNamespace(sb, name ); |
| } |
| else if (namespacesSame( attrName, name )) |
| { |
| sb.append( ": attribute local name mismatch " ); |
| sb.append( "expected " + attrName.getLocalPart() ); |
| sb.append( " got " + name.getLocalPart() ); |
| } |
| else |
| { |
| sb.append( ": attribute element mismatch " ); |
| sb.append( "got " ); |
| sb.append( QNameHelper.pretty( name ) ); |
| } |
| } |
| } |
| |
| if (sb != null) |
| { |
| XmlError err = XmlError.forCursor( sb.toString(), new Cursor( c ) ); |
| throw new XmlException( err.toString(), null, err ); |
| } |
| } |
| finally |
| { |
| c.pop(); |
| } |
| } |
| |
| // |
| // |
| // |
| |
| public static XmlObject newInstance ( |
| SchemaTypeLoader stl, SchemaType type, XmlOptions options ) |
| { |
| Locale l = getLocale( stl, options ); |
| |
| if (l.noSync()) { l.enter(); try { return l.newInstance( type, options ); } finally { l.exit(); } } |
| else synchronized ( l ) { l.enter(); try { return l.newInstance( type, options ); } finally { l.exit(); } } |
| } |
| |
| private XmlObject newInstance ( SchemaType type, XmlOptions options ) |
| { |
| options = XmlOptions.maskNull( options ); |
| |
| Cur c = tempCur(); |
| |
| c.createRoot(); |
| |
| SchemaType sType = (SchemaType) options.get( XmlOptions.DOCUMENT_TYPE ); |
| |
| if (sType == null) |
| sType = type == null ? XmlObject.type : type; |
| |
| c.setType( sType ); |
| |
| XmlObject x = (XmlObject) c.getUser(); |
| |
| c.release(); |
| |
| return x; |
| } |
| |
| // |
| // |
| // |
| |
| public static XmlObject parseToXmlObject ( |
| SchemaTypeLoader stl, String xmlText, SchemaType type, XmlOptions options ) |
| throws XmlException |
| { |
| Locale l = getLocale( stl, options ); |
| |
| if (l.noSync()) { l.enter(); try { return l.parseToXmlObject( xmlText, type, options ); } finally { l.exit(); } } |
| else synchronized ( l ) { l.enter(); try { return l.parseToXmlObject( xmlText, type, options ); } finally { l.exit(); } } |
| } |
| |
| private XmlObject parseToXmlObject ( String xmlText, SchemaType type, XmlOptions options ) |
| throws XmlException |
| { |
| Cur c = parse( xmlText, type, options ); |
| |
| XmlObject x = (XmlObject) c.getUser(); |
| |
| c.release(); |
| |
| return x; |
| } |
| |
| private Cur parse ( String xmlText, SchemaType type, XmlOptions options ) |
| throws XmlException |
| { |
| Cur c = |
| getSaxLoader( options ). |
| load( this, new InputSource( new StringReader( xmlText ) ), options ); |
| |
| autoTypeDocument( c, type, options ); |
| |
| return c; |
| } |
| |
| // |
| // |
| // |
| |
| public static XmlObject parseToXmlObject ( |
| SchemaTypeLoader stl, XMLInputStream xis, SchemaType type, XmlOptions options ) |
| throws XmlException, XMLStreamException |
| { |
| throw new RuntimeException( "Not impl" ); |
| // Root r = new Root( stl, null, options ); |
| // r.loadXml( xis, type, options ); |
| // return r.getObject(); |
| } |
| |
| public static XmlObject parseToXmlObject ( |
| SchemaTypeLoader stl, XMLStreamReader xsr, SchemaType type, XmlOptions options ) |
| throws XmlException |
| { |
| throw new RuntimeException( "Not impl" ); |
| // Root r = new Root( stl, null, options ); |
| // r.loadXml( xsr, type, options ); |
| // return r.getObject(); |
| } |
| |
| public static XmlObject parseToXmlObject ( |
| SchemaTypeLoader stl, InputStream is, SchemaType type, XmlOptions options ) |
| throws XmlException, IOException |
| { |
| throw new RuntimeException( "Not impl" ); |
| // Root r = new Root( stl, null, options ); |
| // r.loadXml( is, type, options ); |
| // return r.getObject(); |
| } |
| |
| public static XmlObject parseToXmlObject ( |
| SchemaTypeLoader stl, Reader reader, SchemaType type, XmlOptions options ) |
| throws XmlException, IOException |
| { |
| throw new RuntimeException( "Not impl" ); |
| // Root r = new Root( stl, null, options ); |
| // r.loadXml( reader, type, options ); |
| // return r.getObject(); |
| } |
| |
| public static XmlObject parseToXmlObject ( |
| SchemaTypeLoader stl, Node node, SchemaType type, XmlOptions options ) |
| throws XmlException |
| { |
| throw new RuntimeException( "Not impl" ); |
| // Root r = new Root( stl, null, options ); |
| // r.loadXml( node, type, options ); |
| // return r.getObject(); |
| } |
| |
| public static XmlSaxHandler newSaxHandler ( |
| SchemaTypeLoader stl, SchemaType type, XmlOptions options ) |
| { |
| throw new RuntimeException( "Not impl" ); |
| // return new Root( stl, null, options ).newSaxHandler( type, options ); |
| } |
| |
| // TODO (ericvas ) - have a qname factory here so that the same factory may be |
| // used by the parser. This factory would probably come from my |
| // high speed parser. Otherwise, use a thread local on |
| |
| QName makeQName ( String uri, String localPart ) |
| { |
| assert localPart != null && localPart.length() > 0; |
| // TODO - make sure name is a well formed name? |
| |
| return _qnameFactory.getQName( uri, localPart ); |
| } |
| |
| QName makeQName ( String uri, String local, String prefix ) |
| { |
| return _qnameFactory.getQName( uri, local, prefix == null ? "" : prefix ); |
| } |
| |
| QName makeQualifiedQName ( String uri, String qname ) |
| { |
| if (qname == null) |
| qname = ""; |
| |
| int i = qname.indexOf( ':' ); |
| |
| return i < 0 |
| ? _qnameFactory.getQName( uri, qname ) |
| : _qnameFactory.getQName( uri, qname.substring( i + 1 ), qname.substring( 0, i ) ); |
| } |
| |
| static private class DocProps extends XmlDocumentProperties |
| { |
| private HashMap _map = new HashMap(); |
| |
| public Object put ( Object key, Object value ) { return _map.put( key, value ); } |
| public Object get ( Object key ) { return _map.get( key ); } |
| public Object remove ( Object key ) { return _map.remove( key ); } |
| } |
| |
| static XmlDocumentProperties getDocProps ( Cur c, boolean ensure ) |
| { |
| c.push(); |
| |
| while ( c.toParent() ) |
| ; |
| |
| DocProps props = (DocProps) c.getBookmark( DocProps.class ); |
| |
| if (props == null) |
| c.setBookmark( DocProps.class, props = new DocProps() ); |
| |
| c.pop(); |
| |
| return props; |
| } |
| |
| void registerForTextChange ( Cur c ) |
| { |
| // The end of this list points to itself so that I can know if |
| // any cur is on the list by seeing if netx != null. |
| |
| assert c._nextTextChangeListener == null; |
| |
| if (_textChangeListeners == null) |
| _textChangeListeners = c._nextTextChangeListener = c; |
| else |
| { |
| c._nextTextChangeListener = _textChangeListeners; |
| _textChangeListeners = c; |
| } |
| } |
| |
| interface GeneralChangeListener |
| { |
| void notifyGeneralChange ( ); |
| |
| void setNextGeneralChangeListener ( GeneralChangeListener listener ); |
| |
| GeneralChangeListener getNextGeneralChangeListener ( ); |
| } |
| |
| void registerForGeneralChange ( GeneralChangeListener listener ) |
| { |
| if (listener.getNextGeneralChangeListener() == null) |
| { |
| if (_generalChangeListeners == null) |
| listener.setNextGeneralChangeListener( listener ); |
| else |
| listener.setNextGeneralChangeListener( _generalChangeListeners ); |
| |
| _generalChangeListeners = listener; |
| } |
| } |
| |
| void notifyGeneralChangeListeners ( ) |
| { |
| while ( _generalChangeListeners != null ) |
| { |
| _generalChangeListeners.notifyGeneralChange(); |
| |
| if (_generalChangeListeners.getNextGeneralChangeListener() == _generalChangeListeners) |
| _generalChangeListeners.setNextGeneralChangeListener( null ); |
| |
| GeneralChangeListener next = _generalChangeListeners.getNextGeneralChangeListener(); |
| |
| _generalChangeListeners.setNextGeneralChangeListener( null ); |
| |
| _generalChangeListeners = next; |
| } |
| } |
| |
| void notifyTextChangeListeners ( ) |
| { |
| while ( _textChangeListeners != null ) |
| { |
| _textChangeListeners.textChangeNotification(); |
| |
| if (_textChangeListeners._nextTextChangeListener == _textChangeListeners) |
| _textChangeListeners._nextTextChangeListener = null; |
| |
| _textChangeListeners = _textChangeListeners._nextTextChangeListener; |
| } |
| } |
| |
| // |
| // Cursor helpers |
| // |
| |
| static String getTextValue ( Cur c, int wsr ) |
| { |
| assert c.isNode(); |
| |
| if (!c.hasChildren()) |
| return c.getValueAsString( wsr ); |
| |
| ScrubBuffer sb = getScrubBuffer( wsr ); |
| |
| c.push(); |
| |
| for ( c.next() ; !c.isAtEndOfLastPush() ; c.next() ) |
| if (c.isText()) |
| sb.scrub( c.getChars( -1 ), c._offSrc, c._cchSrc ); |
| |
| c.pop(); |
| |
| return sb.getResultAsString(); |
| } |
| |
| static String applyWhiteSpaceRule ( String s, int wsr ) |
| { |
| int l = s.length(); |
| |
| if (l == 0) |
| return s; |
| |
| char ch; |
| |
| if (wsr == Locale.WS_REPLACE) |
| { |
| for ( int i = 0 ; i < l ; i++ ) |
| if ((ch = s.charAt( i )) == '\n' || ch == '\r' || ch == '\t') |
| return processWhiteSpaceRule( s, wsr ); |
| } |
| else if (wsr == Locale.WS_COLLAPSE) |
| { |
| if (CharUtil.isWhiteSpace( s.charAt( 0 ) ) || CharUtil.isWhiteSpace( s.charAt( l - 1 ))) |
| return processWhiteSpaceRule( s, wsr ); |
| |
| boolean lastWasWhite = false; |
| |
| for ( int i = 1 ; i < l ; i++ ) |
| { |
| boolean isWhite = CharUtil.isWhiteSpace( s.charAt( i ) ); |
| |
| if (isWhite && lastWasWhite) |
| return processWhiteSpaceRule( s, wsr ); |
| |
| lastWasWhite = isWhite; |
| } |
| } |
| |
| return s; |
| } |
| |
| static String processWhiteSpaceRule ( String s, int wsr ) |
| { |
| ScrubBuffer sb = getScrubBuffer( wsr ); |
| |
| sb.scrub( s, 0, s.length() ); |
| |
| return sb.getResultAsString(); |
| } |
| |
| private static final class ScrubBuffer |
| { |
| void init ( int wsr ) |
| { |
| assert wsr == Locale.WS_REPLACE || wsr == Locale.WS_COLLAPSE; |
| |
| _dstOff = 0; |
| _replace = wsr == Locale.WS_REPLACE; |
| } |
| |
| void scrub ( Object src, int off, int cch ) |
| { |
| char[] chars; |
| |
| if (cch == 0) |
| return; |
| |
| if (src instanceof char[]) |
| chars = (char[]) src; |
| else if (cch < _srcBuf.length) |
| chars = _srcBuf; |
| else if (cch < 16384) |
| chars = _srcBuf = new char [ 16384 ]; |
| else |
| chars = new char [ cch ]; |
| |
| if (src != chars) |
| { |
| CharUtil.getChars( chars, 0, src, off, cch ); |
| off = 0; |
| } |
| |
| char ch; |
| |
| while ( cch > 0 && CharUtil.isWhiteSpace( chars[ off ] ) ) |
| { off++; cch--; } |
| |
| while ( cch > 0 && CharUtil.isWhiteSpace( chars[ off + cch - 1 ] ) ) |
| cch--; |
| |
| boolean lastWasWhite = _dstOff > 0 && CharUtil.isWhiteSpace( _dstBuf[ _dstOff ] ); |
| |
| while ( cch-- > 0 ) |
| { |
| ch = chars[ off++ ]; |
| |
| if (CharUtil.isWhiteSpace( ch )) |
| { |
| if (_replace || !lastWasWhite) |
| _dstBuf[ _dstOff++ ] = ' '; |
| |
| lastWasWhite = true; |
| } |
| else |
| { |
| _dstBuf[ _dstOff++ ] = ch; |
| lastWasWhite = false; |
| } |
| } |
| } |
| |
| String getResultAsString ( ) |
| { |
| return new String( _dstBuf, 0, _dstOff ); |
| } |
| |
| private static final int START_STATE = 0; |
| private static final int SPACE_SEEN_STATE = 1; |
| private static final int NOSPACE_STATE = 2; |
| |
| private boolean _replace; |
| |
| private char[] _srcBuf = new char [ 1024 ]; |
| private char[] _dstBuf = new char [ 1024 ]; |
| private int _dstOff; |
| } |
| |
| private static ThreadLocal tl_scrubBuffer = |
| new ThreadLocal ( ) { protected Object initialValue ( ) { return new ScrubBuffer(); } }; |
| |
| static ScrubBuffer getScrubBuffer ( int wsr ) |
| { |
| ScrubBuffer sb = (ScrubBuffer) tl_scrubBuffer.get(); |
| sb.init( wsr ); |
| return sb; |
| } |
| |
| static final int scrubText( |
| Object src, int off, int cch, int wsRule, StringBuffer sb, int state ) |
| { |
| char[] chars = cch < 1024 ? (char[]) tl_scrubBuffer.get() : new char [ cch ]; |
| |
| if (chars.length > 1024 && cch < 16384) |
| tl_scrubBuffer.set( chars ); |
| |
| CharUtil.getChars( chars, 0, src, off, cch ); |
| |
| |
| |
| |
| throw new RuntimeException( "Not impl" ); |
| |
| // assert text != null; |
| // |
| // if (text._buf == null) |
| // { |
| // assert cch == 0; |
| // assert cp == 0; |
| // return state; |
| // } |
| // |
| // if (cch == 0) |
| // return state; |
| // |
| // boolean replace = false; |
| // boolean collapse = false; |
| // |
| // switch ( ws ) |
| // { |
| // case TypeStore.WS_UNSPECIFIED : break; |
| // case TypeStore.WS_PRESERVE : break; |
| // case TypeStore.WS_REPLACE : replace = true; break; |
| // case TypeStore.WS_COLLAPSE : collapse = replace = true; break; |
| // |
| // default : assert false: "Unknown white space rule " +ws; |
| // } |
| // |
| // if (!replace && !collapse) |
| // { |
| // text.fetch(sb, cp, cch); |
| // return state; |
| // } |
| // |
| // int off = text.unObscure( cp, cch ); |
| // int startpt = 0; |
| // |
| // for ( int i = 0 ; i < cch ; i++ ) |
| // { |
| // char ch = text._buf[ off + i ]; |
| // |
| // if (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t') |
| // { |
| // sb.append(text._buf, off + startpt, i - startpt); |
| // startpt = i + 1; |
| // |
| // if (collapse) |
| // { |
| // if (state == NOSPACE_STATE) |
| // state = SPACE_SEEN_STATE; |
| // } |
| // else |
| // sb.append(' '); |
| // } |
| // else |
| // { |
| // if (state == SPACE_SEEN_STATE) |
| // sb.append( ' ' ); |
| // |
| // state = NOSPACE_STATE; |
| // } |
| // } |
| // |
| // sb.append( text._buf, off + startpt, cch - startpt ); |
| // |
| // return state; |
| } |
| |
| static boolean pushToContainer ( Cur c ) |
| { |
| c.push(); |
| |
| for ( ; ; ) |
| { |
| switch ( c.kind() ) |
| { |
| case ROOT : case ELEM : return true; |
| case - ROOT : case - ELEM : c.pop(); return false; |
| case COMMENT : case PROCINST : c.skip(); break; |
| default : c.nextWithAttrs(); break; |
| } |
| } |
| } |
| |
| static boolean toFirstNormalAttr ( Cur c ) |
| { |
| c.push(); |
| |
| if (c.toFirstAttr()) |
| { |
| do |
| { |
| if (!c.isXmlns()) |
| { |
| c.popButStay(); |
| return true; |
| } |
| } |
| while ( c.toNextAttr() ); |
| } |
| |
| c.pop(); |
| |
| return false; |
| } |
| |
| static boolean toNextNormalAttr ( Cur c ) |
| { |
| c.push(); |
| |
| while ( c.toNextAttr() ) |
| { |
| if (!c.isXmlns()) |
| { |
| c.popButStay(); |
| return true; |
| } |
| } |
| |
| c.pop(); |
| |
| return false; |
| } |
| |
| static boolean toFirstChildElement ( Cur c ) |
| { |
| if (!pushToContainer( c )) |
| return false; |
| |
| if (!c.toFirstChild() || (!c.isElem() && !toNextSiblingElement( c ))) |
| { |
| c.pop(); |
| return false; |
| } |
| |
| c.popButStay(); |
| |
| return true; |
| } |
| |
| static boolean toNextSiblingElement ( Cur c ) |
| { |
| if (!c.hasParent()) |
| return false; |
| |
| c.push(); |
| |
| int k = c.kind(); |
| |
| if (k == ATTR) |
| c.toParent(); |
| else if (k == ELEM) |
| c.skip(); |
| |
| while ( (k = c.kind()) > 0 ) |
| { |
| if (k == ELEM) |
| { |
| c.popButStay(); |
| return true; |
| } |
| |
| if (k > 0) |
| c.toEnd(); |
| |
| c.next(); |
| } |
| |
| c.pop(); |
| |
| return false; |
| } |
| |
| static boolean toChild ( Cur c, String uri, String local, int i ) |
| { |
| return toChild( c, c._locale.makeQName( uri, local ), i ); |
| } |
| |
| static boolean toChild ( Cur c, QName name, int i ) |
| { |
| // if (!c.pushToContainer()) |
| // return false; |
| // |
| throw new RuntimeException( "Not implemented" ); |
| // c.pop.... |
| } |
| |
| // private final class NthChildCache |
| // { |
| // private boolean namesSame ( QName pattern, QName name ) |
| // { |
| // return pattern == null || pattern.equals( name ); |
| // } |
| // |
| // private boolean setsSame ( QNameSet patternSet, QNameSet set) |
| // { |
| // // value equality is probably too expensive. Since the use case |
| // // involves QNameSets that are generated by the compiler, we |
| // // can use identity comparison. |
| // return patternSet != null && patternSet == set; |
| // } |
| // |
| // private boolean nameHit(QName namePattern, QNameSet setPattern, QName name) |
| // { |
| // if (setPattern == null) |
| // return namesSame(namePattern, name); |
| // else |
| // return setPattern.contains(name); |
| // } |
| // |
| // private boolean cacheSame (QName namePattern, QNameSet setPattern) |
| // { |
| // return setPattern == null ? namesSame(namePattern, _name) : |
| // setsSame(setPattern, _set); |
| // } |
| // |
| // int distance ( Splay parent, QName name, QNameSet set, int n ) |
| // { |
| // assert n >= 0; |
| // |
| // if (_version != Root.this.getVersion()) |
| // return Integer.MAX_VALUE - 1; |
| // |
| // if (parent != _parent || !cacheSame(name, set)) |
| // return Integer.MAX_VALUE; |
| // |
| // return n > _n ? n - _n : _n - n; |
| // } |
| // |
| // Begin fetch ( Splay parent, QName name, QNameSet set, int n ) |
| // { |
| // assert n >= 0; |
| // |
| // if (_version != Root.this.getVersion() || _parent != parent || |
| // ! cacheSame(name, set) || n == 0) |
| // { |
| // _version = Root.this.getVersion(); |
| // _parent = parent; |
| // _name = name; |
| // _child = null; |
| // _n = -1; |
| // |
| // if (!parent.isLeaf()) |
| // { |
| // loop: |
| // for ( Splay s = parent.nextSplay() ; ; s = s.nextSplay() ) |
| // { |
| // switch ( s.getKind() ) |
| // { |
| // case END : |
| // case ROOT : break loop; |
| // |
| // case BEGIN : |
| // if (nameHit( name, set, s.getName() )) |
| // { |
| // _child = s; |
| // _n = 0; |
| // break loop; |
| // } |
| // |
| // s = s.getFinishSplay(); |
| // break; |
| // } |
| // } |
| // } |
| // } |
| // |
| // if (_n < 0) |
| // return null; |
| // |
| // if (n > _n) |
| // { |
| // while ( n > _n ) |
| // { |
| // for ( Splay s = _child.getFinishSplay().nextSplay() ; ; |
| // s = s.nextSplay() ) |
| // { |
| // if (s.isFinish()) |
| // return null; |
| // |
| // if (s.isBegin()) |
| // { |
| // if (nameHit( name, set, s.getName() )) |
| // { |
| // _child = s; |
| // _n++; |
| // break; |
| // } |
| // |
| // s = s.getFinishSplay(); |
| // } |
| // } |
| // } |
| // } |
| // else if (n < _n) |
| // { |
| // while ( n < _n ) |
| // { |
| // Splay s = _child; |
| // |
| // for ( ; ; ) |
| // { |
| // s = s.prevSplay(); |
| // |
| // if (s.isLeaf() || s.isEnd()) |
| // { |
| // if (s.isEnd()) |
| // s = s.getContainer(); |
| // |
| // if (nameHit( name, set, s.getName() )) |
| // { |
| // _child = s; |
| // _n--; |
| // break; |
| // } |
| // } |
| // else if (s.isContainer()) |
| // return null; |
| // } |
| // } |
| // } |
| // |
| // return (Begin) _child; |
| // } |
| // |
| // private long _version; |
| // private Splay _parent; |
| // private QName _name; |
| // private QNameSet _set; |
| // |
| // private Splay _child; |
| // private int _n; |
| // } |
| |
| // |
| // |
| // |
| |
| long version ( ) |
| { |
| return _versionAll; |
| } |
| |
| Cur permCur ( ) |
| { |
| return getCur( Cur.PERM ); |
| } |
| |
| Cur weakCur ( Object o ) |
| { |
| assert o != null && !(o instanceof Ref); |
| |
| Cur c = getCur( Cur.WEAK ); |
| |
| assert c._value == null; |
| |
| c._value = new Ref( c, o ); |
| |
| return c; |
| } |
| |
| final ReferenceQueue refQueue ( ) |
| { |
| if (_refQueue == null) |
| _refQueue = new ReferenceQueue(); |
| |
| return _refQueue; |
| } |
| |
| final static class Ref extends PhantomReference |
| { |
| Ref ( Cur c, Object obj ) |
| { |
| super( obj, c._locale.refQueue() ); |
| |
| _cur = c; |
| } |
| |
| final Cur _cur; |
| } |
| |
| Cur tempCur ( ) |
| { |
| Cur c = getCur( Cur.TEMP ); |
| |
| if (c._tempFrame < 0) |
| { |
| assert _numTempFramesLeft < _tempFrames.length; |
| |
| int frame = _tempFrames.length - _numTempFramesLeft - 1; |
| |
| assert frame >= 0 && frame < _tempFrames.length; |
| |
| c._nextTemp = _tempFrames[ frame ]; |
| _tempFrames[ frame ] = c; |
| |
| c._tempFrame = frame; |
| } |
| |
| return c; |
| } |
| |
| void unregisterCurs ( ) |
| { |
| while ( _registered != null ) |
| _registered.embed(); |
| |
| assert _registered == null; |
| } |
| |
| private Cur getCur ( int curKind ) |
| { |
| assert curKind == Cur.TEMP || curKind == Cur.PERM || curKind == Cur.WEAK; |
| assert _curPool == null || _curPoolCount > 0; |
| |
| Cur c; |
| |
| if (_curPool == null) |
| { |
| c = new Cur( this ); |
| c._tempFrame = -1; |
| } |
| else |
| { |
| c = _curPool; |
| _curPool = c.listRemove( _curPool ); |
| c._state = Cur.UNREGISTERED; |
| _curPoolCount--; |
| } |
| |
| assert c._state == Cur.UNREGISTERED; |
| assert c._prev == null && c._next == null; |
| assert !c.isPositioned(); |
| assert c._value == null; |
| |
| c._curKind = curKind; |
| |
| return c; |
| } |
| |
| TextNode createTextNode ( ) |
| { |
| return _saaj == null ? new TextNode( this ) : new SaajTextNode( this ); |
| } |
| |
| CdataNode createCdataNode ( ) |
| { |
| return _saaj == null ? new CdataNode( this ) : new SaajCdataNode( this ); |
| } |
| |
| boolean entered ( ) |
| { |
| return _tempFrames.length - _numTempFramesLeft > 0; |
| } |
| |
| public void enter ( Locale otherLocale ) |
| { |
| enter(); |
| |
| if (otherLocale != this) |
| otherLocale.enter(); |
| } |
| |
| public void enter ( ) |
| { |
| assert _numTempFramesLeft >= 0; |
| |
| if (--_numTempFramesLeft <= 0) |
| { |
| Cur[] newTempFrames = new Cur [ (_numTempFramesLeft = _tempFrames.length) * 2 ]; |
| System.arraycopy( _tempFrames, 0, newTempFrames, 0, _tempFrames.length ); |
| _tempFrames = newTempFrames; |
| } |
| |
| if (++_entryCount > 1000) |
| { |
| _entryCount = 0; |
| |
| if (_refQueue != null) |
| { |
| for ( ; ; ) |
| { |
| Ref ref = (Ref) _refQueue.poll(); |
| |
| if (ref == null) |
| break; |
| |
| ref._cur.release(); |
| } |
| } |
| } |
| } |
| |
| public void exit ( Locale otherLocale ) |
| { |
| exit(); |
| |
| if (otherLocale != this) |
| otherLocale.exit(); |
| } |
| |
| public void exit ( ) |
| { |
| assert _numTempFramesLeft >= 0; |
| |
| int frame = _tempFrames.length - ++_numTempFramesLeft; |
| |
| Cur c = _tempFrames [ frame ]; |
| |
| _tempFrames [ frame ] = null; |
| |
| while ( c != null ) |
| { |
| assert c._tempFrame == frame; |
| |
| Cur next = c._nextTemp; |
| |
| c._nextTemp = null; |
| c._tempFrame = -1; |
| |
| c.release(); |
| |
| c = next; |
| } |
| } |
| |
| // |
| // |
| // |
| |
| public boolean noSync ( ) |
| { |
| return _noSync; |
| } |
| |
| public boolean sync ( ) |
| { |
| return !_noSync; |
| } |
| |
| static final boolean isWhiteSpace ( String s ) |
| { |
| int l = s.length(); |
| |
| while ( l-- > 0) |
| if (!CharUtil.isWhiteSpace( s.charAt( l ))) |
| return false; |
| |
| return true; |
| } |
| |
| static final boolean isWhiteSpace ( StringBuffer sb ) |
| { |
| int l = sb.length(); |
| |
| while ( l-- > 0) |
| if (!CharUtil.isWhiteSpace( sb.charAt( l ))) |
| return false; |
| |
| return true; |
| } |
| |
| static boolean beginsWithXml ( String name ) |
| { |
| if (name.length() < 3) |
| return false; |
| |
| char ch; |
| |
| if (((ch = name.charAt( 0 )) == 'x' || ch == 'X') && |
| ((ch = name.charAt( 1 )) == 'm' || ch == 'M') && |
| ((ch = name.charAt( 2 )) == 'l' || ch == 'L')) |
| { |
| return true; |
| } |
| |
| return false; |
| } |
| |
| static boolean isXmlns ( QName name ) |
| { |
| String prefix = name.getPrefix(); |
| |
| if (prefix.equals( "xmlns" )) |
| return true; |
| |
| return prefix.length() == 0 && name.getLocalPart().equals( "xmlns" ); |
| } |
| |
| QName createXmlns ( String prefix ) |
| { |
| if (prefix == null) |
| prefix = ""; |
| |
| return |
| prefix.length() == 0 |
| ? makeQName( _xmlnsUri, "xmlns", "" ) |
| : makeQName( _xmlnsUri, prefix, "xmlns" ); |
| } |
| |
| static String xmlnsPrefix ( QName name ) |
| { |
| return name.getPrefix().equals( "xmlns" ) ? name.getLocalPart() : ""; |
| } |
| |
| // |
| // Loading/parsing |
| // |
| |
| static abstract class LoadContext |
| { |
| protected abstract void startElement ( QName name ); |
| protected abstract void endElement ( ); |
| |
| protected abstract void attr ( String local, String uri, String prefix, |
| String value ); |
| |
| protected abstract void comment ( char[] buff, int off, int cch ); |
| protected abstract void procInst ( String target, String value ); |
| protected abstract void text ( char[] buff, int off, int cch ); |
| protected abstract Cur finish ( ); |
| |
| } |
| |
| private static ThreadLocal tl_saxLoadersDefaultResolver = |
| new ThreadLocal ( ) { protected Object initialValue ( ) { return newSaxLoader(); } }; |
| |
| private static ThreadLocal tl_saxLoaders = |
| new ThreadLocal ( ) { protected Object initialValue ( ) { return newSaxLoader(); } }; |
| |
| private static SaxLoader getSaxLoader ( XmlOptions options ) |
| { |
| // XMLReader.setEntityResolver() cannot be passed null. |
| // Because of this, I cannot reset the entity resolver to be |
| // that which was default. Thus, I need to cache two |
| // SaxLoaders. One which uses the default entity resolver and |
| // one which I can change the resolve to whatever I want for a |
| // given parse. |
| |
| options = XmlOptions.maskNull( options ); |
| |
| EntityResolver er = (EntityResolver) options.get( XmlOptions.ENTITY_RESOLVER ); |
| |
| if (er == null) |
| er = ResolverUtil.getGlobalEntityResolver(); |
| |
| if (er == null && options.hasOption( XmlOptions.LOAD_USE_DEFAULT_RESOLVER )) |
| return (SaxLoader) tl_saxLoadersDefaultResolver.get(); |
| |
| SaxLoader sl = (SaxLoader) tl_saxLoaders.get(); |
| |
| if (er == null) |
| er = sl; |
| |
| sl.setEntityResolver( er ); |
| |
| return sl; |
| } |
| |
| private static SaxLoader newSaxLoader ( ) |
| { |
| SaxLoader sl = null; |
| |
| try |
| { |
| sl = PiccoloSaxLoader.newInstance(); |
| |
| if (sl == null) |
| sl = DefaultSaxLoader.newInstance(); |
| } |
| catch ( Exception e ) |
| { |
| throw new RuntimeException( "Can't find an XML parser", e ); |
| } |
| |
| if (sl == null) |
| throw new RuntimeException( "Can't find an XML parser" ); |
| |
| return sl; |
| } |
| |
| private static class DefaultSaxLoader extends SaxLoader |
| { |
| private DefaultSaxLoader ( XMLReader xr ) |
| { |
| super( xr, null ); |
| } |
| |
| static SaxLoader newInstance ( ) throws Exception |
| { |
| return |
| new DefaultSaxLoader( |
| SAXParserFactory.newInstance().newSAXParser().getXMLReader() ); |
| } |
| } |
| |
| private static class PiccoloSaxLoader extends SaxLoader |
| { |
| // TODO - Need to look at root.java to bring this loader up to |
| // date with all needed features |
| |
| private PiccoloSaxLoader ( |
| XMLReader xr, Locator startLocator, Method m_getEncoding, Method m_getVersion ) |
| { |
| super( xr, startLocator ); |
| |
| _m_getEncoding = m_getEncoding; |
| _m_getVersion = m_getVersion; |
| } |
| |
| static SaxLoader newInstance ( ) throws Exception |
| { |
| Class pc = null; |
| |
| try |
| { |
| pc = Class.forName( "com.bluecast.xml.Piccolo" ); |
| } |
| catch ( ClassNotFoundException e ) |
| { |
| return null; |
| } |
| |
| XMLReader xr = (XMLReader) pc.newInstance(); |
| |
| Method m_getEncoding = pc.getMethod( "getEncoding", null ); |
| Method m_getVersion = pc.getMethod( "getVersion", null ); |
| Method m_getStartLocator = pc.getMethod( "getStartLocator", null ); |
| |
| Locator startLocator = |
| (Locator) m_getStartLocator.invoke( xr, null ); |
| |
| return new PiccoloSaxLoader( xr, startLocator, m_getEncoding, m_getVersion ); |
| } |
| |
| private Method _m_getEncoding; |
| private Method _m_getVersion; |
| } |
| |
| private static abstract class SaxLoader |
| implements ContentHandler, LexicalHandler, ErrorHandler, EntityResolver |
| { |
| SaxLoader ( XMLReader xr, Locator startLocator ) |
| { |
| _xr = xr; |
| _startLocator = startLocator; |
| |
| try |
| { |
| _xr.setFeature( "http://xml.org/sax/features/namespace-prefixes", true ); |
| _xr.setFeature( "http://xml.org/sax/features/namespaces", true ); |
| _xr.setFeature( "http://xml.org/sax/features/validation", false ); |
| _xr.setProperty( "http://xml.org/sax/properties/lexical-handler", this ); |
| _xr.setContentHandler( this ); |
| _xr.setErrorHandler( this ); |
| } |
| catch ( Throwable e ) |
| { |
| throw new RuntimeException( e.getMessage(), e ); |
| } |
| } |
| |
| void setEntityResolver ( EntityResolver er ) |
| { |
| _xr.setEntityResolver( er ); |
| } |
| |
| public Cur load ( Locale l, InputSource is, XmlOptions options ) |
| { |
| _locale = l; |
| _context = new Cur.CurLoadContext( _locale, options ); |
| |
| try |
| { |
| _xr.parse( is ); |
| } |
| catch ( Exception e ) |
| { |
| throw new RuntimeException( e.getMessage(), e ); |
| } |
| |
| return _context.finish(); |
| } |
| |
| public void setDocumentLocator ( Locator locator ) |
| { |
| // TODO - hook up locator ... |
| } |
| |
| public void startDocument ( ) throws SAXException |
| { |
| // Do nothing ... start of document is implicit |
| } |
| |
| public void endDocument ( ) throws SAXException |
| { |
| // Do nothing ... end of document is implicit |
| } |
| |
| public void startElement ( String uri, String local, String qName, Attributes atts ) |
| throws SAXException |
| { |
| if (local.length() == 0) |
| local = qName; |
| |
| // Out current parser (Piccolo) does not error when a |
| // namespace is used and not defined. Check for these here |
| |
| if (qName.indexOf( ':' ) >= 0 && uri.length() == 0) |
| { |
| XmlError err = |
| XmlError.forMessage( |
| "Use of undefined namespace prefix: " + |
| qName.substring( 0, qName.indexOf( ':' ) )); |
| |
| throw new XmlRuntimeException( err.toString(), null, err ); |
| } |
| |
| _context.startElement( _locale.makeQualifiedQName( uri, qName ) ); |
| |
| for ( int i = 0, len = atts.getLength() ; i < len ; i++ ) |
| { |
| String aqn = atts.getQName( i ); |
| |
| if (aqn.equals( "xmlns" )) |
| { |
| _context.attr( "xmlns", _xmlnsUri, null, atts.getValue( i ) ); |
| } |
| else if (aqn.startsWith( "xmlns:" )) |
| { |
| String prefix = aqn.substring( 6 ); |
| |
| if (prefix.length() == 0) |
| { |
| XmlError err = |
| XmlError.forMessage( "Prefix not specified", XmlError.SEVERITY_ERROR ); |
| |
| throw new XmlRuntimeException( err.toString(), null, err ); |
| } |
| |
| String attrUri = atts.getValue( i ); |
| |
| if (attrUri.length() == 0) |
| { |
| XmlError err = |
| XmlError.forMessage( |
| "Prefix can't be mapped to no namespace: " + prefix, |
| XmlError.SEVERITY_ERROR ); |
| |
| throw new XmlRuntimeException( err.toString(), null, err ); |
| } |
| |
| _context.attr( prefix, _xmlnsUri, "xmlns", attrUri ); |
| } |
| else |
| { |
| int colon = aqn.indexOf( ':' ); |
| |
| if (colon < 0) |
| _context.attr( aqn, atts.getURI( i ), null, atts.getValue( i ) ); |
| else |
| { |
| _context.attr( |
| aqn.substring( colon + 1 ), atts.getURI( i ), aqn.substring( 0, colon ), |
| atts.getValue( i ) ); |
| } |
| } |
| } |
| } |
| |
| public void endElement ( String namespaceURI, String localName, String qName ) |
| throws SAXException |
| { |
| _context.endElement(); |
| } |
| |
| public void characters ( char ch[], int start, int length ) throws SAXException |
| { |
| _context.text( ch, start, length ); |
| } |
| |
| public void ignorableWhitespace ( char ch[], int start, int length ) throws SAXException |
| { |
| } |
| |
| public void comment ( char ch[], int start, int length ) throws SAXException |
| { |
| _context.comment( ch, start, length ); |
| } |
| |
| public void processingInstruction ( String target, String data ) throws SAXException |
| { |
| _context.procInst( target, data ); |
| } |
| |
| public void startDTD ( String name, String publicId, String systemId ) throws SAXException |
| { |
| } |
| |
| public void endDTD ( ) throws SAXException |
| { |
| } |
| |
| public void startPrefixMapping ( String prefix, String uri ) throws SAXException |
| { |
| if (beginsWithXml( prefix ) && ! ( "xml".equals( prefix ) && _xml1998Uri.equals( uri ))) |
| { |
| XmlError err = |
| XmlError.forMessage( |
| "Prefix can't begin with XML: " + prefix, XmlError.SEVERITY_ERROR ); |
| |
| throw new XmlRuntimeException( err.toString(), null, err ); |
| } |
| } |
| |
| public void endPrefixMapping ( String prefix ) throws SAXException |
| { |
| } |
| |
| public void skippedEntity ( String name ) throws SAXException |
| { |
| // throw new RuntimeException( "Not impl: skippedEntity" ); |
| } |
| |
| public void startCDATA ( ) throws SAXException |
| { |
| } |
| |
| public void endCDATA ( ) throws SAXException |
| { |
| } |
| |
| public void startEntity ( String name ) throws SAXException |
| { |
| // throw new RuntimeException( "Not impl: startEntity" ); |
| } |
| |
| public void endEntity ( String name ) throws SAXException |
| { |
| // throw new RuntimeException( "Not impl: endEntity" ); |
| } |
| |
| public void fatalError ( SAXParseException e ) throws SAXException |
| { |
| throw e; |
| } |
| |
| public void error ( SAXParseException e ) throws SAXException |
| { |
| throw e; |
| } |
| |
| public void warning ( SAXParseException e ) throws SAXException |
| { |
| throw e; |
| } |
| |
| public InputSource resolveEntity ( String publicId, String systemId ) |
| { |
| return new InputSource( new StringReader( "" ) ); |
| } |
| |
| private Locale _locale; |
| private XMLReader _xr; |
| private LoadContext _context; |
| private Locator _startLocator; |
| } |
| |
| private Dom load ( InputSource is, XmlOptions options ) |
| { |
| return getSaxLoader( options ).load( this, is, options ).getDom(); |
| } |
| |
| public Dom load ( Reader r ) |
| { |
| return load( new InputSource( r ), null ); |
| } |
| |
| public Dom load ( String s ) |
| { |
| return load( new InputSource( new StringReader( s ) ), null ); |
| } |
| |
| public Dom load ( InputStream in ) |
| { |
| return load( in, null ); |
| } |
| |
| public Dom load ( InputStream in, XmlOptions options ) |
| { |
| return load( new InputSource( in ), options ); |
| } |
| |
| public Dom load ( String s, XmlOptions options ) |
| { |
| return load( new InputSource( new StringReader( s ) ), options ); |
| } |
| |
| // |
| // DOMImplementation methods |
| // |
| |
| public Document createDocument ( String uri, String qname, DocumentType doctype ) |
| { |
| return DomImpl._domImplementation_createDocument( this, uri, qname, doctype ); |
| } |
| |
| public DocumentType createDocumentType ( String qname, String publicId, String systemId ) |
| { |
| throw new RuntimeException( "Not implemented" ); |
| // return DomImpl._domImplementation_createDocumentType( this, qname, publicId, systemId ); |
| } |
| |
| public boolean hasFeature ( String feature, String version ) |
| { |
| return DomImpl._domImplementation_hasFeature( this, feature, version ); |
| } |
| |
| public Object getFeature ( String feature, String version ) |
| { |
| throw new RuntimeException( "DOM Level 3 Not implemented" ); |
| } |
| |
| |
| // |
| // SaajCallback methods |
| // |
| |
| public void setSaajData ( Node n, Object o ) |
| { |
| assert n instanceof Dom; |
| |
| DomImpl.saajCallback_setSaajData( (Dom) n, o ); |
| } |
| |
| public Object getSaajData ( Node n ) |
| { |
| assert n instanceof Dom; |
| |
| return DomImpl.saajCallback_getSaajData( (Dom) n ); |
| } |
| |
| public Element createSoapElement ( QName name, QName parentName ) |
| { |
| assert _ownerDoc != null; |
| |
| return DomImpl.saajCallback_createSoapElement( _ownerDoc, name, parentName ); |
| } |
| |
| public Element importSoapElement ( Document doc, Element elem, boolean deep, QName parentName ) |
| { |
| assert doc instanceof Dom; |
| |
| return DomImpl.saajCallback_importSoapElement( (Dom) doc, elem, deep, parentName ); |
| } |
| |
| |
| private static final class DefaultQNameFactory implements QNameFactory |
| { |
| private QNameCache _cache = XmlBeans.getQNameCache(); |
| |
| public QName getQName ( String uri, String local ) |
| { |
| return _cache.getName( uri, local, "" ); |
| } |
| |
| public QName getQName ( String uri, String local, String prefix ) |
| { |
| return _cache.getName( uri, local, prefix ); |
| } |
| |
| public QName getQName ( |
| char[] uriSrc, int uriPos, int uriCch, |
| char[] localSrc, int localPos, int localCch ) |
| { |
| return |
| _cache.getName( |
| new String( uriSrc, uriPos, uriCch ), |
| new String( localSrc, localPos, localCch ), |
| "" ); |
| } |
| |
| public QName getQName ( |
| char[] uriSrc, int uriPos, int uriCch, |
| char[] localSrc, int localPos, int localCch, |
| char[] prefixSrc, int prefixPos, int prefixCch ) |
| { |
| return |
| _cache.getName( |
| new String( uriSrc, uriPos, uriCch ), |
| new String( localSrc, localPos, localCch ), |
| new String( prefixSrc, prefixPos, prefixCch ) ); |
| } |
| } |
| |
| // |
| // |
| // |
| |
| boolean _noSync; |
| |
| SchemaTypeLoader _schemaTypeLoader; |
| |
| private ReferenceQueue _refQueue; |
| private int _entryCount; |
| |
| private int _numTempFramesLeft; |
| private Cur[] _tempFrames; |
| |
| Cur _curPool; |
| int _curPoolCount; |
| |
| Cur _registered; |
| |
| GeneralChangeListener _generalChangeListeners; |
| |
| Cur _textChangeListeners; |
| |
| long _versionAll; |
| long _versionSansText; |
| |
| Locations _locations; |
| |
| CharUtil _charUtil; |
| |
| Saaj _saaj; |
| |
| Dom _ownerDoc; |
| |
| QNameFactory _qnameFactory; |
| |
| boolean _validateOnSet; |
| } |