vmassol 2005/02/15 02:31:44 Modified: integration/ant build.xml integration/ant/src/java/org/apache/cactus/integration/ant/deployment/application ApplicationXml.java ApplicationXmlIo.java ApplicationXmlTag.java DefaultApplicationXml.java Added: integration/ant/src/java/org/apache/cactus/integration/ant CactifyEarTask.java CactusWar.java integration/ant/src/test-input/org/apache/cactus/integration/ant test-cactifyear.xml integration/ant/src/test/org/apache/cactus/integration/ant TestCactifyEarTask.java Log: CACTUS-190: Added new CactifyEar Ant task. Submitted by Magnus Grimsell. Revision Changes Path 1.60 +3 -1 jakarta-cactus/integration/ant/build.xml Index: build.xml =================================================================== RCS file: /home/cvs/jakarta-cactus/integration/ant/build.xml,v retrieving revision 1.59 retrieving revision 1.60 diff -u -r1.59 -r1.60 --- build.xml 30 Jan 2005 12:12:30 -0000 1.59 +++ build.xml 15 Feb 2005 10:31:44 -0000 1.60 @@ -167,6 +167,8 @@ comment="Cactus Tasks for Ant"> <entry key="cactifywar" value="org.apache.cactus.integration.ant.CactifyWarTask"/> + <entry key="cactifyear" + value="org.apache.cactus.integration.ant.CactifyEarTask"/> <entry key="cactus" value="org.apache.cactus.integration.ant.CactusTask"/> <entry key="runservertests" 1.2 +10 -2 jakarta-cactus/integration/ant/src/java/org/apache/cactus/integration/ant/deployment/application/ApplicationXml.java Index: ApplicationXml.java =================================================================== RCS file: /home/cvs/jakarta-cactus/integration/ant/src/java/org/apache/cactus/integration/ant/deployment/application/ApplicationXml.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- ApplicationXml.java 31 May 2004 20:05:24 -0000 1.1 +++ ApplicationXml.java 15 Feb 2005 10:31:44 -0000 1.2 @@ -1,7 +1,7 @@ /* * ======================================================================== * - * Copyright 2003 The Apache Software Foundation. + * Copyright 2003-2005 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -84,4 +84,12 @@ * they occur in the descriptor */ Iterator getElements(ApplicationXmlTag theTag); + + /** + * Adds a web module to the deployment descriptor + * + * @param theUri the uri of the new module + * @param theContext the context of the new module + */ + void addWebModule(String theUri, String theContext); } 1.2 +100 -2 jakarta-cactus/integration/ant/src/java/org/apache/cactus/integration/ant/deployment/application/ApplicationXmlIo.java Index: ApplicationXmlIo.java =================================================================== RCS file: /home/cvs/jakarta-cactus/integration/ant/src/java/org/apache/cactus/integration/ant/deployment/application/ApplicationXmlIo.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- ApplicationXmlIo.java 31 May 2004 20:05:24 -0000 1.1 +++ ApplicationXmlIo.java 15 Feb 2005 10:31:44 -0000 1.2 @@ -1,7 +1,7 @@ /* * ======================================================================== * - * Copyright 2003 The Apache Software Foundation. + * Copyright 2003-2005 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,13 +21,17 @@ import java.io.File; import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import org.apache.xml.serialize.OutputFormat; +import org.apache.xml.serialize.XMLSerializer; import org.xml.sax.EntityResolver; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -148,4 +152,98 @@ return new DefaultApplicationXml(builder.parse(theInput)); } + /** + * Writes the specified document to a file. + * + * @param theAppXml The descriptor to serialize + * @param theFile The file to write to + * @throws IOException If an I/O error occurs + */ + public static void writeApplicationXml(ApplicationXml theAppXml, + File theFile) + throws IOException + { + writeApplicationXml(theAppXml, theFile, null, false); + } + + /** + * Writes the specified document to a file. + * + * @param theAppXml The descriptor to serialize + * @param theFile The file to write to + * @param theEncoding The character encoding to use + * @throws IOException If an I/O error occurs + */ + public static void writeApplicationXml(ApplicationXml theAppXml, + File theFile, + String theEncoding) + throws IOException + { + writeApplicationXml(theAppXml, theFile, theEncoding, false); + } + + /** + * Writes the specified document to a file. + * + * @param theAppXml The descriptor to serialize + * @param theFile The file to write to + * @param theEncoding The character encoding to use + * @param isIndent Whether the written XML should be indented + * @throws IOException If an I/O error occurs + */ + public static void writeApplicationXml(ApplicationXml theAppXml, + File theFile, + String theEncoding, + boolean isIndent) + throws IOException + { + OutputStream out = null; + try + { + out = new FileOutputStream(theFile); + writeApplicationXml(theAppXml, out, theEncoding, isIndent); + } + finally + { + if (out != null) + { + try + { + out.close(); + } + catch (IOException ioe) + { + // we'll pass on the original IO error, so ignore this one + } + } + } + } + + /** + * Writes the specified document to an output stream. + * + * @param theAppXml The descriptor to serialize + * @param theOutput The output stream to write to + * @param theEncoding The character encoding to use + * @param isIndent Whether the written XML should be indented + * @throws IOException If an I/O error occurs + */ + public static void writeApplicationXml(ApplicationXml theAppXml, + OutputStream theOutput, + String theEncoding, + boolean isIndent) + throws IOException + { + OutputFormat outputFormat = + new OutputFormat(theAppXml.getDocument()); + if (theEncoding != null) + { + outputFormat.setEncoding(theEncoding); + } + outputFormat.setIndenting(isIndent); + outputFormat.setPreserveSpace(false); + XMLSerializer serializer = new XMLSerializer(theOutput, outputFormat); + serializer.serialize(theAppXml.getDocument()); + } + } 1.2 +8 -2 jakarta-cactus/integration/ant/src/java/org/apache/cactus/integration/ant/deployment/application/ApplicationXmlTag.java Index: ApplicationXmlTag.java =================================================================== RCS file: /home/cvs/jakarta-cactus/integration/ant/src/java/org/apache/cactus/integration/ant/deployment/application/ApplicationXmlTag.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- ApplicationXmlTag.java 31 May 2004 20:05:24 -0000 1.1 +++ ApplicationXmlTag.java 15 Feb 2005 10:31:44 -0000 1.2 @@ -1,7 +1,7 @@ /* * ======================================================================== * - * Copyright 2003 The Apache Software Foundation. + * Copyright 2003-2005 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -73,6 +73,12 @@ public static final ApplicationXmlTag CONTEXT_ROOT = new ApplicationXmlTag("context-root"); + /** + * Element name 'security-role', + */ + public static final ApplicationXmlTag SECURITY_ROLE = + new ApplicationXmlTag("security-role"); + // Instance Variables ------------------------------------------------------ /** 1.2 +96 -2 jakarta-cactus/integration/ant/src/java/org/apache/cactus/integration/ant/deployment/application/DefaultApplicationXml.java Index: DefaultApplicationXml.java =================================================================== RCS file: /home/cvs/jakarta-cactus/integration/ant/src/java/org/apache/cactus/integration/ant/deployment/application/DefaultApplicationXml.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- DefaultApplicationXml.java 31 May 2004 20:05:24 -0000 1.1 +++ DefaultApplicationXml.java 15 Feb 2005 10:31:44 -0000 1.2 @@ -1,7 +1,7 @@ /* * ======================================================================== * - * Copyright 2003 The Apache Software Foundation. + * Copyright 2003-2005 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -51,6 +51,18 @@ */ private final Element rootElement; + /** + * Specifies the order in which the top-level elements must appear in the + * descriptor, according to the DTD. + */ + private static final ApplicationXmlTag[] ELEMENT_ORDER = { + ApplicationXmlTag.ICON, + ApplicationXmlTag.DISPLAY_NAME, + ApplicationXmlTag.DESCRIPTION, + ApplicationXmlTag.MODULE, + ApplicationXmlTag.SECURITY_ROLE + }; + // Constructors ------------------------------------------------------------ /** @@ -171,6 +183,23 @@ return elements.iterator(); } + /** + * @see ApplicationXml#addWebModule(String, String) + */ + public void addWebModule(String theUri, String theContext) + { + Element moduleElement = + this.document.createElement(ApplicationXmlTag.MODULE.getTagName()); + Element webElement = + this.document.createElement(ApplicationXmlTag.WEB.getTagName()); + webElement.appendChild( + createNestedText(ApplicationXmlTag.WEB_URI, theUri)); + webElement.appendChild( + createNestedText(ApplicationXmlTag.CONTEXT_ROOT, theContext)); + moduleElement.appendChild(webElement); + addElement(ApplicationXmlTag.MODULE, moduleElement); + } + // Private Methods --------------------------------------------------------- /** @@ -220,4 +249,69 @@ return null; } + /** + * Creates an element that contains nested text. + * + * @param theTag The tag to create an instance of + * @param theText The text that should be nested in the element + * @return The created DOM element + */ + private Element createNestedText(ApplicationXmlTag theTag, String theText) + { + Element element = this.document.createElement(theTag.getTagName()); + element.appendChild(this.document.createTextNode(theText)); + return element; + } + + /** + * Adds an element of the specified tag to the descriptor. + * + * @param theTag The descriptor tag + * @param theElement The element to add + */ + public final void addElement(ApplicationXmlTag theTag, Element theElement) + { + Node importedNode = this.document.importNode(theElement, true); + Node refNode = getInsertionPointFor(theTag); + this.rootElement.insertBefore(importedNode, refNode); + } + + /** + * Returns the node before which the specified tag should be inserted, or + * <code>null</code> if the node should be inserted at the end of the + * descriptor. + * + * @param theTag The tag that should be inserted + * @return The node before which the tag can be inserted + */ + private Node getInsertionPointFor(ApplicationXmlTag theTag) + { + for (int i = 0; i < ELEMENT_ORDER.length; i++) + { + if (ELEMENT_ORDER[i] == theTag) + { + for (int j = i + 1; j < ELEMENT_ORDER.length; j++) + { + NodeList elements = + this.rootElement.getElementsByTagName( + ELEMENT_ORDER[j].getTagName()); + if (elements.getLength() > 0) + { + Node result = elements.item(0); + Node previous = result.getPreviousSibling(); + while ((previous != null) + && ((previous.getNodeType() == Node.COMMENT_NODE) + || (previous.getNodeType() == Node.TEXT_NODE))) + { + result = previous; + previous = result.getPreviousSibling(); + } + return result; + } + } + break; + } + } + return null; + } } 1.1 jakarta-cactus/integration/ant/src/java/org/apache/cactus/integration/ant/CactifyEarTask.java Index: CactifyEarTask.java =================================================================== /* * ======================================================================== * * Copyright 2005 The Apache Software Foundation. * * Licensed 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 org.apache.cactus.integration.ant; import java.io.File; import java.io.IOException; import javax.xml.parsers.ParserConfigurationException; import org.apache.cactus.integration.ant.deployment.application.ApplicationXml; import org.apache.cactus.integration.ant.deployment.application.ApplicationXmlIo; import org.apache.cactus.integration.ant.deployment.application.DefaultEarArchive; import org.apache.cactus.integration.ant.deployment.application.EarArchive; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.taskdefs.Ear; import org.apache.tools.ant.types.ZipFileSet; import org.apache.tools.ant.util.FileUtils; import org.xml.sax.SAXException; /** * An Ant task that injects elements necessary to run Cactus tests into an * existing EAR file. * * @version $Id: CactifyEarTask.java,v 1.1 2005/02/15 10:31:44 vmassol Exp $ */ public class CactifyEarTask extends Ear { /** * Cactus war configuration holder */ private CactusWar cactusWar; /** * The archive that contains the web-app that should be cactified. */ private File srcFile; /** * * @param theCactusWar CactusWar to set */ public void addConfiguredCactuswar(CactusWar theCactusWar) { cactusWar = theCactusWar; } /** * @param theSrcFile The srcFile to set. */ public void setSrcFile(File theSrcFile) { srcFile = theSrcFile; } /** * @see org.apache.tools.ant.Task#execute() */ public void execute() throws BuildException { if (cactusWar == null) { cactusWar = createCactusWarConfig(); } //Add everything that's in the source EAR to the destination EAR ZipFileSet currentFiles = new ZipFileSet(); currentFiles.setSrc(this.srcFile); currentFiles.createExclude().setName("META-INF/application.xml"); addZipfileset(currentFiles); // cactify the application.xml ApplicationXml appXml = getOriginalApplicationXml(); File tmpAppXml = cactifyApplicationXml(appXml); setAppxml(tmpAppXml); // create the cactus war File cactusWarFile = createCactusWar(); addFileToEar(cactusWarFile, cactusWar.getFileName()); super.execute(); } /** * * @return the application.xml from the source ear */ private ApplicationXml getOriginalApplicationXml() { ApplicationXml appXml = null; try { EarArchive ear = new DefaultEarArchive(this.srcFile); appXml = ear.getApplicationXml(); if (appXml == null) { throw new BuildException("The EAR source file does not " + "contain a META-INF/application.xml " + "deployment descriptor"); } } catch (SAXException e) { throw new BuildException( "Parsing of application.xml deployment descriptor failed", e); } catch (IOException e) { throw new BuildException("Failed to open EAR", e); } catch (ParserConfigurationException e) { throw new BuildException("XML parser configuration error", e); } return appXml; } /** * * @param theAppXml the application.xml to cactify * @return the cactified application.xml */ private File cactifyApplicationXml(ApplicationXml theAppXml) { theAppXml.addWebModule(cactusWar.getFileName(), cactusWar.getContext()); // serialize the cactified app xml FileUtils fileUtils = FileUtils.newFileUtils(); File tmpAppXml = fileUtils.createTempFile("cactus", "application.xml", getProject().getBaseDir()); tmpAppXml.deleteOnExit(); try { ApplicationXmlIo.writeApplicationXml(theAppXml, tmpAppXml, null, true); } catch (IOException ioe) { throw new BuildException( "Could not write temporary deployment descriptor", ioe); } return tmpAppXml; } /** * * @return the cactus.war */ private File createCactusWar() { FileUtils fileUtils = FileUtils.newFileUtils(); File tmpCactusWar = fileUtils.createTempFile("cactus", "cactus.war", getProject().getBaseDir()); tmpCactusWar.deleteOnExit(); cactusWar.setDestFile(tmpCactusWar); cactusWar.execute(); return tmpCactusWar; } /** * * @param theFile the file to add * @param theFullPath the path within the ear */ private void addFileToEar(File theFile, String theFullPath) { ZipFileSet fs = new ZipFileSet(); fs.setFile(theFile); fs.setFullpath(theFullPath); addZipfileset(fs); } /** * Initialize cactusWar with some default values. * * @return the CactusWar configuration */ private CactusWar createCactusWarConfig() { CactusWar cactusWarConfig = new CactusWar(); CactusWar.Version version = new CactusWar.Version(); version.setValue("2.3"); cactusWarConfig.setVersion(version); cactusWarConfig.setContext("/cactus"); cactusWarConfig.setProject(getProject()); return cactusWarConfig; } } 1.1 jakarta-cactus/integration/ant/src/java/org/apache/cactus/integration/ant/CactusWar.java Index: CactusWar.java =================================================================== /* * ======================================================================== * * Copyright 2005 The Apache Software Foundation. * * Licensed 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 org.apache.cactus.integration.ant; /** * * * * @version $Id: CactusWar.java,v 1.1 2005/02/15 10:31:44 vmassol Exp $ */ public class CactusWar extends CactifyWarTask { /** * Name of the generated web app file */ private static final String FILE_NAME = "cactus.war"; /** * Context of the cactus web application */ private String context; /** * @return Returns the context. */ public String getContext() { return context; } /** * @param theContext The context to set. */ public void setContext(String theContext) { context = theContext; } /** * * @return the name of the web app file */ public String getFileName() { return FILE_NAME; } } 1.1 jakarta-cactus/integration/ant/src/test-input/org/apache/cactus/integration/ant/test-cactifyear.xml Index: test-cactifyear.xml =================================================================== <?xml version="1.0"?> <project name="test-cactifyear" basedir="." default="help"> <property name="work.dir" location="${basedir}/work"/> <target name="setUp"> <mkdir dir="${work.dir}"/> </target> <target name="testCanAddCactifiedWar"> <cactifyear srcfile="empty.ear" destfile="${work.dir}/cactified.ear"/> </target> <target name="testCustomCactusWarContext"> <cactifyear srcfile="empty.ear" destfile="${work.dir}/cactified.ear"> <cactuswar context="/myTestFramework" version="2.3"/> </cactifyear> </target> <target name="tearDown"> <delete dir="${work.dir}"/> </target> </project> 1.1 jakarta-cactus/integration/ant/src/test/org/apache/cactus/integration/ant/TestCactifyEarTask.java Index: TestCactifyEarTask.java =================================================================== /* * ======================================================================== * * Copyright 2005 The Apache Software Foundation. * * Licensed 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 org.apache.cactus.integration.ant; import java.io.File; import org.apache.cactus.integration.ant.deployment.application.ApplicationXml; import org.apache.cactus.integration.ant.deployment.application.DefaultEarArchive; import org.apache.cactus.integration.ant.deployment.application.EarArchive; import org.apache.cactus.integration.ant.deployment.webapp.WarArchive; import org.apache.cactus.integration.ant.deployment.webapp.WebXml; /** * Test class for the CactifyEar task. * * @version $Id: TestCactifyEarTask.java,v 1.1 2005/02/15 10:31:44 vmassol Exp $ */ public class TestCactifyEarTask extends AntTestCase { /** * @see AntTestCase#AntTestCase */ public TestCactifyEarTask() { super("org/apache/cactus/integration/ant/test-cactifyear.xml"); } /** * @see junit.framework.TestCase#setUp() */ protected void setUp() throws Exception { super.setUp(); getProject().addTaskDefinition("cactifyear", CactifyEarTask.class); } /** * Tests that the basic function of the task works, * that is to add a cactified war to the ear. * * @throws Exception If an unexpected error occurs */ public void testCanAddCactifiedWar() throws Exception { executeTestTarget(); File destFile = getProject().resolveFile("work/cactified.ear"); EarArchive destEar = new DefaultEarArchive(destFile); ApplicationXml appXml = destEar.getApplicationXml(); assertEquals("/cactus", appXml.getWebModuleContextRoot("cactus.war")); WarArchive cactusWar = destEar.getWebModule("cactus.war"); WebXml webXml = cactusWar.getWebXml(); assertNotNull(webXml.getServlet("ServletRedirector")); } /** * Tests that the context of the cactus.war can be specified. * * @throws Exception If an unexpected error occurs */ public void testCustomCactusWarContext() throws Exception { executeTestTarget(); File destFile = getProject().resolveFile("work/cactified.ear"); EarArchive destEar = new DefaultEarArchive(destFile); ApplicationXml appXml = destEar.getApplicationXml(); assertEquals("/myTestFramework", appXml.getWebModuleContextRoot("cactus.war")); } }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]