/*
* $Id$
*
* Copyright 2006, The jCoderZ.org Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
* * Neither the name of the jCoderZ.org Project nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jcoderz.commons.taskdefs;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
/**
* This task is used to modify a deployment descriptor, making a
* copy of the given entity beans with their name changed from
* FooEntity to FooReaderEntity. It also modifies the accompanying
* weblogic specific deployment descriptors.
* @author Albrecht Messner
*/
public class MakeReadonlyBeans
extends Task
{
private static final String STYLE_GENERIC = "make-readonly-bean-generic.xsl";
private static final String STYLE_WEBLOGIC = "make-readonly-bean-wl.xsl";
private static final String STYLE_WEBLOGIC_CMP
= "make-readonly-bean-wlcmp.xsl";
private static final String STYLE_GENERATE_UTIL
= "generate-readonly-entity-util.xsl";
/** The output directory. */
private File mDestDir;
/** The generic deployment descriptor (ejb-jar.xml) to transform. */
private File mGenericDeploymentDescriptor = null;
/**
* The weblogic ejb deployment descriptor (weblogic-ejb-jar.xml) to
* transform.
*/
private File mWlsDeploymentDescriptor = null;
/**
* The weblogic RDBMS deployment descriptor (weblogic-cmp-rdbms-jar.xml)
* to transform.
*/
private File mWlsCmpDeploymentDescriptor = null;
/** List of all beans that need to be made read-only. */
private final List mReadonlyBeans = new ArrayList();
/** force output of target files even if they already exist. */
private boolean mForce = false;
/** terminate ant build on error. */
private boolean mFailOnError = false;
/** The directory to which generated source files should be written. */
private File mSourceDestDir;
/**
* Set the destination directory into which the XSL result
* files should be copied to. This parameter is required.
* @param dir the name of the destination directory.
**/
public void setDestdir (File dir)
{
mDestDir = dir;
}
public void setSourceDestdir (File dir)
{
mSourceDestDir = dir;
}
/**
* Sets the force output of target files flag to the given value.
*
* @param b Whether we should force the generation of output files.
*/
public void setForce (boolean b)
{
mForce = b;
}
/**
* Set whether we should fail on an error.
*
* @param b Whether we should fail on an error.
*/
public void setFailonerror (boolean b)
{
mFailOnError = b;
}
public void setDeploymentDescriptor (File f)
{
mGenericDeploymentDescriptor = f;
}
public void setWeblogicDeploymentDescriptor (File f)
{
mWlsDeploymentDescriptor = f;
}
public void setWeblogicCmpDeploymentDescriptor (File f)
{
mWlsCmpDeploymentDescriptor = f;
}
public ReadOnlyBean createReadOnlyBean ()
{
final ReadOnlyBean bn = new ReadOnlyBean();
mReadonlyBeans.add(bn);
return bn;
}
/** {@inheritDoc} */
public void execute ()
throws BuildException
{
try
{
checkFilesAndDirectories();
if (mForce || checkIfBuildRequired())
{
final File genericDdTarget
= new File(mDestDir, mGenericDeploymentDescriptor.getName());
transform(mGenericDeploymentDescriptor,
genericDdTarget,
STYLE_GENERIC);
transform(mWlsDeploymentDescriptor,
new File(mDestDir, mWlsDeploymentDescriptor.getName()),
STYLE_WEBLOGIC);
transform(mWlsCmpDeploymentDescriptor,
new File(mDestDir, mWlsCmpDeploymentDescriptor.getName()),
STYLE_WEBLOGIC_CMP);
transform(genericDdTarget,
new File(mDestDir, "generate-utils-stdout.txt"),
STYLE_GENERATE_UTIL);
}
else
{
log("All files are up-to-date.", Project.MSG_INFO);
}
}
catch (BuildException e)
{
if (mFailOnError)
{
throw e;
}
log(e.getMessage(), Project.MSG_ERR);
}
}
private String createListOfReadonlyBeans ()
{
final StringBuffer sbuf = new StringBuffer();
for (final Iterator it = mReadonlyBeans.iterator(); it.hasNext(); )
{
if (sbuf.length() == 0)
{
sbuf.append('|');
}
final ReadOnlyBean bean = (ReadOnlyBean) it.next();
sbuf.append(bean.getName());
sbuf.append('|');
}
if (sbuf.length() == 0)
{
sbuf.append("||");
}
return sbuf.toString();
}
private boolean checkIfBuildRequired ()
{
final File genericOutFile
= new File(mDestDir, mGenericDeploymentDescriptor.getName());
final File weblogicOutFile
= new File(mDestDir, mWlsDeploymentDescriptor.getName());
final File weblogicCmpOutFile
= new File(mDestDir, mWlsCmpDeploymentDescriptor.getName());
boolean buildRequired = false;
if (! genericOutFile.exists()
|| genericOutFile.lastModified()
< mGenericDeploymentDescriptor.lastModified())
{
buildRequired = true;
}
if (! weblogicOutFile.exists()
|| weblogicOutFile.lastModified()
< mWlsDeploymentDescriptor.lastModified())
{
buildRequired = true;
}
if (! weblogicCmpOutFile.exists()
|| weblogicCmpOutFile.lastModified()
< mWlsCmpDeploymentDescriptor.lastModified())
{
buildRequired = true;
}
return buildRequired;
}
private void checkFilesAndDirectories ()
{
checkFile("genericDeploymentDescriptor", mGenericDeploymentDescriptor);
checkFile("weblogicDeploymentDescriptor", mWlsDeploymentDescriptor);
checkFile("weblogicCmpDeploymentDescriptor", mWlsCmpDeploymentDescriptor);
checkDirectory("destdir", mDestDir);
checkDirectory("sourceDestdir", mSourceDestDir);
}
private void checkFile (String paramName, File file)
{
if (file == null)
{
throw new BuildException(
"Mandatory attribute '" + paramName + "' is missing.");
}
if (! file.exists())
{
throw new BuildException("File '" + file + "' does not exist");
}
}
private void checkDirectory (String paramName, File directory)
{
if (directory == null)
{
throw new BuildException(
"Mandatory attribute '" + paramName + "' missing.");
}
if (! directory.exists())
{
throw new BuildException(
"Output directory '" + directory + "' does not exist.");
}
if (! directory.isDirectory())
{
throw new BuildException("'" + directory + "' is not a directory");
}
}
/**
* Execute the XSL transformation.
* @throws BuildException if an error during transformation occurs.
*/
private void transform (File inFile, File outFile, String xslFile)
throws BuildException
{
try
{
// Xalan2 transformator is required,
// that why we explicit use this factory
final TransformerFactory factory
= new org.apache.xalan.processor.TransformerFactoryImpl();
factory.setURIResolver(new JarArchiveUriResolver(this));
final InputStream xslStream
= LogMessageGenerator.class.getResourceAsStream(xslFile);
final Transformer transformer
= factory.newTransformer(new StreamSource(xslStream));
transformer.setParameter("outdir", mDestDir.getAbsolutePath());
transformer.setParameter("srcdir", mSourceDestDir.getAbsolutePath());
transformer.setParameter("bean-names", createListOfReadonlyBeans());
final StreamResult out = new StreamResult(outFile);
transformer.transform(getSaxSource(inFile), out);
}
catch (Exception e)
{
throw new BuildException("Error during transformation: " + e, e);
}
}
private SAXSource getSaxSource (File xmlFile)
throws SAXException, FileNotFoundException
{
final XMLReader xr = getXmlReader();
xr.setEntityResolver(new DummyEntityResolver(this));
final FileInputStream fileInStream = new FileInputStream(xmlFile);
final InputSource inSource = new InputSource(fileInStream);
return new SAXSource(xr, inSource);
}
private static XMLReader getXmlReader()
throws SAXException
{
XMLReader result;
try
{
result = XMLReaderFactory.createXMLReader(
"org.apache.xerces.parsers.SAXParser");
}
catch (Exception ex)
{
// log this?
result = XMLReaderFactory.createXMLReader();
}
return result;
}
public final class ReadOnlyBean
{
private String mName;
/**
* @return Returns the beanName.
*/
public String getName ()
{
return mName;
}
/**
* @param beanName The beanName to set.
*/
public void setName (String beanName)
{
mName = beanName;
}
}
}