|
|
|
|
|
*/ |
|
/* |
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
|
* contributor license agreements. See the NOTICE file distributed with |
|
* this work for additional information regarding copyright ownership. |
|
* The ASF licenses this file to You 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 com.sun.org.apache.xml.internal.dtm.ref; |
|
|
|
import com.sun.org.apache.xalan.internal.utils.ObjectFactory; |
|
import com.sun.org.apache.xerces.internal.parsers.SAXParser; |
|
import com.sun.org.apache.xml.internal.res.XMLErrorResources; |
|
import com.sun.org.apache.xml.internal.res.XMLMessages; |
|
import java.io.IOException; |
|
import java.lang.reflect.Constructor; |
|
import java.lang.reflect.Method; |
|
import org.xml.sax.InputSource; |
|
import org.xml.sax.SAXException; |
|
import org.xml.sax.XMLReader; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public class IncrementalSAXSource_Xerces |
|
implements IncrementalSAXSource |
|
{ |
|
// |
|
// Reflection. To allow this to compile with both Xerces1 and Xerces2, which |
|
// require very different methods and objects, we need to avoid static |
|
// references to those APIs. So until Xerces2 is pervasive and we're willing |
|
// to make it a prerequisite, we will rely upon relection. |
|
// |
|
Method fParseSomeSetup=null; |
|
Method fParseSome=null; |
|
Object fPullParserConfig=null; |
|
Method fConfigSetInput=null; |
|
Method fConfigParse=null; |
|
Method fSetInputSource=null; |
|
Constructor<?> fConfigInputSourceCtor=null; |
|
Method fConfigSetByteStream=null; |
|
Method fConfigSetCharStream=null; |
|
Method fConfigSetEncoding=null; |
|
Method fReset=null; |
|
|
|
// |
|
// Data |
|
|
|
SAXParser fIncrementalParser; |
|
private boolean fParseInProgress=false; |
|
|
|
// |
|
// Constructors |
|
// |
|
|
|
|
|
|
|
|
|
|
|
|
|
* */ |
|
public IncrementalSAXSource_Xerces() |
|
throws NoSuchMethodException |
|
{ |
|
try |
|
{ |
|
// This should be cleaned up and the use of reflection |
|
// removed - see JDK-8129880 |
|
|
|
// Xerces-2 incremental parsing support (as of Beta 3) |
|
// ContentHandlers still get set on fIncrementalParser (to get |
|
// conversion from XNI events to SAX events), but |
|
// _control_ for incremental parsing must be exercised via the config. |
|
// |
|
// At this time there's no way to read the existing config, only |
|
// to assert a new one... and only when creating a brand-new parser. |
|
// |
|
// Reflection is used to allow us to continue to compile against |
|
// Xerces1. If/when we can abandon the older versions of the parser, |
|
// this will simplify significantly. |
|
|
|
|
|
Class<?> xniConfigClass=ObjectFactory.findProviderClass( |
|
"com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration", |
|
true); |
|
Class<?>[] args1={xniConfigClass}; |
|
Constructor<?> ctor=SAXParser.class.getConstructor(args1); |
|
|
|
// Build the parser configuration object. StandardParserConfiguration |
|
// happens to implement XMLPullParserConfiguration, which is the API |
|
|
|
Class<?> xniStdConfigClass=ObjectFactory.findProviderClass( |
|
"com.sun.org.apache.xerces.internal.parsers.StandardParserConfiguration", |
|
true); |
|
fPullParserConfig=xniStdConfigClass.getConstructor().newInstance(); |
|
Object[] args2={fPullParserConfig}; |
|
fIncrementalParser = (SAXParser)ctor.newInstance(args2); |
|
|
|
// Preload all the needed the configuration methods... I want to know they're |
|
// all here before we commit to trying to use them, just in case the |
|
|
|
Class<?> fXniInputSourceClass=ObjectFactory.findProviderClass( |
|
"com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource", |
|
true); |
|
Class<?>[] args3={fXniInputSourceClass}; |
|
fConfigSetInput=xniStdConfigClass.getMethod("setInputSource",args3); |
|
|
|
Class<?>[] args4={String.class,String.class,String.class}; |
|
fConfigInputSourceCtor=fXniInputSourceClass.getConstructor(args4); |
|
Class<?>[] args5={java.io.InputStream.class}; |
|
fConfigSetByteStream=fXniInputSourceClass.getMethod("setByteStream",args5); |
|
Class<?>[] args6={java.io.Reader.class}; |
|
fConfigSetCharStream=fXniInputSourceClass.getMethod("setCharacterStream",args6); |
|
Class<?>[] args7={String.class}; |
|
fConfigSetEncoding=fXniInputSourceClass.getMethod("setEncoding",args7); |
|
|
|
Class<?>[] argsb={Boolean.TYPE}; |
|
fConfigParse=xniStdConfigClass.getMethod("parse",argsb); |
|
Class<?>[] noargs=new Class<?>[0]; |
|
fReset=fIncrementalParser.getClass().getMethod("reset",noargs); |
|
} |
|
catch(Exception e) |
|
{ |
|
// Fallback if this fails (implemented in createIncrementalSAXSource) is |
|
// to attempt Xerces-1 incremental setup. Can't do tail-call in |
|
// constructor, so create new, copy Xerces-1 initialization, |
|
|
|
IncrementalSAXSource_Xerces dummy=new IncrementalSAXSource_Xerces(new SAXParser()); |
|
this.fParseSomeSetup=dummy.fParseSomeSetup; |
|
this.fParseSome=dummy.fParseSome; |
|
this.fIncrementalParser=dummy.fIncrementalParser; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
* */ |
|
public IncrementalSAXSource_Xerces(SAXParser parser) |
|
throws NoSuchMethodException |
|
{ |
|
// Reflection is used to allow us to compile against |
|
// Xerces2. If/when we can abandon the older versions of the parser, |
|
// this constructor will simply have to fail until/unless the |
|
// Xerces2 incremental support is made available on previously |
|
|
|
fIncrementalParser=parser; |
|
Class<?> me=parser.getClass(); |
|
Class<?>[] parms={InputSource.class}; |
|
fParseSomeSetup=me.getMethod("parseSomeSetup",parms); |
|
parms=new Class<?>[0]; |
|
fParseSome=me.getMethod("parseSome",parms); |
|
// Fallback if this fails (implemented in createIncrementalSAXSource) is |
|
// to use IncrementalSAXSource_Filter rather than Xerces-specific code. |
|
} |
|
|
|
// |
|
// Factories |
|
|
|
static public IncrementalSAXSource createIncrementalSAXSource() |
|
{ |
|
try |
|
{ |
|
return new IncrementalSAXSource_Xerces(); |
|
} |
|
catch(NoSuchMethodException e) |
|
{ |
|
// Xerces version mismatch; neither Xerces1 nor Xerces2 succeeded. |
|
|
|
IncrementalSAXSource_Filter iss=new IncrementalSAXSource_Filter(); |
|
iss.setXMLReader(new SAXParser()); |
|
return iss; |
|
} |
|
} |
|
|
|
static public IncrementalSAXSource |
|
createIncrementalSAXSource(SAXParser parser) { |
|
try |
|
{ |
|
return new IncrementalSAXSource_Xerces(parser); |
|
} |
|
catch(NoSuchMethodException e) |
|
{ |
|
// Xerces version mismatch; neither Xerces1 nor Xerces2 succeeded. |
|
|
|
IncrementalSAXSource_Filter iss=new IncrementalSAXSource_Filter(); |
|
iss.setXMLReader(parser); |
|
return iss; |
|
} |
|
} |
|
|
|
// |
|
// Public methods |
|
// |
|
|
|
|
|
public void setContentHandler(org.xml.sax.ContentHandler handler) |
|
{ |
|
// Typecast required in Xerces2; SAXParser doesn't inheret XMLReader |
|
|
|
((XMLReader)fIncrementalParser).setContentHandler(handler); |
|
} |
|
|
|
|
|
public void setLexicalHandler(org.xml.sax.ext.LexicalHandler handler) |
|
{ |
|
|
|
try |
|
{ |
|
// Typecast required in Xerces2; SAXParser doesn't inheret XMLReader |
|
|
|
((XMLReader)fIncrementalParser).setProperty("http://xml.org/sax/properties/lexical-handler", |
|
handler); |
|
} |
|
catch(org.xml.sax.SAXNotRecognizedException e) |
|
{ |
|
// Nothing we can do about it |
|
} |
|
catch(org.xml.sax.SAXNotSupportedException e) |
|
{ |
|
// Nothing we can do about it |
|
} |
|
} |
|
|
|
|
|
public void setDTDHandler(org.xml.sax.DTDHandler handler) |
|
{ |
|
// Typecast required in Xerces2; SAXParser doesn't inheret XMLReader |
|
|
|
((XMLReader)fIncrementalParser).setDTDHandler(handler); |
|
} |
|
|
|
//================================================================ |
|
|
|
|
|
|
|
|
|
|
|
* */ |
|
public void startParse(InputSource source) throws SAXException |
|
{ |
|
if (fIncrementalParser==null) |
|
throw new SAXException(XMLMessages.createXMLMessage(XMLErrorResources.ER_STARTPARSE_NEEDS_SAXPARSER, null)); |
|
if (fParseInProgress) |
|
throw new SAXException(XMLMessages.createXMLMessage(XMLErrorResources.ER_STARTPARSE_WHILE_PARSING, null)); |
|
|
|
boolean ok=false; |
|
|
|
try |
|
{ |
|
ok = parseSomeSetup(source); |
|
} |
|
catch(Exception ex) |
|
{ |
|
throw new SAXException(ex); |
|
} |
|
|
|
if(!ok) |
|
throw new SAXException(XMLMessages.createXMLMessage(XMLErrorResources.ER_COULD_NOT_INIT_PARSER, null)); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
* */ |
|
public Object deliverMoreNodes (boolean parsemore) |
|
{ |
|
if(!parsemore) |
|
{ |
|
fParseInProgress=false; |
|
return Boolean.FALSE; |
|
} |
|
|
|
Object arg; |
|
try { |
|
boolean keepgoing = parseSome(); |
|
arg = keepgoing ? Boolean.TRUE : Boolean.FALSE; |
|
} catch (SAXException ex) { |
|
arg = ex; |
|
} catch (IOException ex) { |
|
arg = ex; |
|
} catch (Exception ex) { |
|
arg = new SAXException(ex); |
|
} |
|
return arg; |
|
} |
|
|
|
|
|
private boolean parseSomeSetup(InputSource source) |
|
throws SAXException, IOException, IllegalAccessException, |
|
java.lang.reflect.InvocationTargetException, |
|
java.lang.InstantiationException |
|
{ |
|
if(fConfigSetInput!=null) |
|
{ |
|
// Obtain input from SAX inputSource object, construct XNI version of |
|
|
|
Object[] parms1={source.getPublicId(),source.getSystemId(),null}; |
|
Object xmlsource=fConfigInputSourceCtor.newInstance(parms1); |
|
Object[] parmsa={source.getByteStream()}; |
|
fConfigSetByteStream.invoke(xmlsource,parmsa); |
|
parmsa[0]=source.getCharacterStream(); |
|
fConfigSetCharStream.invoke(xmlsource,parmsa); |
|
parmsa[0]=source.getEncoding(); |
|
fConfigSetEncoding.invoke(xmlsource,parmsa); |
|
|
|
// Bugzilla5272 patch suggested by Sandy Gao. |
|
// Has to be reflection to run with Xerces2 |
|
// after compilation against Xerces1. or vice |
|
|
|
Object[] noparms=new Object[0]; |
|
fReset.invoke(fIncrementalParser,noparms); |
|
|
|
parmsa[0]=xmlsource; |
|
fConfigSetInput.invoke(fPullParserConfig,parmsa); |
|
|
|
|
|
return parseSome(); |
|
} |
|
else |
|
{ |
|
Object[] parm={source}; |
|
Object ret=fParseSomeSetup.invoke(fIncrementalParser,parm); |
|
return ((Boolean)ret).booleanValue(); |
|
} |
|
} |
|
|
|
private static final Object[] noparms=new Object[0]; |
|
private static final Object[] parmsfalse={Boolean.FALSE}; |
|
private boolean parseSome() |
|
throws SAXException, IOException, IllegalAccessException, |
|
java.lang.reflect.InvocationTargetException |
|
{ |
|
|
|
if(fConfigSetInput!=null) |
|
{ |
|
Object ret=(Boolean)(fConfigParse.invoke(fPullParserConfig,parmsfalse)); |
|
return ((Boolean)ret).booleanValue(); |
|
} |
|
else |
|
{ |
|
Object ret=fParseSome.invoke(fIncrementalParser,noparms); |
|
return ((Boolean)ret).booleanValue(); |
|
} |
|
} |
|
|
|
|
|
//================================================================ |
|
|
|
|
|
*/ |
|
@Deprecated |
|
public static void _main(String args[]) |
|
{ |
|
System.out.println("Starting..."); |
|
|
|
CoroutineManager co = new CoroutineManager(); |
|
int appCoroutineID = co.co_joinCoroutineSet(-1); |
|
if (appCoroutineID == -1) |
|
{ |
|
System.out.println("ERROR: Couldn't allocate coroutine number.\n"); |
|
return; |
|
} |
|
IncrementalSAXSource parser= |
|
createIncrementalSAXSource(); |
|
|
|
|
|
com.sun.org.apache.xml.internal.serialize.XMLSerializer trace; |
|
trace=new com.sun.org.apache.xml.internal.serialize.XMLSerializer(System.out,null); |
|
parser.setContentHandler(trace); |
|
parser.setLexicalHandler(trace); |
|
|
|
// Tell coroutine to begin parsing, run while parsing is in progress |
|
|
|
for(int arg=0;arg<args.length;++arg) |
|
{ |
|
try |
|
{ |
|
InputSource source = new InputSource(args[arg]); |
|
Object result=null; |
|
boolean more=true; |
|
parser.startParse(source); |
|
for(result = parser.deliverMoreNodes(more); |
|
result==Boolean.TRUE; |
|
result = parser.deliverMoreNodes(more)) |
|
{ |
|
System.out.println("\nSome parsing successful, trying more.\n"); |
|
|
|
|
|
if(arg+1<args.length && "!".equals(args[arg+1])) |
|
{ |
|
++arg; |
|
more=false; |
|
} |
|
|
|
} |
|
|
|
if (result instanceof Boolean && ((Boolean)result)==Boolean.FALSE) |
|
{ |
|
System.out.println("\nParser ended (EOF or on request).\n"); |
|
} |
|
else if (result == null) { |
|
System.out.println("\nUNEXPECTED: Parser says shut down prematurely.\n"); |
|
} |
|
else if (result instanceof Exception) { |
|
throw new com.sun.org.apache.xml.internal.utils.WrappedRuntimeException((Exception)result); |
|
// System.out.println("\nParser threw exception:"); |
|
// ((Exception)result).printStackTrace(); |
|
} |
|
|
|
} |
|
|
|
catch(SAXException e) |
|
{ |
|
e.printStackTrace(); |
|
} |
|
} |
|
|
|
} |
|
|
|
|
|
} // class IncrementalSAXSource_Xerces |