Reorganize the SAX event pipeline, this fixes the problem of slow parsing when the namespace is not correct

git-svn-id: https://svn.apache.org/repos/asf/maven/maven-1/plugins/trunk@350057 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
ltheussl 2005-11-30 21:32:02 +00:00
parent cbd121a8be
commit 8158ed0a6a
2 changed files with 88 additions and 77 deletions

View File

@ -66,6 +66,7 @@ public class JaxpMsvBean
private static final int MSV_FATAL_ERROR = 2; private static final int MSV_FATAL_ERROR = 2;
private boolean isValid = true; private boolean isValid = true;
private boolean validNamespace = true;
private XPathLocationTracker tracker; private XPathLocationTracker tracker;
//~ Methods -------------------------------------------------------------- //~ Methods --------------------------------------------------------------
@ -82,18 +83,20 @@ public class JaxpMsvBean
verifier.setErrorHandler( new ErrorHandlerImpl() ); verifier.setErrorHandler( new ErrorHandlerImpl() );
VerifierHandler handler = verifier.getVerifierHandler(); VerifierHandler handler = verifier.getVerifierHandler();
tracker = new XPathLocationTracker( handler );
SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware( true ); factory.setNamespaceAware( true );
factory.setValidating( false ); factory.setValidating( false );
XMLReader reader = factory.newSAXParser().getXMLReader(); XMLReader reader = factory.newSAXParser().getXMLReader();
reader.setContentHandler( tracker );
reader.setEntityResolver( new EntityResolverImpl() );
reader.parse( new InputSource( new FileInputStream( file ) ) ); tracker = new XPathLocationTracker();
tracker.setParent( reader );
tracker.setContentHandler( handler );
tracker.setEntityResolver( new EntityResolverImpl() );
tracker.parse( new InputSource( new FileInputStream( file ) ) );
endMessage(); endMessage();
} }
@ -101,7 +104,7 @@ public class JaxpMsvBean
* Sets the schema. * Sets the schema.
* @param newSchema The schema to set * @param newSchema The schema to set
*/ */
public void setSchema(String newSchema) public void setSchema( String newSchema )
{ {
this.schema = newSchema; this.schema = newSchema;
} }
@ -110,7 +113,7 @@ public class JaxpMsvBean
* Sets the file. * Sets the file.
* @param newFile The file to set * @param newFile The file to set
*/ */
public void setFile(String newFile) public void setFile( String newFile )
{ {
this.file = newFile; this.file = newFile;
} }
@ -138,33 +141,36 @@ public class JaxpMsvBean
if ( isValid ) if ( isValid )
{ {
log.info( file + " verified: OK" ); log.info( file + " verified: OK" );
} else { }
else
{
log.info( file + " is NOT valid!" ); log.info( file + " is NOT valid!" );
} }
} }
private void setValid(boolean valid) private void errorMessage( SAXParseException e, int type )
{
this.isValid = valid;
}
private void errorMessage(SAXParseException e, int type)
{ {
File xmlFile = new File( file ); File xmlFile = new File( file );
if ( type == MSV_ERROR ) if ( type == MSV_ERROR )
{
// if namespace is not correct, error messages are crap
if ( validNamespace )
{ {
log.error( " ERROR on line " + e.getLineNumber() log.error( " ERROR on line " + e.getLineNumber()
+ " of file " + xmlFile.getName() + "," ); + " of file " + xmlFile.getName() + "," );
log.error( " XPath location " + tracker.getXPath() + ":" ); log.error( " XPath location " + tracker.getXPath() + ":" );
log.error( " " + e.getMessage() ); log.error( " " + e.getMessage() );
} else if ( type == MSV_FATAL_ERROR ) }
}
else if ( type == MSV_FATAL_ERROR )
{ {
log.error( " Non-recoverable parsing error on line " log.error( " Non-recoverable parsing error on line "
+ e.getLineNumber() + " of file " + xmlFile.getName() + "," ); + e.getLineNumber() + " of file " + xmlFile.getName() + "," );
log.error( " XPath location " + tracker.getXPath() + ":" ); log.error( " XPath location " + tracker.getXPath() + ":" );
log.error( " " + e.getMessage() ); log.error( " " + e.getMessage() );
} else if ( type == MSV_WARNING ) }
else if ( type == MSV_WARNING )
{ {
log.warn( " WARNING on line " + e.getLineNumber() log.warn( " WARNING on line " + e.getLineNumber()
+ " of file " + xmlFile.getName() + "," ); + " of file " + xmlFile.getName() + "," );
@ -175,45 +181,36 @@ public class JaxpMsvBean
private class ErrorHandlerImpl implements ErrorHandler private class ErrorHandlerImpl implements ErrorHandler
{ {
public void warning(SAXParseException e) throws SAXException public void warning( SAXParseException e ) throws SAXException
{ {
errorMessage( e, MSV_WARNING ); errorMessage( e, MSV_WARNING );
throw e;
} }
public void error(SAXParseException e) throws SAXException public void error( SAXParseException e ) throws SAXException
{ {
/*if (e.getMessage() != null && e.getMessage().indexOf("xsi:schemaLocation") > -1) errorMessage( e, MSV_ERROR);
{ isValid = false;
// unexpected attribute "xsi:schemaLocation"
// ignore, this is due to a valid xsd declaration
// Jaxp ignores additionals namespaces declared in the xml file (xmlns:xsi) and it can't validate
// using multiple schema at once
return;
}*/
errorMessage( e, MSV_ERROR) ;
setValid( false );
if ( e.getMessage() != null if ( e.getMessage() != null
&& e.getMessage().startsWith("namespace URI of tag") ) && e.getMessage().startsWith("namespace URI of tag") )
{ {
// Fail the build if namespace declaration is wrong. validNamespace = false;
// Otherwise parsing seems to hang after the first element. }
throw new SAXException( e ); throw e;
} }
} public void fatalError( SAXParseException e ) throws SAXException
public void fatalError(SAXParseException e) throws SAXException
{ {
errorMessage( e, MSV_FATAL_ERROR ); errorMessage( e, MSV_FATAL_ERROR );
setValid( false ); isValid = false;
throw e;
} }
} }
private class EntityResolverImpl implements EntityResolver private class EntityResolverImpl implements EntityResolver
{ {
public InputSource resolveEntity(String publicId, public InputSource resolveEntity( String publicId,
String systemId) throws SAXException String systemId ) throws SAXException
{ {
log.warn( " WARNING: External entity " + systemId log.warn( " WARNING: External entity " + systemId
+ " won't be resolved" ); + " won't be resolved" );

View File

@ -21,8 +21,8 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.xml.sax.Attributes; import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.XMLFilterImpl; import org.xml.sax.helpers.XMLFilterImpl;
/** /**
@ -31,36 +31,26 @@ import org.xml.sax.helpers.XMLFilterImpl;
* *
* @author <a href="mailto:ltheussl@apache.org">Lukas Theussl</a> * @author <a href="mailto:ltheussl@apache.org">Lukas Theussl</a>
*/ */
public class XPathLocationTracker extends XMLFilterImpl public class XPathLocationTracker extends XMLFilterImpl
{ {
private State state; private State state;
private static final Integer[] ints = new Integer[] private static final Integer[] ints = new Integer[]
{ {
new Integer(0), new Integer( 0 ),
new Integer(1), new Integer( 1 ),
new Integer(2), new Integer( 2 ),
new Integer(3), new Integer( 3 ),
new Integer(4) new Integer( 4 )
}; };
/**
* Constructor: sets the ContentHandler.
* @param handler The ContentHandler
*/
public XPathLocationTracker( ContentHandler handler )
{
setContentHandler(handler);
}
/** /**
* Overriding ContentHandler. * Overriding ContentHandler.
* @throws SAXException SAXException * @throws SAXException SAXException
*/ */
public void startDocument() throws SAXException public void startDocument() throws SAXException
{ {
state = new State(null); state = new State( null );
super.startDocument(); super.startDocument();
} }
@ -82,11 +72,19 @@ public class XPathLocationTracker extends XMLFilterImpl
* @param atts atts * @param atts atts
* @throws SAXException SAXException * @throws SAXException SAXException
*/ */
public void startElement(String uri, String localName, public void startElement( String uri, String localName,
String qName, Attributes atts) throws SAXException String qName, Attributes atts ) throws SAXException
{ {
state = state.push(qName); state = state.push( qName );
super.startElement(uri, localName, qName, atts); try
{
super.startElement( uri, localName, qName, atts );
}
catch ( SAXParseException e )
{
// ignored on purpose: just avoid to throw an exception here
// it is thrown by the ErrorHandler in JaxpMsvBean instead
}
} }
/** /**
@ -96,10 +94,18 @@ public class XPathLocationTracker extends XMLFilterImpl
* @param qName qName * @param qName qName
* @throws SAXException SAXException * @throws SAXException SAXException
*/ */
public void endElement(String uri, String localName, String qName) public void endElement( String uri, String localName, String qName )
throws SAXException throws SAXException
{ {
super.endElement(uri, localName, qName); try
{
super.endElement( uri, localName, qName );
}
catch ( SAXParseException e )
{
// ignored on purpose: just avoid to throw an exception here
// it is thrown by the ErrorHandler in JaxpMsvBean instead
}
state = state.pop(); state = state.pop();
} }
@ -114,17 +120,19 @@ public class XPathLocationTracker extends XMLFilterImpl
if ( state == null ) if ( state == null )
{ {
throw new IllegalStateException( throw new IllegalStateException(
"startDocument event is not invoked"); "startDocument event is not invoked" );
} }
return state.getXPath(); return state.getXPath();
} }
private static Integer getInt(int i) private static Integer getInt( int i )
{ {
if ( i < ints.length ) if ( i < ints.length )
{ {
return ints[i]; return ints[i];
} else { }
else
{
return new Integer(i); return new Integer(i);
} }
} }
@ -148,8 +156,10 @@ public class XPathLocationTracker extends XMLFilterImpl
currentName = rawName; currentName = rawName;
if ( child == null ) if ( child == null )
{ {
child = new State(this); child = new State( this );
} else { }
else
{
child.reset(); child.reset();
} }
return child; return child;
@ -163,14 +173,16 @@ public class XPathLocationTracker extends XMLFilterImpl
private void count( String rawName ) private void count( String rawName )
{ {
Integer i = (Integer) counter.get(rawName); Integer i = (Integer) counter.get( rawName );
if ( i == null ) if ( i == null )
{ {
i = getInt(1); i = getInt( 1 );
} else {
i = getInt(i.intValue() + 1);
} }
counter.put(rawName, i); else
{
i = getInt( i.intValue() + 1 );
}
counter.put( rawName, i );
} }
private void reset() private void reset()
@ -185,16 +197,18 @@ public class XPathLocationTracker extends XMLFilterImpl
if ( parent == null ) // root if ( parent == null ) // root
{ {
xPath = "/"; xPath = "/";
if ( currentName != null) if ( currentName != null )
{ {
xPath += currentName; xPath += currentName;
} }
} else { // child node }
else // child node
{
xPath = parent.getXPath(); xPath = parent.getXPath();
if ( currentName != null ) if ( currentName != null )
{ {
xPath += '/' + currentName; xPath += '/' + currentName;
Integer i = (Integer) counter.get(currentName); Integer i = (Integer) counter.get( currentName );
xPath += '[' + i.toString() + ']'; xPath += '[' + i.toString() + ']';
} }
} }