package org.apache.maven;
/* ====================================================================
* 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.
* ====================================================================
*/
import com.sun.msv.verifier.jarv.TheFactoryImpl;
import java.io.File;
import java.io.FileInputStream;
import java.io.ByteArrayInputStream;
import javax.xml.parsers.SAXParserFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.iso_relax.verifier.Verifier;
import org.iso_relax.verifier.VerifierFactory;
import org.iso_relax.verifier.VerifierHandler;
import org.xml.sax.ErrorHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.SAXParseException;
import org.xml.sax.SAXException;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
/**
* JaxpMsvBean Bean: Uses JAXP implementation of MSV.
*
* @author <a href="mailto:ltheussl@apache.org">Lukas Theussl</a>
*/
public class JaxpMsvBean
{
//~ Instance fields ------------------------------------------------------
/** The schema to use. */
private String schema;
/** The file to validate. */
private String file;
/** For debug output. */
private Log log = LogFactory.getLog(JaxpMsvBean.class);
private static final String EMPTY = "";
private static final ByteArrayInputStream EMPTY_STREAM =
new ByteArrayInputStream(EMPTY.getBytes());
private static final int MSV_WARNING = 0;
private static final int MSV_ERROR = 1;
private static final int MSV_FATAL_ERROR = 2;
private boolean isValid = true;
private boolean validNamespace = true;
private XPathLocationTracker tracker;
//~ Methods --------------------------------------------------------------
/**
* Performs validation.
* @throws Exception Exception
*/
public void validate() throws Exception
{
VerifierFactory verifierFactory = new TheFactoryImpl();
Verifier verifier = verifierFactory.newVerifier( new File( schema ) );
verifier.setErrorHandler( new ErrorHandlerImpl() );
VerifierHandler handler = verifier.getVerifierHandler();
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware( true );
factory.setValidating( false );
XMLReader reader = factory.newSAXParser().getXMLReader();
tracker = new XPathLocationTracker();
tracker.setParent( reader );
tracker.setContentHandler( handler );
tracker.setEntityResolver( new EntityResolverImpl() );
tracker.parse( new InputSource( new FileInputStream( file ) ) );
endMessage();
}
/**
* Sets the schema.
* @param newSchema The schema to set
*/
public void setSchema( String newSchema )
{
this.schema = newSchema;
}
/**
* Sets the file.
* @param newFile The file to set
*/
public void setFile( String newFile )
{
this.file = newFile;
}
/**
* Gets the schema.
* @return The schema
*/
public String getSchema()
{
return schema;
}
/**
* Gets the file.
* @return The file
*/
public String getFile()
{
return file;
}
private void endMessage()
{
if ( isValid )
{
log.info( file + " verified: OK" );
}
else
{
log.info( file + " is NOT valid!" );
}
}
private void errorMessage( SAXParseException e, int type )
{
File xmlFile = new File( file );
if ( type == MSV_ERROR )
{
// if namespace is not correct, error messages are crap
if ( validNamespace )
{
log.error( " ERROR on line " + e.getLineNumber()
+ " of file " + xmlFile.getName() + "," );
log.error( " XPath location " + tracker.getXPath() + ":" );
log.error( " " + e.getMessage() );
}
}
else if ( type == MSV_FATAL_ERROR )
{
log.error( " Non-recoverable parsing error on line "
+ e.getLineNumber() + " of file " + xmlFile.getName() + "," );
log.error( " XPath location " + tracker.getXPath() + ":" );
log.error( " " + e.getMessage() );
}
else if ( type == MSV_WARNING )
{
log.warn( " WARNING on line " + e.getLineNumber()
+ " of file " + xmlFile.getName() + "," );
log.warn( " XPath location " + tracker.getXPath() + ":" );
log.warn( e.getMessage() );
}
}
private class ErrorHandlerImpl implements ErrorHandler
{
public void warning( SAXParseException e ) throws SAXException
{
errorMessage( e, MSV_WARNING );
throw e;
}
public void error( SAXParseException e ) throws SAXException
{
errorMessage( e, MSV_ERROR);
isValid = false;
if ( e.getMessage() != null
&& e.getMessage().startsWith("namespace URI of tag") )
{
validNamespace = false;
}
throw e;
}
public void fatalError( SAXParseException e ) throws SAXException
{
errorMessage( e, MSV_FATAL_ERROR );
isValid = false;
throw e;
}
}
private class EntityResolverImpl implements EntityResolver
{
public InputSource resolveEntity( String publicId,
String systemId ) throws SAXException
{
log.warn( " WARNING: External entity " + systemId
+ " won't be resolved" );
return new InputSource( EMPTY_STREAM );
}
}
}