Index: lams_tool_deploy/src/java/org/lamsfoundation/lams/tool/deploy/InsertContextWebXmlTask.java =================================================================== RCS file: /usr/local/cvsroot/lams_tool_deploy/src/java/org/lamsfoundation/lams/tool/deploy/Attic/InsertContextWebXmlTask.java,v diff -u -r1.1 -r1.2 --- lams_tool_deploy/src/java/org/lamsfoundation/lams/tool/deploy/InsertContextWebXmlTask.java 13 Apr 2006 00:09:51 -0000 1.1 +++ lams_tool_deploy/src/java/org/lamsfoundation/lams/tool/deploy/InsertContextWebXmlTask.java 13 Apr 2006 04:25:03 -0000 1.2 @@ -38,13 +38,7 @@ public class InsertContextWebXmlTask extends UpdateWebXmlTask { - /** Creates a new instance of InsertContextWebXmlTask */ - public InsertContextWebXmlTask(final String applicationContextPath, final String lamsEarPath, final String centralWebXmlPath, - final String learningWebXmlPath, final String monitoringWebXmlPath) { - super(applicationContextPath, lamsEarPath, centralWebXmlPath, learningWebXmlPath, monitoringWebXmlPath ); - } - - /** + /** * Update the param-value node of the context-param entry. Don't add it if it already exists. * @param doc * @param children Index: lams_tool_deploy/src/java/org/lamsfoundation/lams/tool/deploy/RemoveContextWebXmlTask.java =================================================================== RCS file: /usr/local/cvsroot/lams_tool_deploy/src/java/org/lamsfoundation/lams/tool/deploy/Attic/RemoveContextWebXmlTask.java,v diff -u -r1.1 -r1.2 --- lams_tool_deploy/src/java/org/lamsfoundation/lams/tool/deploy/RemoveContextWebXmlTask.java 13 Apr 2006 00:09:52 -0000 1.1 +++ lams_tool_deploy/src/java/org/lamsfoundation/lams/tool/deploy/RemoveContextWebXmlTask.java 13 Apr 2006 04:25:03 -0000 1.2 @@ -26,9 +26,7 @@ import org.apache.commons.lang.StringUtils; -import org.w3c.dom.Comment; import org.w3c.dom.Document; -import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Text; @@ -41,14 +39,7 @@ public class RemoveContextWebXmlTask extends UpdateWebXmlTask { - /** Creates a new instance of InsertContextWebXmlTask */ - public RemoveContextWebXmlTask(final String applicationContextPath, final String lamsEarPath, final String centralWebXmlPath, - final String learningWebXmlPath, final String monitoringWebXmlPath) { - super(applicationContextPath, lamsEarPath, centralWebXmlPath, learningWebXmlPath, monitoringWebXmlPath ); - } - - - /** + /** * Remove the tool's applicationContext entry from the param-value node of the context-param entry. * Should find and remove all the matching entries (should it somehow have have got in there m * @param doc Index: lams_tool_deploy/src/java/org/lamsfoundation/lams/tool/deploy/UpdateWebXmlTask.java =================================================================== RCS file: /usr/local/cvsroot/lams_tool_deploy/src/java/org/lamsfoundation/lams/tool/deploy/Attic/UpdateWebXmlTask.java,v diff -u -r1.3 -r1.4 --- lams_tool_deploy/src/java/org/lamsfoundation/lams/tool/deploy/UpdateWebXmlTask.java 13 Apr 2006 00:09:53 -0000 1.3 +++ lams_tool_deploy/src/java/org/lamsfoundation/lams/tool/deploy/UpdateWebXmlTask.java 13 Apr 2006 04:25:03 -0000 1.4 @@ -25,7 +25,23 @@ package org.lamsfoundation.lams.tool.deploy; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +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 java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.zip.Deflater; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -36,7 +52,6 @@ import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; -import org.apache.commons.lang.StringUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -50,7 +65,9 @@ */ public abstract class UpdateWebXmlTask implements Task { - + private static final int BUFFER_SIZE = 8192; + protected static final String WEBXML_PATH = "WEB-INF/web.xml"; + /** * The lams.ear path file. */ @@ -64,22 +81,8 @@ */ protected String applicationContextPath; - private String centralWebXmlPath; - private String learningWebXmlPath; - private String monitoringWebXmlPath; + private List warsToUpdate; - /** Creates a new instance of UpdateApplicationXmlTask */ - public UpdateWebXmlTask(final String applicationContextURI, final String lamsEarPath, final String centralWebXmlPath, - final String learningWebXmlPath, final String monitoringWebXmlPath) - { - this.applicationContextPath = applicationContextURI; - this.lamsEarPath = lamsEarPath; - this.centralWebXmlPath = centralWebXmlPath; - this.learningWebXmlPath = learningWebXmlPath; - this.monitoringWebXmlPath = monitoringWebXmlPath; - } - - /** * Sets the location of the application xml file to be modified. * @param appxml New value of property appxml. @@ -99,34 +102,150 @@ throw new DeployException("UpdateWebXmTask: Unable to update web.xml as the application content path is missing (applicationContextPath)."); } - Document doc = null; - - if ( centralWebXmlPath!=null && ! StringUtils.isEmpty(centralWebXmlPath) ) { - doc = parseWebXml(centralWebXmlPath); - updateWebXml(doc, centralWebXmlPath); - writeWebXml(doc, centralWebXmlPath); - } - - if ( learningWebXmlPath!=null && ! StringUtils.isEmpty(learningWebXmlPath) ) { - doc = parseWebXml(learningWebXmlPath); - updateWebXml(doc, learningWebXmlPath); - writeWebXml(doc, learningWebXmlPath); - } + if ( warsToUpdate != null ) { + + // map the old File to the new File e.g. lams_learning.war is the key, lams_learning.war.new is the value + Map filesToRename = new HashMap(warsToUpdate.size()); + + for ( String warFileName: warsToUpdate ) { + + File warFile = new File(warFileName); + if ( ! warFile.canRead() || warFile.isDirectory() ) { + throw new DeployException("Unable to access war file "+warFileName+". May be missing, a directory or not readable"); + } + String newFilename = lamsEarPath+warFileName+".new"; + File outputFile = new File(newFilename); + ZipOutputStream newWarOutputStream = null; + ZipInputStream warInputStream = null; + try { + + newWarOutputStream = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(outputFile))); + newWarOutputStream.setMethod(ZipOutputStream.DEFLATED); + newWarOutputStream.setLevel(Deflater.DEFAULT_COMPRESSION); + //newWarOutputStream.setMethod(ZipOutputStream.STORED); - if ( monitoringWebXmlPath!=null && ! StringUtils.isEmpty(monitoringWebXmlPath) ) { - doc = parseWebXml(monitoringWebXmlPath); - updateWebXml(doc, monitoringWebXmlPath); - writeWebXml(doc, monitoringWebXmlPath); - } + warInputStream = new ZipInputStream(new BufferedInputStream(new FileInputStream(warFile))); + ZipEntry entry = null; + + // work through each entry, copying across to the output stream. + // when we hit the web.xml, we have to modify it. + while( ( entry = warInputStream.getNextEntry() ) != null ) { + processEntry(newWarOutputStream, warInputStream, entry); + } + + warInputStream.close(); + newWarOutputStream.close(); + + } catch (IOException e) { + throw new DeployException("Unable to process war file "+warFileName,e); + } finally { + try { + if ( warInputStream != null ) + warInputStream.close(); + if ( newWarOutputStream != null ) + newWarOutputStream.close(); + } catch ( IOException e2 ) {} + } + + filesToRename.put(warFile, outputFile); + } + + copyNewFilesToOldNames(filesToRename); + } + } - - protected void updateWebXml(Document doc, String documentPath) throws DeployException + + /** + * Everything worked okay so rename the files + * @param filesToRename + */ + private void copyNewFilesToOldNames(Map filesToRename) throws DeployException { + for ( Map.Entry mapEntry : filesToRename.entrySet() ) { + Map renamed = new HashMap(warsToUpdate.size()); + + File origFile = mapEntry.getKey(); + File backup = new File ( origFile.getAbsoluteFile() + ".bak"); + boolean successful = origFile.renameTo(backup); + if ( successful ) { + renamed.put(origFile, backup); + successful = mapEntry.getValue().renameTo(origFile); + } + + if ( successful ) { + System.out.println("Updated web.xml in war file "+origFile.getName()); + + } else { + for ( Map.Entry renamedMapEntry : renamed.entrySet() ) { + File updatedFile = renamedMapEntry.getKey(); + File backupFile = renamedMapEntry.getValue(); + backupFile.renameTo(updatedFile); + } + String message = "Error occured renaming the war files. Tried to go back to old files but may or may not have succeeded. Check files:"; + for ( String warFileName: warsToUpdate ) { + message += " " + warFileName; + } + throw new DeployException(message); + } + + } + } + + /** + * @param newWarOutputStream + * @param warInputStream + * @param entry + * @throws IOException + */ + private void processEntry(ZipOutputStream newWarOutputStream, ZipInputStream warInputStream, ZipEntry entry) throws IOException { + + if ( entry.getName().equals(WEBXML_PATH) ) { + + ZipEntry newEntry = new ZipEntry(WEBXML_PATH); + newWarOutputStream.putNextEntry(newEntry); + + // can't just pass the stream to the parser, as the parser will close the stream. + InputStream copyInputStream = copyToByteArrayInputStream(warInputStream); + + Document doc = parseWebXml(copyInputStream); + updateWebXml(doc); + writeWebXml(doc, newWarOutputStream); + + } else { + + ZipEntry newEntry = new ZipEntry(entry.getName()); + newWarOutputStream.putNextEntry(newEntry); + + byte[] data = new byte[ BUFFER_SIZE ]; + int count = -1; + while( (count = warInputStream.read( data, 0, BUFFER_SIZE ) ) != -1 ) + { + newWarOutputStream.write( data, 0, count ); + } + } + + newWarOutputStream.closeEntry(); + } + + private ByteArrayInputStream copyToByteArrayInputStream(ZipInputStream warInputStream) throws IOException { + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + byte[] data = new byte[ BUFFER_SIZE ]; + int count = -1; + while( (count = warInputStream.read( data, 0, BUFFER_SIZE ) ) != -1 ) + { + os.write( data, 0, count ); + } + os.close(); + + return new ByteArrayInputStream(os.toByteArray()); + } + protected void updateWebXml(Document doc) throws DeployException { NodeList contextParamNodeList = doc.getElementsByTagName("context-param"); Element matchingContextParamElement = findContextParamWithMatchingParamName("contextConfigLocation", contextParamNodeList); if ( matchingContextParamElement == null ) { - throw new DeployException("No contextConfigLocation can be found in the file "+documentPath); + throw new DeployException("No contextConfigLocation can be found in the web.xml in the war"); } NodeList contextParamElements = matchingContextParamElement.getChildNodes(); @@ -145,11 +264,11 @@ protected abstract void updateValue(Document doc, Node contextParamElement) throws DeployException; /** - * Writes the modified web.xml back out to the file system. + * Writes the modified web.xml back out to war file * @param doc The application.xml DOM Document * @throws org.apache.tools.ant.DeployException in case of any problems */ - protected void writeWebXml(final Document doc, final String webXmlPath) throws DeployException + protected void writeWebXml(final Document doc, final OutputStream outputStream) throws DeployException { try { @@ -159,7 +278,7 @@ DOMSource source = new DOMSource(doc); // Prepare the output file - StreamResult result = new StreamResult(webXmlPath); + StreamResult result = new StreamResult(outputStream); // Write the DOM document to the file // Get Transformer @@ -169,7 +288,7 @@ } catch (TransformerException tex) { - throw new DeployException("Error writing out modified web xml "+webXmlPath, tex); + throw new DeployException("Error writing out modified web xml ", tex); } } @@ -179,7 +298,7 @@ * @throws org.apache.tools.ant.DeployException in case of errors * @return A DOM Document of the web xml */ - protected Document parseWebXml(final String webXmlPath) throws DeployException + protected Document parseWebXml(final InputStream webXmlPath) throws DeployException { try { @@ -278,35 +397,13 @@ this.applicationContextPath = applicationContextPath; } - - public String getCentralWebXmlPath() { - return centralWebXmlPath; + public List getWarsToUpdate() { + return warsToUpdate; } - - public void setCentralWebXmlPath(String centralWebXmlPath) { - this.centralWebXmlPath = centralWebXmlPath; + public void setWarsToUpdate(List warsToUpdate) { + this.warsToUpdate = warsToUpdate; } - - - public String getLearningWebXmlPath() { - return learningWebXmlPath; - } - - - public void setLearningWebXmlPath(String learningWebXmlPath) { - this.learningWebXmlPath = learningWebXmlPath; - } - - - public String getMonitoringWebXmlPath() { - return monitoringWebXmlPath; - } - - - public void setMonitoringWebXmlPath(String monitoringWebXmlPath) { - this.monitoringWebXmlPath = monitoringWebXmlPath; - } } Index: lams_tool_deploy/test/java/org/lamsfoundation/lams/tool/deploy/TestUpdateWebXmlTask.java =================================================================== RCS file: /usr/local/cvsroot/lams_tool_deploy/test/java/org/lamsfoundation/lams/tool/deploy/Attic/TestUpdateWebXmlTask.java,v diff -u -r1.2 -r1.3 --- lams_tool_deploy/test/java/org/lamsfoundation/lams/tool/deploy/TestUpdateWebXmlTask.java 13 Apr 2006 00:09:53 -0000 1.2 +++ lams_tool_deploy/test/java/org/lamsfoundation/lams/tool/deploy/TestUpdateWebXmlTask.java 13 Apr 2006 04:25:03 -0000 1.3 @@ -24,58 +24,112 @@ package org.lamsfoundation.lams.tool.deploy; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.LinkedList; +import java.util.List; -public class TestUpdateWebXmlTask extends ToolDBTest { +import junit.framework.TestCase; - public TestUpdateWebXmlTask(String testName) - { - super(testName); - } +import org.w3c.dom.Document; - protected void setUp() throws java.lang.Exception - { - super.setUp(); - } - protected void tearDown() throws java.lang.Exception - { - super.tearDown(); - } +public class TestUpdateWebXmlTask extends TestCase { + public static final String dummyWarNoNBEntryPath = "test/file/test-dummy.war"; + public static final String dummyWarNBEntryPath = "test/file/test-dummy-with-nb.war"; + + public TestUpdateWebXmlTask(String testName) + { + super(testName); + } + + protected void setUp() throws java.lang.Exception + { + super.setUp(); + } + + protected void tearDown() throws java.lang.Exception + { + super.tearDown(); + } + public void testInsertExecute() throws Exception { - InsertContextWebXmlTask task = new InsertContextWebXmlTask("/org/lamsfoundation/lams/tool/noticeboard/applicationContext.xml",null,"test/file/web.xml",null,null); - task.execute(); + InsertContextWebXmlTask task = new InsertContextWebXmlTask(); + webXmlFileTest(task, "test/file/web.xml"); + } public void testInsertEntryAlreadyExistsExecute() throws Exception { - InsertContextWebXmlTask task = new InsertContextWebXmlTask("/org/lamsfoundation/lams/tool/noticeboard/applicationContext.xml",null,"test/file/web1EntryInsert.xml",null,null); - task.execute(); + InsertContextWebXmlTask task = new InsertContextWebXmlTask(); + webXmlFileTest(task, "test/file/web1EntryInsert.xml"); } public void testRemoveExecuteNoEntry() throws Exception { // tests removing it from the end of the list of contexts - RemoveContextWebXmlTask task = new RemoveContextWebXmlTask("/org/lamsfoundation/lams/tool/noticeboard/applicationContext.xml", - null,"test/file/webNoEntry.xml",null,null); - task.execute(); + RemoveContextWebXmlTask task = new RemoveContextWebXmlTask(); + webXmlFileTest(task, "test/file/webNoEntry.xml"); } public void testRemoveExecuteEnd() throws Exception { // tests removing it from the end of the list of contexts - RemoveContextWebXmlTask task = new RemoveContextWebXmlTask("/org/lamsfoundation/lams/tool/noticeboard/applicationContext.xml", - null,"test/file/web1Entry.xml",null,null); - task.execute(); + RemoveContextWebXmlTask task = new RemoveContextWebXmlTask(); + webXmlFileTest(task, "test/file/web1Entry.xml"); } public void testRemoveExecuteBeginMidEnd() throws Exception { // tests removing it from the beginning and middle of the list of contexts - RemoveContextWebXmlTask task = new RemoveContextWebXmlTask("/org/lamsfoundation/lams/tool/noticeboard/applicationContext.xml", - null,"test/file/web3Entry.xml",null,null); - task.execute(); + RemoveContextWebXmlTask task = new RemoveContextWebXmlTask(); + webXmlFileTest(task, "test/file/web3Entry.xml"); } + /** + * @param filename + * @return + * @throws FileNotFoundException + * @throws IOException + */ + private void webXmlFileTest(UpdateWebXmlTask task, String filename) throws FileNotFoundException, IOException { + + task.setApplicationContextPath("/org/lamsfoundation/lams/tool/noticeboard/applicationContext.xml"); + + InputStream is = new FileInputStream(filename); + Document doc = task.parseWebXml(is); + is.close(); + task.updateWebXml(doc); + OutputStream os = new FileOutputStream(filename+".new"); + task.writeWebXml(doc, os); + os.close(); + } + + public void testAddToWar() throws Exception + { + InsertContextWebXmlTask task = new InsertContextWebXmlTask(); + task.setApplicationContextPath("/org/lamsfoundation/lams/tool/noticeboard/applicationContext.xml"); + List warFiles = new LinkedList(); + warFiles.add(dummyWarNoNBEntryPath); + task.setWarsToUpdate(warFiles); + task.setLamsEarPath(""); + task.execute(); + } + + public void testRemoveFromToWar() throws Exception + { + RemoveContextWebXmlTask task = new RemoveContextWebXmlTask(); + task.setApplicationContextPath("/org/lamsfoundation/lams/tool/noticeboard/applicationContext.xml"); + List warFiles = new LinkedList(); + warFiles.add(dummyWarNBEntryPath); + task.setWarsToUpdate(warFiles); + task.setLamsEarPath(""); + task.execute(); + } } \ No newline at end of file