package org.codehaus.mojo.cis.core;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
/**
* A bean class, which acts as a frontend for the
* {@link WebXmlMerger}.
*/
public class WebXmlMergerBean extends AbstractCisBean
{
private URL[] webXmlFiles;
private File targetFile;
private File markerFile;
/**
* Returns the marker file.
*/
public File getMarkerFile() {
if ( markerFile == null )
{
final File dir = getCisMarkersDir();
if ( dir == null )
{
return null;
}
setMarkerFile( new File( dir, "web.xml.marker" ) );
}
return markerFile;
}
/**
* Sets the marker file.
*/
public void setMarkerFile( File pMarkerFile ) {
markerFile = pMarkerFile;
}
/**
* Returns the target file.
*/
public File getTargetFile()
throws CisCoreErrorMessage
{
if ( targetFile == null )
{
final File dir = getCisHomeDir();
if ( dir == null )
{
throw new CisCoreErrorMessage( "You must set either the target file or the cis.home directory." );
}
return new File( dir, "WEB-INF/web.xml" );
}
return targetFile;
}
/**
* Sets the target file.
*/
public void setTargetFile( File pTargetFile )
{
targetFile = pTargetFile;
}
/**
* Returns the location of the custom "web.xml" file.
*/
public URL[] getWebXmlFiles()
{
return webXmlFiles;
}
/**
* Sets the location of the custom "web.xml" file.
*/
public void setWebXmlFiles( URL[] pWebXmlFiles )
{
webXmlFiles = pWebXmlFiles;
}
/**
* Called to merge the given "web.xml" files into the given
* target file.
*/
protected void mergeWebXmlFiles( URL[] pWebXmlFiles, File targetWebXml )
throws CisCoreException
{
try
{
Document[] documents = new Document[pWebXmlFiles.length];
DocumentBuilderFactory dbf = newDocumentBuilderFactory();
for ( int i = 0; i < documents.length; i++ )
{
URL u = pWebXmlFiles[i];
try
{
DocumentBuilder db = dbf.newDocumentBuilder();
db.setEntityResolver( new CisCoreEntityResolver( getCisUtils() ));
final InputSource isource = new InputSource( u.openStream() );
isource.setSystemId( u.toExternalForm() );
documents[i] = db.parse( isource );
}
catch ( SAXParseException e )
{
throw new CisCoreException( "Faile to parse file "
+ u.toExternalForm() + " at line " + e.getLineNumber()
+ ", column " + e.getColumnNumber() + ": "
+ e.getMessage(), e );
}
catch ( SAXException e )
{
throw new CisCoreException( "Failed to parse file "
+ u.toExternalForm() + ": " + e.getMessage(),
e );
}
catch ( IOException e )
{
throw new CisCoreException( "Failed to read file "
+ u.toExternalForm() + ": " + e.getMessage(),
e );
}
}
Document doc = new WebXmlMerger().merge( documents );
TransformerFactory.newInstance().newTransformer().transform( new DOMSource( doc), new StreamResult( targetWebXml ) );
}
catch ( ParserConfigurationException e )
{
throw new CisCoreException( e.getMessage(), e );
}
catch ( TransformerException e )
{
throw new CisCoreException( "Failed to create file "
+ targetWebXml.getPath() + ": "
+ e.getMessage(), e );
}
}
private DocumentBuilderFactory newDocumentBuilderFactory()
{
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setValidating( false );
dbf.setNamespaceAware( true );
return dbf;
}
public void execute() throws CisCoreException
{
URL[] files = getWebXmlFiles();
File mrkrFile = getMarkerFile();
File trgtFile = getTargetFile();
final CisUtils.Resource targetResource = new DefaultResource( mrkrFile == null ? trgtFile : mrkrFile );
boolean uptodate = true;
if ( files == null || files.length == 0 )
{
getCisUtils().info( "No web.xml files specified." );
return;
}
for ( int i = 0; uptodate && i < files.length; i++ )
{
final CisUtils.Resource sourceResource = new DefaultResource( files[i] );
uptodate = getCisUtils().isUpToDate( sourceResource, targetResource, true );
if ( !uptodate )
{
getCisUtils().debug( "File " + trgtFile
+ " isn't uptodate compared to "
+ files[i].toExternalForm() );
break;
}
}
if ( !uptodate )
{
getCisUtils().debug( "Generating " + trgtFile );
mergeWebXmlFiles( webXmlFiles, trgtFile );
if ( mrkrFile != null )
{
getCisUtils().touch( mrkrFile );
}
}
else
{
getCisUtils().debug( "File " + trgtFile + " is uptodate." );
}
}
}