You are viewing a plain text version of this content. The canonical link for it is here.
Posted to pluto-scm@portals.apache.org by dd...@apache.org on 2007/03/03 03:49:05 UTC

svn commit: r514060 - in /portals/pluto/trunk: ./ pluto-ant-tasks/src/main/java/org/apache/pluto/ant/ pluto-util/ pluto-util/src/main/java/org/apache/pluto/util/assemble/ pluto-util/src/main/java/org/apache/pluto/util/assemble/file/ pluto-util/src/main...

Author: ddewolf
Date: Fri Mar  2 18:49:04 2007
New Revision: 514060

URL: http://svn.apache.org/viewvc?view=rev&rev=514060
Log:
PLUTO-314: Thanks to Eric Dalquist, enhancing the assembler

Added:
    portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/WebXmlRewritingAssembler.java   (with props)
    portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/war/
    portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/war/WarAssembler.java   (with props)
    portals/pluto/trunk/pluto-util/src/test/
    portals/pluto/trunk/pluto-util/src/test/java/
    portals/pluto/trunk/pluto-util/src/test/java/org/
    portals/pluto/trunk/pluto-util/src/test/java/org/apache/
    portals/pluto/trunk/pluto-util/src/test/java/org/apache/pluto/
    portals/pluto/trunk/pluto-util/src/test/java/org/apache/pluto/util/
    portals/pluto/trunk/pluto-util/src/test/java/org/apache/pluto/util/assemble/
    portals/pluto/trunk/pluto-util/src/test/java/org/apache/pluto/util/assemble/file/
    portals/pluto/trunk/pluto-util/src/test/java/org/apache/pluto/util/assemble/file/FileAssemblerTest.java   (with props)
    portals/pluto/trunk/pluto-util/src/test/java/org/apache/pluto/util/assemble/war/
    portals/pluto/trunk/pluto-util/src/test/java/org/apache/pluto/util/assemble/war/WarAssemblerTest.java   (with props)
    portals/pluto/trunk/pluto-util/src/test/resources/
    portals/pluto/trunk/pluto-util/src/test/resources/org/
    portals/pluto/trunk/pluto-util/src/test/resources/org/apache/
    portals/pluto/trunk/pluto-util/src/test/resources/org/apache/pluto/
    portals/pluto/trunk/pluto-util/src/test/resources/org/apache/pluto/util/
    portals/pluto/trunk/pluto-util/src/test/resources/org/apache/pluto/util/assemble/
    portals/pluto/trunk/pluto-util/src/test/resources/org/apache/pluto/util/assemble/file/
    portals/pluto/trunk/pluto-util/src/test/resources/org/apache/pluto/util/assemble/file/assembled.web.xml   (with props)
    portals/pluto/trunk/pluto-util/src/test/resources/org/apache/pluto/util/assemble/file/portlet.xml   (with props)
    portals/pluto/trunk/pluto-util/src/test/resources/org/apache/pluto/util/assemble/file/web.xml   (with props)
Modified:
    portals/pluto/trunk/pluto-ant-tasks/src/main/java/org/apache/pluto/ant/AssembleTask.java
    portals/pluto/trunk/pluto-util/pom.xml
    portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/AssemblerConfig.java
    portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/AssemblerFactory.java
    portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/file/FileAssembler.java
    portals/pluto/trunk/pom.xml

Modified: portals/pluto/trunk/pluto-ant-tasks/src/main/java/org/apache/pluto/ant/AssembleTask.java
URL: http://svn.apache.org/viewvc/portals/pluto/trunk/pluto-ant-tasks/src/main/java/org/apache/pluto/ant/AssembleTask.java?view=diff&rev=514060&r1=514059&r2=514060
==============================================================================
--- portals/pluto/trunk/pluto-ant-tasks/src/main/java/org/apache/pluto/ant/AssembleTask.java (original)
+++ portals/pluto/trunk/pluto-ant-tasks/src/main/java/org/apache/pluto/ant/AssembleTask.java Fri Mar  2 18:49:04 2007
@@ -16,14 +16,19 @@
  */
 package org.apache.pluto.ant;
 
-import org.apache.tools.ant.Task;
-import org.apache.tools.ant.BuildException;
+import java.io.File;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+
 import org.apache.pluto.util.UtilityException;
 import org.apache.pluto.util.assemble.Assembler;
-import org.apache.pluto.util.assemble.AssemblerFactory;
 import org.apache.pluto.util.assemble.AssemblerConfig;
-
-import java.io.File;
+import org.apache.pluto.util.assemble.AssemblerFactory;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.DirectoryScanner;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.FileSet;
 
 /**
  * TODO JavaDoc
@@ -41,6 +46,12 @@
     private File destfile;
 
     private File webapp;
+    
+    private File war;
+    
+    private File destdir;
+    
+    private Collection warFileSets = new LinkedList();
 
     public File getPortletxml() {
         if(webapp != null)
@@ -79,21 +90,76 @@
     public void setWebapp(File webapp) {
         this.webapp = webapp;
     }
+    
+    public File getWar() {
+        return this.war;
+    }
+
+    public void setWar(File war) {
+        this.war = war;
+    }
+
+    public File getDestdir() {
+        if (destdir == null) {
+            return (war != null ? war.getParentFile() : null);
+        }
+        return this.destdir;
+    }
+
+    public void setDestdir(File destDir) {
+        this.destdir = destDir;
+    }
+    
+    public void addWars(FileSet fileSet) {
+        this.warFileSets.add(fileSet);
+    }
 
     public void execute() throws BuildException {
 
         validateArgs();
 
         try {
-            AssemblerConfig config = new AssemblerConfig();
-            config.setPortletDescriptor(getPortletxml());
-            config.setWebappDescriptor(getWebxml());
-            config.setDestination(getDestfile());
-
-            Assembler assembler =
-                AssemblerFactory.getFactory().createAssembler(config);
-
-           assembler.assemble(config);
+            if (this.warFileSets.size() > 0) {
+                for (final Iterator fileSetItr = this.warFileSets.iterator(); fileSetItr.hasNext();) {
+                    final FileSet fileSet = (FileSet)fileSetItr.next();
+                    final DirectoryScanner directoryScanner = fileSet.getDirectoryScanner(this.getProject());
+                    
+                    final File basedir = directoryScanner.getBasedir();
+                    final String[] includedFiles = directoryScanner.getIncludedFiles();
+                    
+                    for (int index = 0; index < includedFiles.length; index++) {
+                        AssemblerConfig config = new AssemblerConfig();
+                        
+                        final File warSource = new File(basedir, includedFiles[index]);
+                        config.setWarSource(warSource);
+                        config.setDestination(getDestdir());
+                        
+                        this.log("Assembling '" + warSource + "' to '" + getDestdir() + "'");
+                        Assembler assembler = AssemblerFactory.getFactory().createAssembler(config);
+                        assembler.assemble(config);
+                    }
+                }
+            }
+            else {
+                AssemblerConfig config = new AssemblerConfig();
+    
+                final File warSource = getWar();
+                if (warSource != null) {
+                    config.setWarSource(warSource);
+                    config.setDestination(getDestdir());
+                    this.log("Assembling '" + warSource + "' to '" + getDestdir() + "'");
+                }
+                else {
+                    config.setPortletDescriptor(getPortletxml());
+                    config.setWebappDescriptor(getWebxml());
+                    config.setDestination(getDestfile());
+                    this.log("Assembling '" + getWebxml() + "' to '" + getDestfile() + "'");
+                }
+                
+    
+                Assembler assembler = AssemblerFactory.getFactory().createAssembler(config);
+                assembler.assemble(config);
+            }
         }
 
         catch(UtilityException ue) {
@@ -102,19 +168,86 @@
     }
 
     private void validateArgs() throws BuildException {
+        //Check if running with webapp arg
         if(webapp != null) {
             if(!webapp.exists()) {
                throw new BuildException("webapp "+webapp.getAbsolutePath()+ " does not exist");
             }
+            
+            if (war != null) {
+                throw new BuildException("war should not be specified if webapp is specified");
+            }
+            if (this.warFileSets.size() > 0) {
+                throw new BuildException("wars should not be specified if webapp is specified");
+            }
+            if (destdir != null) {
+                throw new BuildException("destfile should not be specified if webapp is specified");
+            }
+            
             return;
         }
+        
+        //Check if running with war arg
+        if (war != null) {
+            if(!war.exists()) {
+                throw new BuildException("WAR "+war.getAbsolutePath()+ " does not exist");
+            }
+            
+            if (this.warFileSets.size() > 0) {
+                throw new BuildException("wars should not be specified if war is specified");
+            }
+            if (webapp != null) {
+                throw new BuildException("webapp should not be specified if war is specified");
+            }
+            if (destfile != null) {
+                throw new BuildException("destfile should not be specified if war is specified");
+            }
+            if (portletxml != null) {
+                throw new BuildException("portletxml should not be specified if war is specified");
+            }
+            if (webxml != null) {
+                throw new BuildException("webxml should not be specified if war is specified");
+            }
 
+            return;
+        }
+        
+        //Check if running with war arg
+        if (this.warFileSets.size() > 0) {
+            if (war != null) {
+                throw new BuildException("wars should not be specified if war is specified");
+            }
+            if (webapp != null) {
+                throw new BuildException("webapp should not be specified if war is specified");
+            }
+            if (destfile != null) {
+                throw new BuildException("destfile should not be specified if war is specified");
+            }
+            if (portletxml != null) {
+                throw new BuildException("portletxml should not be specified if war is specified");
+            }
+            if (webxml != null) {
+                throw new BuildException("webxml should not be specified if war is specified");
+            }
+
+            return;
+        }
+
+        //Check if running with portletxml && webxml args
         if(portletxml == null || !portletxml.exists()) {
             throw new BuildException("portletxml "+portletxml+" does not exist");
         }
-
         if(webxml == null || !webxml.exists()) {
             throw new BuildException("webxml "+webxml + " does not exist");
+        }
+        if (war != null) {
+            throw new BuildException("war should not be specified if portletxml and webxml are aspecified");
+        }
+        if (this.warFileSets.size() > 0) {
+            throw new BuildException("wars should not be specified if portletxml and webxml are aspecified");
+        }
+        if (destdir != null) {
+            throw new BuildException("destfile should not be specified if portletxml and webxml are aspecified");
         }
     }
 }

Modified: portals/pluto/trunk/pluto-util/pom.xml
URL: http://svn.apache.org/viewvc/portals/pluto/trunk/pluto-util/pom.xml?view=diff&rev=514060&r1=514059&r2=514060
==============================================================================
--- portals/pluto/trunk/pluto-util/pom.xml (original)
+++ portals/pluto/trunk/pluto-util/pom.xml Fri Mar  2 18:49:04 2007
@@ -58,6 +58,17 @@
       <artifactId>commons-logging</artifactId>
       <version>${commons-logging.version}</version>
     </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+      <version>${commons-io.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>xmlunit</groupId>
+      <artifactId>xmlunit</artifactId>
+      <version>${xmlunit.version}</version>
+      <scope>test</scope>
+    </dependency>
     
   </dependencies>
 

Modified: portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/AssemblerConfig.java
URL: http://svn.apache.org/viewvc/portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/AssemblerConfig.java?view=diff&rev=514060&r1=514059&r2=514060
==============================================================================
--- portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/AssemblerConfig.java (original)
+++ portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/AssemblerConfig.java Fri Mar  2 18:49:04 2007
@@ -38,6 +38,9 @@
     /** The class of the servlet that will handle portlet requests */
     private String dispatchServletClass = null;
     
+    /** A source WAR archive to assemble */
+    private File warSource = null;
+    
     // Public Methods ----------------------------------------------------------
     
     public File getPortletDescriptor() {
@@ -62,7 +65,6 @@
     
     public void setDestination(File destination) {
         this.destination = destination;
-        this.destination.getParentFile().mkdirs();
     }
 
     public String getDispatchServletClass() {
@@ -71,5 +73,13 @@
 
     public void setDispatchServletClass(String dispatchServletClass) {
         this.dispatchServletClass = dispatchServletClass;
+    }
+
+    public File getWarSource() {
+        return this.warSource;
+    }
+
+    public void setWarSource(File warSource) {
+        this.warSource = warSource;
     }
 }

Modified: portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/AssemblerFactory.java
URL: http://svn.apache.org/viewvc/portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/AssemblerFactory.java?view=diff&rev=514060&r1=514059&r2=514060
==============================================================================
--- portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/AssemblerFactory.java (original)
+++ portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/AssemblerFactory.java Fri Mar  2 18:49:04 2007
@@ -17,6 +17,7 @@
 package org.apache.pluto.util.assemble;
 
 import org.apache.pluto.util.assemble.file.FileAssembler;
+import org.apache.pluto.util.assemble.war.WarAssembler;
 
 /**
  * The pluto assembler factory that creates an assembler. 
@@ -55,7 +56,12 @@
      * @return an assembler instance.
      */
     public Assembler createAssembler(AssemblerConfig config) {
-    	return new FileAssembler();
+        if (config.getWarSource() != null) {
+            return new WarAssembler();
+        }
+        else {
+            return new FileAssembler();
+        }
     }
     
 }

Added: portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/WebXmlRewritingAssembler.java
URL: http://svn.apache.org/viewvc/portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/WebXmlRewritingAssembler.java?view=auto&rev=514060
==============================================================================
--- portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/WebXmlRewritingAssembler.java (added)
+++ portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/WebXmlRewritingAssembler.java Fri Mar  2 18:49:04 2007
@@ -0,0 +1,241 @@
+/* Copyright 2007 The JA-SIG Collaborative.  All rights reserved.
+*  See license distributed with this file and
+*  available online at http://www.uportal.org/license.html
+*/
+
+package org.apache.pluto.util.assemble;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Properties;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.pluto.descriptors.portlet.PortletAppDD;
+import org.apache.pluto.descriptors.portlet.PortletDD;
+import org.apache.pluto.descriptors.services.PortletAppDescriptorService;
+import org.apache.pluto.descriptors.services.castor.EntityResolverImpl;
+import org.apache.pluto.descriptors.services.castor.PortletAppDescriptorServiceImpl;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+/**
+ * @author Eric Dalquist <a href="mailto:eric.dalquist@doit.wisc.edu">eric.dalquist@doit.wisc.edu</a>
+ * @version $Revision$
+ */
+public abstract class WebXmlRewritingAssembler implements Assembler {
+    /** The XML output properties. */
+    private static final Properties PROPERTIES = new Properties();
+    
+    /** Element tagnames that may appear before servlet elements. */
+    private static final Collection BEFORE_SERVLET_DEF = new ArrayList();
+    
+    /** Element tagnames that may appear before servlet-mapping elements. */
+    private static final Collection BEFORE_MAPPING_DEF = new ArrayList();
+
+    static {
+        // Initialize xml output properties.
+        PROPERTIES.setProperty(OutputKeys.INDENT, "yes");
+        
+        // Initialize BEFORE_SERVLET_DEF collection.
+        BEFORE_SERVLET_DEF.add("icon");
+        BEFORE_SERVLET_DEF.add("display-name");
+        BEFORE_SERVLET_DEF.add("description");
+        BEFORE_SERVLET_DEF.add("distributable");
+        BEFORE_SERVLET_DEF.add("context-param");
+        BEFORE_SERVLET_DEF.add("filter");
+        BEFORE_SERVLET_DEF.add("filter-mapping");
+        BEFORE_SERVLET_DEF.add("listener");
+        
+        // initialize BEFORE_MAPPING_DEF collection.
+        BEFORE_MAPPING_DEF.addAll(BEFORE_SERVLET_DEF);
+        BEFORE_MAPPING_DEF.add("servlet");
+    }
+    
+    
+    /**
+     * Updates the webapp descriptor by injecting portlet wrapper servlet
+     * definitions and mappings.
+     * 
+     * TODO: currently we rely specifically on the castor implementation.
+     * 
+     * @param webXmlIn  input stream to the webapp descriptor, it will be closed before the web xml is written out.
+     * @param portletXmlIn  input stream to the portlet app descriptor, it will be closed before the web xml is written out.
+     * @param webXmlOut output stream to the webapp descriptor, it will be flushed and closed.
+     * @param dispatchServletClass The name of the servlet class to use for
+     *                         handling portlet requests
+     * @throws IOException
+     */
+    protected void updateWebappDescriptor(InputStream webXmlIn,
+                                              InputStream portletXmlIn,
+                                              OutputStream webXmlOut,
+                                              String dispatchServletClass)
+    throws IOException {
+
+        if (dispatchServletClass == null ||
+            dispatchServletClass.length() == 0 ||
+            dispatchServletClass.trim().length() == 0) {
+            dispatchServletClass = DISPATCH_SERVLET_CLASS;
+        }
+        
+        Document webXmlDoc = parse(webXmlIn);
+        webXmlIn.close();
+        
+        Collection servletElements = new ArrayList();
+        Collection mappingElements = new ArrayList();
+
+        PortletAppDescriptorService portletAppDescriptorService =
+                new PortletAppDescriptorServiceImpl();
+        PortletAppDD portletAppDD = portletAppDescriptorService.read(portletXmlIn);
+        portletXmlIn.close();
+        
+        for (Iterator it = portletAppDD.getPortlets().iterator();
+                it.hasNext(); ) {
+            
+            // Read portlet definition.
+            PortletDD portlet = (PortletDD) it.next();
+            String name = portlet.getPortletName();
+            
+            // Create servlet definition element.
+            Element servlet = webXmlDoc.createElement("servlet");
+            Element servletName = webXmlDoc.createElement("servlet-name");
+            servletName.appendChild(webXmlDoc.createTextNode(name));
+            servlet.appendChild(servletName);
+            
+            Element servletClass = webXmlDoc.createElement("servlet-class");
+            servletClass.appendChild(webXmlDoc.createTextNode(dispatchServletClass));
+            servlet.appendChild(servletClass);
+            
+            Element initParam = webXmlDoc.createElement("init-param");
+            Element paramName = webXmlDoc.createElement("param-name");
+            paramName.appendChild(webXmlDoc.createTextNode("portlet-name"));
+            
+            Element paramValue = webXmlDoc.createElement("param-value");
+            paramValue.appendChild(webXmlDoc.createTextNode(name));
+            
+            initParam.appendChild(paramName);
+            initParam.appendChild(paramValue);
+            servlet.appendChild(initParam);
+            
+            Element load = webXmlDoc.createElement("load-on-startup");
+            load.appendChild(webXmlDoc.createTextNode("1"));
+            servlet.appendChild(load);
+            
+            // Create servlet mapping element.
+            Element mapping = webXmlDoc.createElement("servlet-mapping");
+            servletName = webXmlDoc.createElement("servlet-name");
+            servletName.appendChild(webXmlDoc.createTextNode(name));
+            Element uri = webXmlDoc.createElement("url-pattern");
+            uri.appendChild(webXmlDoc.createTextNode("/PlutoInvoker/"+name));
+            mapping.appendChild(servletName);
+            mapping.appendChild(uri);
+            
+            // Save servlet definition and servlet mapping.
+            servletElements.add(servlet);
+            mappingElements.add(mapping);
+        }
+
+        Element webAppNode = webXmlDoc.getDocumentElement();
+        NodeList nodes = webAppNode.getChildNodes();
+        
+        // Find the first node that shouldn't be before the servlet and start
+        // appending. This is kind of ugly, but the hack works for now!
+        for (int i = 0; i < nodes.getLength(); i++) {
+            Node node = nodes.item(i);
+            if (node.getNodeType() == Node.ELEMENT_NODE) {
+                
+                if (!BEFORE_SERVLET_DEF.contains(node.getNodeName())) {
+                    for (Iterator it = servletElements.iterator();
+                            it.hasNext(); ) {
+                        Node servlet = (Node) it.next();
+                        webAppNode.insertBefore(servlet, node);
+                        it.remove();
+                    }
+                }
+                
+                if(!BEFORE_MAPPING_DEF.contains(node.getNodeName())) {
+                    for (Iterator it = mappingElements.iterator();
+                            it.hasNext(); ) {
+                        Node mapping = (Node) it.next();
+                        webAppNode.insertBefore(mapping, node);
+                        it.remove();
+                    }
+                }
+            }
+        }
+
+        // Now, in case there are not any nodes after the servlet def!
+        for (Iterator it = servletElements.iterator(); it.hasNext(); ) {
+            webAppNode.appendChild((Node)it.next());
+        }
+        for (Iterator it = mappingElements.iterator(); it.hasNext(); ) {
+            webAppNode.appendChild((Node)it.next());
+        }
+        
+        // Write out the updated web.xml document.
+        this.save(webXmlDoc, webXmlOut);
+    }
+    
+    /**
+     * Saves the XML document to the specified output stream.
+     * @param xmlDoc  the XML document.
+     * @param out  the output stream.
+     * @throws IOException  if an error occurs.
+     */
+    protected void save(Document xmlDoc, OutputStream out)
+    throws IOException {
+        try {
+            TransformerFactory factory = TransformerFactory.newInstance();
+            Transformer transformer = factory.newTransformer();
+            transformer.setOutputProperties(PROPERTIES);
+            transformer.transform(new DOMSource(xmlDoc),
+                                  new StreamResult(out));
+        } catch (TransformerConfigurationException ex) {
+            ex.printStackTrace();
+            throw new IOException(ex.getMessage());
+        } catch (TransformerException ex) {
+            ex.printStackTrace();
+            throw new IOException(ex.getMessage());
+        } finally {
+            out.flush();
+            out.close();
+        }
+    }
+    
+    /**
+     * Parses an input stream of an XML file to an XML document.
+     * @param xmlIn  the input stream of an XML file.
+     * @return the XML document.
+     * @throws IOException  if an error occurs.
+     */
+    protected Document parse(InputStream xmlIn) throws IOException {
+        Document xmlDoc = null;
+        try {
+            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+            DocumentBuilder builder = factory.newDocumentBuilder();
+            builder.setEntityResolver(new EntityResolverImpl());
+            xmlDoc = builder.parse(xmlIn);
+        } catch (ParserConfigurationException ex) {
+            throw new IOException(ex.getMessage());
+        } catch (SAXException ex) {
+            throw new IOException(ex.getMessage());
+        }
+        return xmlDoc;
+    }
+}

Propchange: portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/WebXmlRewritingAssembler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/WebXmlRewritingAssembler.java
------------------------------------------------------------------------------
    svn:keywords = Id Author Date Rev

Modified: portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/file/FileAssembler.java
URL: http://svn.apache.org/viewvc/portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/file/FileAssembler.java?view=diff&rev=514060&r1=514059&r2=514060
==============================================================================
--- portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/file/FileAssembler.java (original)
+++ portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/file/FileAssembler.java Fri Mar  2 18:49:04 2007
@@ -16,39 +16,15 @@
  */
 package org.apache.pluto.util.assemble.file;
 
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerConfigurationException;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
+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.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.Properties;
 
-import org.apache.pluto.descriptors.portlet.PortletAppDD;
-import org.apache.pluto.descriptors.portlet.PortletDD;
-import org.apache.pluto.descriptors.services.PortletAppDescriptorService;
-import org.apache.pluto.descriptors.services.castor.EntityResolverImpl;
-import org.apache.pluto.descriptors.services.castor.PortletAppDescriptorServiceImpl;
 import org.apache.pluto.util.UtilityException;
-import org.apache.pluto.util.assemble.Assembler;
 import org.apache.pluto.util.assemble.AssemblerConfig;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.xml.sax.SAXException;
+import org.apache.pluto.util.assemble.WebXmlRewritingAssembler;
 
 /**
  *
@@ -56,36 +32,7 @@
  * @version 1.0
  * @since Nov 8, 2004
  */
-public class FileAssembler implements Assembler {
-	
-	/** The XML output properties. */
-    private static final Properties PROPERTIES = new Properties();
-    
-    /** Element tagnames that may appear before servlet elements. */
-    private static final Collection BEFORE_SERVLET_DEF = new ArrayList();
-    
-    /** Element tagnames that may appear before servlet-mapping elements. */
-    private static final Collection BEFORE_MAPPING_DEF = new ArrayList();
-
-    static {
-    	// Initialize xml output properties.
-        PROPERTIES.setProperty(OutputKeys.INDENT, "yes");
-        
-        // Initialize BEFORE_SERVLET_DEF collection.
-        BEFORE_SERVLET_DEF.add("icon");
-        BEFORE_SERVLET_DEF.add("display-name");
-        BEFORE_SERVLET_DEF.add("description");
-        BEFORE_SERVLET_DEF.add("distributable");
-        BEFORE_SERVLET_DEF.add("context-param");
-        BEFORE_SERVLET_DEF.add("filter");
-        BEFORE_SERVLET_DEF.add("filter-mapping");
-        BEFORE_SERVLET_DEF.add("listener");
-        
-        // initialize BEFORE_MAPPING_DEF collection.
-        BEFORE_MAPPING_DEF.addAll(BEFORE_SERVLET_DEF);
-        BEFORE_MAPPING_DEF.add("servlet");
-    }
-    
+public class FileAssembler extends WebXmlRewritingAssembler {
     // Constructor -------------------------------------------------------------
     
     /**
@@ -100,190 +47,31 @@
     
     public void assemble(AssemblerConfig config) throws UtilityException {
         try {
-            InputStream webXmlIn = new FileInputStream(
-            		config.getWebappDescriptor());
-            InputStream portletXmlIn = new FileInputStream(
-            		config.getPortletDescriptor());
-            Document xmlDoc = updateWebappDescriptor(webXmlIn, portletXmlIn,
-                                                     config.getDispatchServletClass());
-            webXmlIn.close();
-            FileOutputStream webXmlOut = new FileOutputStream(
-            		config.getDestination());
-            save(xmlDoc, webXmlOut);
-        } catch (IOException ex) {
-            throw new UtilityException(ex.getMessage(), ex, null);
-        }
-    }
-    
-    
-    // Protected Methods -------------------------------------------------------
-    
-    /**
-     * Saves the XML document to the specified output stream.
-     * @param xmlDoc  the XML document.
-     * @param out  the output stream.
-     * @throws IOException  if an error occurs.
-     */
-    protected void save(Document xmlDoc, OutputStream out)
-    throws IOException {
-        try {
-            TransformerFactory factory = TransformerFactory.newInstance();
-            Transformer transformer = factory.newTransformer();
-            transformer.setOutputProperties(PROPERTIES);
-            transformer.transform(new DOMSource(xmlDoc),
-                                  new StreamResult(out));
-        } catch (TransformerConfigurationException ex) {
-            ex.printStackTrace();
-            throw new IOException(ex.getMessage());
-        } catch (TransformerException ex) {
-            ex.printStackTrace();
-            throw new IOException(ex.getMessage());
-        } finally {
-            out.flush();
-            out.close();
-        }
-    }
-
-
-    /**
-     * Updates the webapp descriptor by injecting portlet wrapper servlet
-     * definitions and mappings.
-     * 
-     * TODO: currently we rely specifically on the castor implementation.
-     * 
-     * @param webXmlIn  input stream to the webapp descriptor.
-     * @param portletXmlIn  input stream to the portlet app descriptor.
-     * @param dispatchServletClass The name of the servlet class to use for
-     *                         handling portlet requests
-     * @return the updated webapp descriptor XML document.
-     * @throws IOException
-     */
-    protected Document updateWebappDescriptor(InputStream webXmlIn,
-                                              InputStream portletXmlIn,
-                                              String dispatchServletClass)
-    throws IOException {
-
-        if (dispatchServletClass == null ||
-            dispatchServletClass.length() == 0 ||
-            dispatchServletClass.trim().length() == 0) {
-            dispatchServletClass = DISPATCH_SERVLET_CLASS;
-        }
-    	
-        Document webXmlDoc = parse(webXmlIn);
-        Collection servletElements = new ArrayList();
-        Collection mappingElements = new ArrayList();
-
-        PortletAppDescriptorService portletAppDescriptorService =
-            	new PortletAppDescriptorServiceImpl();
-        PortletAppDD portletAppDD = portletAppDescriptorService.read(portletXmlIn);
-        
-        for (Iterator it = portletAppDD.getPortlets().iterator();
-        		it.hasNext(); ) {
-            
-        	// Read portlet definition.
-        	PortletDD portlet = (PortletDD) it.next();
-            String name = portlet.getPortletName();
-            
-            // Create servlet definition element.
-            Element servlet = webXmlDoc.createElement("servlet");
-            Element servletName = webXmlDoc.createElement("servlet-name");
-            servletName.appendChild(webXmlDoc.createTextNode(name));
-            servlet.appendChild(servletName);
-            
-            Element servletClass = webXmlDoc.createElement("servlet-class");
-            servletClass.appendChild(webXmlDoc.createTextNode(dispatchServletClass));
-            servlet.appendChild(servletClass);
-            
-            Element initParam = webXmlDoc.createElement("init-param");
-            Element paramName = webXmlDoc.createElement("param-name");
-            paramName.appendChild(webXmlDoc.createTextNode("portlet-name"));
-            
-            Element paramValue = webXmlDoc.createElement("param-value");
-            paramValue.appendChild(webXmlDoc.createTextNode(name));
+            final File webappDescriptor = config.getWebappDescriptor();
+            InputStream webXmlIn = new FileInputStream(webappDescriptor);
             
-            initParam.appendChild(paramName);
-            initParam.appendChild(paramValue);
-            servlet.appendChild(initParam);
+            final File portletDescriptor = config.getPortletDescriptor();
+            InputStream portletXmlIn = new FileInputStream(portletDescriptor);
             
-            Element load = webXmlDoc.createElement("load-on-startup");
-            load.appendChild(webXmlDoc.createTextNode("1"));
-            servlet.appendChild(load);
-            
-            // Create servlet mapping element.
-            Element mapping = webXmlDoc.createElement("servlet-mapping");
-            servletName = webXmlDoc.createElement("servlet-name");
-            servletName.appendChild(webXmlDoc.createTextNode(name));
-            Element uri = webXmlDoc.createElement("url-pattern");
-            uri.appendChild(webXmlDoc.createTextNode("/PlutoInvoker/"+name));
-            mapping.appendChild(servletName);
-            mapping.appendChild(uri);
-            
-            // Save servlet definition and servlet mapping.
-            servletElements.add(servlet);
-            mappingElements.add(mapping);
-        }
-
-        Element webAppNode = webXmlDoc.getDocumentElement();
-        NodeList nodes = webAppNode.getChildNodes();
-        
-        // Find the first node that shouldn't be before the servlet and start
-        // appending. This is kind of ugly, but the hack works for now!
-        for (int i = 0; i < nodes.getLength(); i++) {
-            Node node = nodes.item(i);
-            if (node.getNodeType() == Node.ELEMENT_NODE) {
+            final File destinationDescriptor = config.getDestination();
+            if (webappDescriptor.equals(destinationDescriptor)) {
+                final File tempXml = File.createTempFile(webappDescriptor.getName() + ".", ".tmp");
+                final FileOutputStream webXmlOut = new FileOutputStream(tempXml);
                 
-            	if (!BEFORE_SERVLET_DEF.contains(node.getNodeName())) {
-                	for (Iterator it = servletElements.iterator();
-                			it.hasNext(); ) {
-                        Node servlet = (Node) it.next();
-                        webAppNode.insertBefore(servlet, node);
-                        it.remove();
-                    }
-                }
+                this.updateWebappDescriptor(webXmlIn, portletXmlIn, webXmlOut, config.getDispatchServletClass());
                 
-                if(!BEFORE_MAPPING_DEF.contains(node.getNodeName())) {
-                	for (Iterator it = mappingElements.iterator();
-                			it.hasNext(); ) {
-                        Node mapping = (Node) it.next();
-                        webAppNode.insertBefore(mapping, node);
-                        it.remove();
-                    }
-                }
+                //Move the temp file to the destination location
+                destinationDescriptor.delete();
+                tempXml.renameTo(destinationDescriptor);
             }
+            else {
+                destinationDescriptor.getParentFile().mkdirs();
+                final FileOutputStream webXmlOut = new FileOutputStream(destinationDescriptor);
+                this.updateWebappDescriptor(webXmlIn, portletXmlIn, webXmlOut, config.getDispatchServletClass());
+            }
+        } catch (IOException ex) {
+            throw new UtilityException(ex.getMessage(), ex, null);
         }
-
-        // Now, in case there are not any nodes after the servlet def!
-        for (Iterator it = servletElements.iterator(); it.hasNext(); ) {
-            webAppNode.appendChild((Node)it.next());
-        }
-        for (Iterator it = mappingElements.iterator(); it.hasNext(); ) {
-            webAppNode.appendChild((Node)it.next());
-        }
-        
-        // Return the updated web.xml document.
-        return webXmlDoc;
-    }
-    
-    /**
-     * Parses an input stream of an XML file to an XML document.
-     * @param xmlIn  the input stream of an XML file.
-     * @return the XML document.
-     * @throws IOException  if an error occurs.
-     */
-    private Document parse(InputStream xmlIn) throws IOException {
-        Document xmlDoc = null;
-        try {
-            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-            DocumentBuilder builder = factory.newDocumentBuilder();
-            builder.setEntityResolver(new EntityResolverImpl());
-            xmlDoc = builder.parse(xmlIn);
-        } catch (ParserConfigurationException ex) {
-            throw new IOException(ex.getMessage());
-        } catch (SAXException ex) {
-            throw new IOException(ex.getMessage());
-        }
-        return xmlDoc;
     }
-    
 }
 

Added: portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/war/WarAssembler.java
URL: http://svn.apache.org/viewvc/portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/war/WarAssembler.java?view=auto&rev=514060
==============================================================================
--- portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/war/WarAssembler.java (added)
+++ portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/war/WarAssembler.java Fri Mar  2 18:49:04 2007
@@ -0,0 +1,184 @@
+/*
+ * 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.
+ */
+package org.apache.pluto.util.assemble.war;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+import java.util.zip.CRC32;
+import java.util.zip.ZipEntry;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.pluto.util.UtilityException;
+import org.apache.pluto.util.assemble.AssemblerConfig;
+import org.apache.pluto.util.assemble.WebXmlRewritingAssembler;
+
+/**
+ *
+ * @author Eric Dalquist <a href="mailto:edalquist@doit.wisc.edu">edalquist@doit.wisc.edu</a>
+ * @version 1.0
+ * @since Nov 8, 2004
+ */
+public class WarAssembler extends WebXmlRewritingAssembler {
+    // Constructor -------------------------------------------------------------
+    
+    /**
+     * Default no-arg constructor.
+     */
+    public WarAssembler() {
+    	// Do nothing.
+    }
+    
+    
+    // Assembler Impl ----------------------------------------------------------
+    
+    public void assemble(AssemblerConfig config) throws UtilityException {
+        try {
+            final File sourceArchive = config.getWarSource();
+            final File destinationFolder = config.getDestination();
+            final File destinationArchive = new File(destinationFolder, sourceArchive.getName());
+            
+            //If the source and dest are the same a temp location is needed
+            if (sourceArchive.equals(destinationArchive)) {
+                final File tempArchive = File.createTempFile(sourceArchive.getName() + ".", ".tmp");
+                this.assembleWar(sourceArchive, tempArchive, config.getDispatchServletClass());
+                
+                //Move the temp file to the destination location
+                destinationArchive.delete();
+                tempArchive.renameTo(destinationArchive);
+            }
+            else {
+                this.assembleWar(sourceArchive, destinationArchive, config.getDispatchServletClass());
+            }
+            
+        } catch (IOException ex) {
+            throw new UtilityException(ex.getMessage(), ex, null);
+        }
+    }
+    
+    /**
+     * Reads the source JAR copying entries to the dest JAR. The web.xml and portlet.xml are cached
+     * and after the entire archive is copied (minus the web.xml) a re-written web.xml is generated
+     * and written to the destination JAR.
+     */
+    protected void assembleWar(File source, File dest, String dispatchServletClass) throws IOException {
+        final JarInputStream jarIn = new JarInputStream(new FileInputStream(source));
+        
+        try {
+            //Create the output JAR stream, copying the Manifest
+            final Manifest manifest = jarIn.getManifest();
+            //TODO add pluto notes to the Manifest?
+            FileUtils.forceMkdir(dest.getParentFile());
+            final JarOutputStream jarOut = new JarOutputStream(new FileOutputStream(dest), manifest);
+
+            try {
+                //Need to buffer the web.xml and portlet.xml files for the rewritting
+                JarEntry servletXmlEntry = null;
+                byte[] servletXmlBuffer = null;
+                byte[] portletXmlBuffer = null;
+                
+                //Read the source archive entry by entry
+                JarEntry originalJarEntry;
+                while ((originalJarEntry = jarIn.getNextJarEntry()) != null) {
+                    final JarEntry newJarEntry = this.smartClone(originalJarEntry);
+                    
+                    //Capture the web.xml JarEntry and contents as a byte[], don't write it out now
+                    if (SERVLET_XML.equals(newJarEntry.getName())) {
+                        servletXmlEntry = newJarEntry;
+                        servletXmlBuffer = IOUtils.toByteArray(jarIn);
+                    }
+                    //Capture the portlet.xml contents as a byte[]
+                    else if (PORTLET_XML.equals(newJarEntry.getName())) {
+                        portletXmlBuffer = IOUtils.toByteArray(jarIn);
+                        jarOut.putNextEntry(newJarEntry);
+                        IOUtils.write(portletXmlBuffer, jarOut);
+                    }
+                    //Copy all other entries directly to the output archive
+                    else {
+                        jarOut.putNextEntry(newJarEntry);
+                        IOUtils.copy(jarIn, jarOut);
+                    }
+                }
+                
+                //Checks to make sure the web.xml and portlet.xml were found
+                if (servletXmlBuffer == null) {
+                    throw new FileNotFoundException("File '" + SERVLET_XML + "' could not be found in the archive '" + source + "'");
+                }
+                if (portletXmlBuffer == null) {
+                    throw new FileNotFoundException("File '" + PORTLET_XML + "' could not be found in the archive '" + source + "'");
+                }
+                
+                //Create streams of the byte[] data for the updater method
+                final InputStream webXmlIn = new ByteArrayInputStream(servletXmlBuffer);
+                final InputStream portletXmlIn = new ByteArrayInputStream(portletXmlBuffer);
+                final ByteArrayOutputStream webXmlOut = new ByteArrayOutputStream(servletXmlBuffer.length);
+                
+                //Update the web.xml
+                this.updateWebappDescriptor(webXmlIn, portletXmlIn, webXmlOut, dispatchServletClass);
+                final byte[] webXmlBytes = webXmlOut.toByteArray();
+                
+                //If no compression is being used (STORED) we have to manually update the size and crc
+                if (servletXmlEntry.getMethod() == ZipEntry.STORED) {
+                    servletXmlEntry.setSize(webXmlBytes.length);
+                    
+                    final CRC32 webXmlCrc = new CRC32();
+                    webXmlCrc.update(webXmlBytes);
+                    servletXmlEntry.setCrc(webXmlCrc.getValue());
+                }
+                
+                //write out the web.xml entry and contents
+                jarOut.putNextEntry(servletXmlEntry);
+                IOUtils.write(webXmlBytes, jarOut);
+            }
+            finally {
+                jarOut.flush();
+                jarOut.close();
+            }
+        }
+        finally {
+            jarIn.close();
+        }
+    }
+
+
+    private JarEntry smartClone(JarEntry originalJarEntry) {
+        final JarEntry newJarEntry = new JarEntry(originalJarEntry.getName());
+        newJarEntry.setComment(originalJarEntry.getComment());
+        newJarEntry.setExtra(originalJarEntry.getExtra());
+        newJarEntry.setMethod(originalJarEntry.getMethod());
+        newJarEntry.setTime(originalJarEntry.getTime());
+
+        //Must set size and CRC for STORED entries
+        if (newJarEntry.getMethod() == ZipEntry.STORED) {
+            newJarEntry.setSize(originalJarEntry.getSize());
+            newJarEntry.setCrc(originalJarEntry.getCrc());
+        }
+        
+        return newJarEntry;
+    }
+}
+

Propchange: portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/war/WarAssembler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/war/WarAssembler.java
------------------------------------------------------------------------------
    svn:keywords = Id Author Date Rev

Added: portals/pluto/trunk/pluto-util/src/test/java/org/apache/pluto/util/assemble/file/FileAssemblerTest.java
URL: http://svn.apache.org/viewvc/portals/pluto/trunk/pluto-util/src/test/java/org/apache/pluto/util/assemble/file/FileAssemblerTest.java?view=auto&rev=514060
==============================================================================
--- portals/pluto/trunk/pluto-util/src/test/java/org/apache/pluto/util/assemble/file/FileAssemblerTest.java (added)
+++ portals/pluto/trunk/pluto-util/src/test/java/org/apache/pluto/util/assemble/file/FileAssemblerTest.java Fri Mar  2 18:49:04 2007
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+package org.apache.pluto.util.assemble.file;
+
+import java.io.File;
+import java.io.FileReader;
+import java.net.URL;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.pluto.util.assemble.AssemblerConfig;
+import org.custommonkey.xmlunit.XMLTestCase;
+import org.custommonkey.xmlunit.XMLUnit;
+
+/**
+ * @author Eric Dalquist <a href="mailto:eric.dalquist@doit.wisc.edu">eric.dalquist@doit.wisc.edu</a>
+ * @version $Revision$
+ */
+public class FileAssemblerTest extends XMLTestCase {
+    private File webXmlFile = null;
+    private File portletXmlFile = null;
+    private File assembledWebXmlFile = null;
+    
+    protected void setUp() throws Exception {
+        XMLUnit.setIgnoreWhitespace(true);
+        
+        final URL webXmlUrl = this.getClass().getResource("/org/apache/pluto/util/assemble/file/web.xml");
+        this.webXmlFile = new File(webXmlUrl.getFile());
+        
+        final URL portletXmlUrl = this.getClass().getResource("/org/apache/pluto/util/assemble/file/portlet.xml");
+        this.portletXmlFile = new File(portletXmlUrl.getFile());
+        
+        final URL assembledWebXmlUrl = this.getClass().getResource("/org/apache/pluto/util/assemble/file/assembled.web.xml");
+        this.assembledWebXmlFile = new File(assembledWebXmlUrl.getFile());
+    }
+
+    protected void tearDown() throws Exception {
+        this.webXmlFile = null;
+        this.portletXmlFile = null;
+    }
+
+    public void testAssembleToNewDirectory() throws Exception {
+        AssemblerConfig config = new AssemblerConfig();
+        
+        final File webXmlFileDest = File.createTempFile(this.webXmlFile.getName() + ".", ".xml");
+        webXmlFileDest.deleteOnExit();
+
+        config.setWebappDescriptor(this.webXmlFile);
+        config.setPortletDescriptor(this.portletXmlFile);
+        config.setDestination(webXmlFileDest);
+        
+        FileAssembler assembler = new FileAssembler();
+        assembler.assemble(config);
+
+        assertXMLEqual(new FileReader(this.assembledWebXmlFile), new FileReader(webXmlFileDest));
+    }
+    
+    public void testAssembleOverSelf() throws Exception {
+        AssemblerConfig config = new AssemblerConfig();
+        
+        final File webXmlFileCopy = File.createTempFile(this.webXmlFile.getName() + ".", ".source.xml");
+        webXmlFileCopy.deleteOnExit();
+
+        FileUtils.copyFile(this.webXmlFile, webXmlFileCopy);
+        
+        config.setWebappDescriptor(webXmlFileCopy);
+        config.setPortletDescriptor(this.portletXmlFile);
+        config.setDestination(webXmlFileCopy);
+        
+        FileAssembler assembler = new FileAssembler();
+        assembler.assemble(config);
+        
+        assertXMLEqual(new FileReader(this.assembledWebXmlFile), new FileReader(webXmlFileCopy));
+    }
+}

Propchange: portals/pluto/trunk/pluto-util/src/test/java/org/apache/pluto/util/assemble/file/FileAssemblerTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/pluto/trunk/pluto-util/src/test/java/org/apache/pluto/util/assemble/file/FileAssemblerTest.java
------------------------------------------------------------------------------
    svn:keywords = Id Author Date Rev

Added: portals/pluto/trunk/pluto-util/src/test/java/org/apache/pluto/util/assemble/war/WarAssemblerTest.java
URL: http://svn.apache.org/viewvc/portals/pluto/trunk/pluto-util/src/test/java/org/apache/pluto/util/assemble/war/WarAssemblerTest.java?view=auto&rev=514060
==============================================================================
--- portals/pluto/trunk/pluto-util/src/test/java/org/apache/pluto/util/assemble/war/WarAssemblerTest.java (added)
+++ portals/pluto/trunk/pluto-util/src/test/java/org/apache/pluto/util/assemble/war/WarAssemblerTest.java Fri Mar  2 18:49:04 2007
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+package org.apache.pluto.util.assemble.war;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.pluto.util.assemble.AssemblerConfig;
+
+/**
+ * @author Eric Dalquist <a href="mailto:eric.dalquist@doit.wisc.edu">eric.dalquist@doit.wisc.edu</a>
+ * @version $Revision$
+ */
+public class WarAssemblerTest extends TestCase {
+    private File portletFile = null;
+    
+    protected void setUp() throws Exception {
+        final URL portletUrl = this.getClass().getResource("/org/apache/pluto/util/assemble/war/WarDeployerTestPortlet.war");
+        this.portletFile = new File(portletUrl.getFile());
+    }
+
+    protected void tearDown() throws Exception {
+        this.portletFile = null;
+    }
+
+    public void testAssembleToNewDirectory() throws Exception {
+        AssemblerConfig config = new AssemblerConfig();
+        
+        config.setWarSource(this.portletFile);
+        
+        final File tempDir = getTempDir();
+        config.setDestination(tempDir);
+        
+        WarAssembler assembler = new WarAssembler();
+        assembler.assemble(config);
+        
+        //How to validate it worked?
+    }
+    
+    public void testAssembleOverSelf() throws Exception {
+        AssemblerConfig config = new AssemblerConfig();
+        
+        final File portletCopy = File.createTempFile(this.portletFile.getName() + ".", ".war");
+        portletCopy.deleteOnExit();
+        FileUtils.copyFile(this.portletFile, portletCopy);
+        
+        config.setWarSource(portletCopy);
+        config.setDestination(portletCopy.getParentFile());
+        
+        WarAssembler assembler = new WarAssembler();
+        assembler.assemble(config);
+        
+        //How to validate it worked?
+    }
+
+    private File getTempDir() throws IOException {
+        final File tempFile = File.createTempFile("DoesNotMatter", ".tmp");
+        tempFile.delete();
+        final File tempDir = tempFile.getParentFile();
+        return tempDir;
+    }
+}

Propchange: portals/pluto/trunk/pluto-util/src/test/java/org/apache/pluto/util/assemble/war/WarAssemblerTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/pluto/trunk/pluto-util/src/test/java/org/apache/pluto/util/assemble/war/WarAssemblerTest.java
------------------------------------------------------------------------------
    svn:keywords = Id Author Date Rev

Added: portals/pluto/trunk/pluto-util/src/test/resources/org/apache/pluto/util/assemble/file/assembled.web.xml
URL: http://svn.apache.org/viewvc/portals/pluto/trunk/pluto-util/src/test/resources/org/apache/pluto/util/assemble/file/assembled.web.xml?view=auto&rev=514060
==============================================================================
--- portals/pluto/trunk/pluto-util/src/test/resources/org/apache/pluto/util/assemble/file/assembled.web.xml (added)
+++ portals/pluto/trunk/pluto-util/src/test/resources/org/apache/pluto/util/assemble/file/assembled.web.xml Fri Mar  2 18:49:04 2007
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app>
+    <display-name>WarTestServletDisplayName</display-name>
+    <servlet>
+        <servlet-name>WarTestPortletName</servlet-name>
+        <servlet-class>org.apache.pluto.core.PortletServlet</servlet-class>
+        <init-param>
+            <param-name>portlet-name</param-name>
+            <param-value>WarTestPortletName</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+    <servlet-mapping>
+        <servlet-name>WarTestPortletName</servlet-name>
+        <url-pattern>/PlutoInvoker/WarTestPortletName</url-pattern>
+    </servlet-mapping>
+</web-app>

Propchange: portals/pluto/trunk/pluto-util/src/test/resources/org/apache/pluto/util/assemble/file/assembled.web.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/pluto/trunk/pluto-util/src/test/resources/org/apache/pluto/util/assemble/file/assembled.web.xml
------------------------------------------------------------------------------
    svn:keywords = Id Author Date Rev

Added: portals/pluto/trunk/pluto-util/src/test/resources/org/apache/pluto/util/assemble/file/portlet.xml
URL: http://svn.apache.org/viewvc/portals/pluto/trunk/pluto-util/src/test/resources/org/apache/pluto/util/assemble/file/portlet.xml?view=auto&rev=514060
==============================================================================
--- portals/pluto/trunk/pluto-util/src/test/resources/org/apache/pluto/util/assemble/file/portlet.xml (added)
+++ portals/pluto/trunk/pluto-util/src/test/resources/org/apache/pluto/util/assemble/file/portlet.xml Fri Mar  2 18:49:04 2007
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd" version="1.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd">
+    <portlet>
+        <portlet-name>WarTestPortletName</portlet-name>
+        <portlet-class>WarTestPortletClass</portlet-class>
+        <expiration-cache>0</expiration-cache>
+        <supports>
+            <mime-type>text/html</mime-type>
+            <portlet-mode>help</portlet-mode>
+        </supports>
+        <supported-locale>en-US</supported-locale>
+
+        <portlet-info>
+            <title>WarTestPortlet Title</title>
+            <short-title>WarTestPortlet Short Title</short-title>
+            <keywords>WarTestPortlet, Keywords</keywords>
+        </portlet-info>
+    </portlet>
+</portlet-app>

Propchange: portals/pluto/trunk/pluto-util/src/test/resources/org/apache/pluto/util/assemble/file/portlet.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/pluto/trunk/pluto-util/src/test/resources/org/apache/pluto/util/assemble/file/portlet.xml
------------------------------------------------------------------------------
    svn:keywords = Id Author Date Rev

Added: portals/pluto/trunk/pluto-util/src/test/resources/org/apache/pluto/util/assemble/file/web.xml
URL: http://svn.apache.org/viewvc/portals/pluto/trunk/pluto-util/src/test/resources/org/apache/pluto/util/assemble/file/web.xml?view=auto&rev=514060
==============================================================================
--- portals/pluto/trunk/pluto-util/src/test/resources/org/apache/pluto/util/assemble/file/web.xml (added)
+++ portals/pluto/trunk/pluto-util/src/test/resources/org/apache/pluto/util/assemble/file/web.xml Fri Mar  2 18:49:04 2007
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app>
+    <display-name>WarTestServletDisplayName</display-name>
+</web-app>

Propchange: portals/pluto/trunk/pluto-util/src/test/resources/org/apache/pluto/util/assemble/file/web.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/pluto/trunk/pluto-util/src/test/resources/org/apache/pluto/util/assemble/file/web.xml
------------------------------------------------------------------------------
    svn:keywords = Id Author Date Rev

Modified: portals/pluto/trunk/pom.xml
URL: http://svn.apache.org/viewvc/portals/pluto/trunk/pom.xml?view=diff&rev=514060&r1=514059&r2=514060
==============================================================================
--- portals/pluto/trunk/pom.xml (original)
+++ portals/pluto/trunk/pom.xml Fri Mar  2 18:49:04 2007
@@ -245,6 +245,8 @@
         <ant.version>1.6.5</ant.version>
         <junit.version>3.8.1</junit.version>
         <jmock.version>1.0.1</jmock.version>
+        <commons-io.version>1.3.1</commons-io.version>
+        <xmlunit.version>1.0</xmlunit.version>
     </properties>