You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by re...@apache.org on 2007/05/01 13:35:27 UTC

svn commit: r534014 [1/3] - in /cocoon/trunk/tools/cocoon-maven-plugin: ./ src/ src/changes/ src/main/java/org/apache/cocoon/maven/deployer/ src/main/java/org/apache/cocoon/maven/deployer/monolithic/ src/main/java/org/apache/cocoon/maven/deployer/servl...

Author: reinhard
Date: Tue May  1 04:35:26 2007
New Revision: 534014

URL: http://svn.apache.org/viewvc?view=rev&rev=534014
Log:
Merging deployer plugin and reloading classloader plugin

Added:
    cocoon/trunk/tools/cocoon-maven-plugin/
      - copied from r531008, cocoon/trunk/tools/cocoon-rcl/cocoon-rcl-plugin/
    cocoon/trunk/tools/cocoon-maven-plugin/pom.xml
      - copied, changed from r533959, cocoon/trunk/tools/cocoon-rcl/cocoon-rcl-plugin/pom.xml
    cocoon/trunk/tools/cocoon-maven-plugin/src/
      - copied from r533959, cocoon/trunk/tools/cocoon-rcl/cocoon-rcl-plugin/src/
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/AbstractDeployMojo.java   (with props)
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/DeployExplodedMojo.java   (with props)
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/DeployWarMojo.java   (with props)
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/WebApplicationRewriter.java   (with props)
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/DeploymentException.java   (with props)
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/FileAlreadyDeployedException.java   (with props)
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/FileDeployer.java   (with props)
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/MonolithicCocoonDeployer.java   (with props)
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/RuleBasedZipExtractor.java   (with props)
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/SingleFileDeployer.java   (with props)
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/XPatchDeployer.java   (with props)
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/servlet/
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/servlet/ShieldedClassLoader.java   (with props)
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/servlet/ShieldedClassLoaderManager.java   (with props)
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/servlet/ShieldingListener.java   (with props)
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/servlet/ShieldingServlet.java   (with props)
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/servlet/ShieldingServletFilter.java   (with props)
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/utils/
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/utils/CopyUtils.java   (with props)
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/utils/FileUtils.java   (with props)
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/utils/WildcardHelper.java   (with props)
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/utils/XMLUtils.java   (with props)
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/resources/org/apache/cocoon/maven/deployer/
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/resources/org/apache/cocoon/maven/deployer/monolithic/
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/resources/org/apache/cocoon/maven/deployer/monolithic/WEB-INF/
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/resources/org/apache/cocoon/maven/deployer/monolithic/WEB-INF/cocoon/
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/resources/org/apache/cocoon/maven/deployer/monolithic/WEB-INF/cocoon/properties/
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/resources/org/apache/cocoon/maven/deployer/monolithic/blocks/
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/resources/org/apache/cocoon/maven/deployer/utils/
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/resources/org/apache/cocoon/maven/deployer/utils/web-app_2_3.dtd   (with props)
Modified:
    cocoon/trunk/tools/cocoon-maven-plugin/src/changes/changes.xml
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/rcl/ReloadingWebappMojo.java
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/rcl/RwmProperties.java
    cocoon/trunk/tools/cocoon-maven-plugin/src/main/resources/org/apache/cocoon/maven/rcl/WEB-INF/log4j.xml

Copied: cocoon/trunk/tools/cocoon-maven-plugin/pom.xml (from r533959, cocoon/trunk/tools/cocoon-rcl/cocoon-rcl-plugin/pom.xml)
URL: http://svn.apache.org/viewvc/cocoon/trunk/tools/cocoon-maven-plugin/pom.xml?view=diff&rev=534014&p1=cocoon/trunk/tools/cocoon-rcl/cocoon-rcl-plugin/pom.xml&r1=533959&p2=cocoon/trunk/tools/cocoon-maven-plugin/pom.xml&r2=534014
==============================================================================
--- cocoon/trunk/tools/cocoon-rcl/cocoon-rcl-plugin/pom.xml (original)
+++ cocoon/trunk/tools/cocoon-maven-plugin/pom.xml Tue May  1 04:35:26 2007
@@ -20,73 +20,81 @@
 <!--+
     | @version $Id$
     +-->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
   <modelVersion>4.0.0</modelVersion>
   <parent>
     <artifactId>cocoon-tools-modules</artifactId>
     <groupId>org.apache.cocoon</groupId>
-    <version>4-SNAPSHOT</version>
-    <relativePath>../../pom.xml</relativePath>    
+    <version>4-SNAPSHOT</version>    
   </parent>
-  <artifactId>cocoon-rcl-plugin</artifactId>
+  <artifactId>cocoon-maven-plugin</artifactId>
   <version>1.0.0-M1-SNAPSHOT</version>
   <packaging>maven-plugin</packaging>
-  <name>Cocoon Reloading Classloader - Maven 2 Plugin</name>
+  <name>Cocoon Maven 2 Plugin</name>
   
   <dependencies>
     <!-- utility libs -->
     <dependency>
       <groupId>antlr</groupId>
       <artifactId>stringtemplate</artifactId>
-      
     </dependency>
     <dependency>
       <groupId>commons-io</groupId>
       <artifactId>commons-io</artifactId>
-      
     </dependency>
     <dependency>
       <groupId>commons-configuration</groupId>
       <artifactId>commons-configuration</artifactId>
-      
     </dependency>    
     <dependency>
       <groupId>commons-lang</groupId>
       <artifactId>commons-lang</artifactId>
-      
     </dependency>  
     <!-- Maven specific -->
     <dependency>
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-plugin-api</artifactId>
-      
     </dependency>
     <dependency>
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-artifact</artifactId>
-      
     </dependency>
     <dependency>
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-model</artifactId>
-      
     </dependency>
     <dependency>
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-artifact</artifactId>
-      
     </dependency>
     <dependency>
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-project</artifactId>
-      
     </dependency>
+    <dependency>
+      <groupId>org.apache.maven.plugins</groupId>
+      <artifactId>maven-war-plugin</artifactId>
+    </dependency>
+    <!-- Xalan neccessary for XPath operations -->
+    <dependency>
+      <groupId>xalan</groupId>
+      <artifactId>xalan</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>xml-apis</groupId>
+      <artifactId>xml-apis</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+      <scope>compile</scope>
+    </dependency>    
     <!-- test libs -->
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
-      
       <scope>test</scope>
     </dependency>
   </dependencies>
@@ -96,7 +104,7 @@
       <plugin>
         <artifactId>maven-plugin-plugin</artifactId>
         <configuration>
-          <goalPrefix>cocoon-rcl</goalPrefix>
+          <goalPrefix>cocoon</goalPrefix>
         </configuration>
       </plugin>
       <plugin>
@@ -132,4 +140,4 @@
     </site>
   </distributionManagement>   
    
-</project>
+</project>
\ No newline at end of file

Modified: cocoon/trunk/tools/cocoon-maven-plugin/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/cocoon/trunk/tools/cocoon-maven-plugin/src/changes/changes.xml?view=diff&rev=534014&r1=533959&r2=534014
==============================================================================
--- cocoon/trunk/tools/cocoon-maven-plugin/src/changes/changes.xml (original)
+++ cocoon/trunk/tools/cocoon-maven-plugin/src/changes/changes.xml Tue May  1 04:35:26 2007
@@ -31,4 +31,4 @@
         </release>
       </body>
     </document>
-    
\ No newline at end of file
+    

Added: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/AbstractDeployMojo.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/AbstractDeployMojo.java?view=auto&rev=534014
==============================================================================
--- cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/AbstractDeployMojo.java (added)
+++ cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/AbstractDeployMojo.java Tue May  1 04:35:26 2007
@@ -0,0 +1,278 @@
+/*
+ * 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.cocoon.maven.deployer;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.cocoon.maven.deployer.monolithic.DeploymentException;
+import org.apache.cocoon.maven.deployer.monolithic.RuleBasedZipExtractor;
+import org.apache.cocoon.maven.deployer.monolithic.XPatchDeployer;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.SystemUtils;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.factory.ArtifactFactory;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.artifact.resolver.ArtifactResolver;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.plugin.war.AbstractWarMojo;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.project.artifact.MavenMetadataSource;
+
+/**
+ * Create a Cocoon web application based on a block deployment descriptor.
+ * 
+ * @version $Id$
+ */
+public abstract class AbstractDeployMojo extends AbstractWarMojo {
+
+    /**
+     * Artifact factory, needed to download source jars for inclusion in
+     * classpath.
+     * 
+     * @component role="org.apache.maven.artifact.factory.ArtifactFactory"
+     * @required
+     * @readonly
+     */
+    private ArtifactFactory artifactFactory;
+
+    /**
+     * Artifact resolver, needed to download source jars for inclusion in
+     * classpath.
+     * 
+     * @component role="org.apache.maven.artifact.resolver.ArtifactResolver"
+     * @required
+     * @readonly
+     */
+    private ArtifactResolver artifactResolver;
+
+    /**
+     * Artifact resolver, needed to download source jars for inclusion in
+     * classpath.
+     * 
+     * @component role="org.apache.maven.artifact.metadata.ArtifactMetadataSource"
+     * @required
+     * @readonly
+     */
+    private MavenMetadataSource metadataSource;
+
+    /**
+     * Local maven repository.
+     * 
+     * @parameter expression="${localRepository}"
+     * @required
+     * @readonly
+     */
+    private ArtifactRepository localRepository;
+
+    /**
+     * Remote repositories which will be searched for blocks.
+     * 
+     * @parameter expression="${project.remoteArtifactRepositories}"
+     * @required
+     * @readonly
+     */
+    private List remoteArtifactRepositories;
+
+    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    // set properties: necessary because DeployMojo is not in the same package
+    // as AbstractWarMojo
+
+    /**
+     * The project whose project files to create.
+     * 
+     * @parameter expression="${project}"
+     * @required
+     */
+    private MavenProject project;
+
+    /**
+     * The directory containing generated classes.
+     * 
+     * @parameter expression="${project.build.outputDirectory}"
+     * @required
+     * @readonly
+     */
+    private File classesDirectory;
+
+    /**
+     * The directory where the webapp is built.
+     * 
+     * @parameter expression="${project.build.directory}/${project.build.finalName}"
+     * @required
+     */
+    private File webappDirectory;
+
+    /**
+     * Single directory for extra files to include in the WAR.
+     * 
+     * @parameter expression="${basedir}/src/main/webapp"
+     * @required
+     */
+    private File warSourceDirectory;
+
+    /**
+     * The path to the web.xml file to use.
+     * 
+     * @parameter expression="${maven.war.webxml}"
+     */
+    private String webXml;
+
+    /**
+     * Use shielded classloading
+     * 
+     * @parameter expression="${maven.war.shieldingclassloader}"
+     */
+    private boolean useShieldingClassLoader = false;
+
+    /**
+     * Move jars for shielded classloading
+     * 
+     * @parameter expression="${maven.war.shieldingrepository}"
+     */
+    private boolean useShieldingRepository = false;
+
+
+    /**
+     * Deploy a monolithic Cocoon web application. This means it doesn't use the
+     * features that the blocks-fw offers.
+     */
+    protected void deployWebapp() throws MojoExecutionException, MojoFailureException {
+        
+        this.buildExplodedWebapp(getWebappDirectory());
+
+        try {
+            super.copyResources(getWarSourceDirectory(), getWebappDirectory());
+        } catch (IOException e) {
+            throw new MojoExecutionException("A problem occurred while copying webapp resources.", e);
+        }
+
+        xpatch(getBlockArtifactsAsMap(this.getProject(), this.getLog()), new File[0], getWebappDirectory(), this.getLog());        
+        
+        // take care of shielded classloading
+        if (this.useShieldingClassLoader) {
+            WebApplicationRewriter.shieldWebapp(new File(getWebappDirectory(), "WEB-INF"), getLog(), this.useShieldingRepository);
+        }
+    }
+
+    public static void xpatch(final Map libraries, File[] xpatchFiles, final File basedir, Log log) throws DeploymentException {
+        XPatchDeployer xwebPatcher = new XPatchDeployer("WEB-INF");
+        xwebPatcher.setBasedir(basedir);
+        xwebPatcher.setLogger(log);
+        // iterate over all blocks that need to be installed into a J2EE web
+        // application
+        for (Iterator it = libraries.entrySet().iterator(); it.hasNext();) {
+            final Map.Entry entry = (Map.Entry) it.next();
+            final Object id = entry.getKey();
+            File lib = (File) entry.getValue();
+            try {
+                log.debug("Scanning " + id);
+                RuleBasedZipExtractor zipExtractor = new RuleBasedZipExtractor(basedir, log);
+                // add the matching/execution rules
+                zipExtractor.addRule("META-INF/cocoon/xpatch/*.xweb", xwebPatcher);
+                // extract all configurations files
+                zipExtractor.extract(lib);
+            } catch (IOException e) {
+                throw new DeploymentException("Can't deploy '" + lib.getAbsolutePath() + "'.", e);
+            }
+        }
+        
+        for (int i = 0; i < xpatchFiles.length; i++ ) {
+            File patch = xpatchFiles[i];
+            try {
+                xwebPatcher.addPatch(patch);
+                log.info("Adding xpatch: " + patch);
+            } catch (IOException e) {
+                throw new DeploymentException("Can't use patches '" + patch + "'.", e);                
+            }
+        }
+
+        InputStream sourceWebXmlFile = null;
+        File webXml = new File(basedir, "WEB-INF/web.xml");
+        System.out.println("webXml.getAbsolutePath=" + webXml.getAbsolutePath());
+        try {
+            sourceWebXmlFile = new FileInputStream(webXml);
+            xwebPatcher.applyPatches(sourceWebXmlFile, "WEB-INF/web.xml");
+        } catch (FileNotFoundException e) {
+            throw new DeploymentException("Can't apply patches on " + webXml + ".", e);
+        } finally {
+            IOUtils.closeQuietly(sourceWebXmlFile);
+        }
+
+    }    
+    
+    /**
+     * Create a <code>Map</code> of <code>java.io.File</code> objects
+     * pointing to artifacts.
+     */
+    public static Map getBlockArtifactsAsMap(MavenProject project, Log log) throws MojoExecutionException {
+        Map files = new HashMap();
+        for (Iterator it = project.getArtifacts().iterator(); it.hasNext();) {
+            Artifact artifact = (Artifact) it.next();
+            String id = artifact.getArtifactId();
+            if (files.containsKey(id)) {
+                // Now search for all artifacts and print their dependency trail
+                StringBuffer msg = new StringBuffer("There are at least two artifacts with the ID '");
+                msg.append(id);
+                msg.append("':");
+                msg.append(SystemUtils.LINE_SEPARATOR);
+                for (Iterator ai = project.getArtifacts().iterator(); ai.hasNext();) {
+                    final Artifact current = (Artifact) ai.next();
+                    if (current.getArtifactId().equals(id)) {
+                        msg.append(artifact);
+                        msg.append(SystemUtils.LINE_SEPARATOR);
+                        final List l = current.getDependencyTrail();
+                        final Iterator i = l.iterator();
+                        while (i.hasNext()) {
+                            msg.append("    ");
+                            msg.append(i.next().toString());
+                            msg.append(SystemUtils.LINE_SEPARATOR);
+                        }
+                    }
+                }
+                throw new MojoExecutionException(msg.toString());
+            }
+
+
+            files.put(id, artifact.getFile());
+            if (log.isDebugEnabled()) {
+                StringBuffer msg = new StringBuffer("Deploying " + artifact);
+                final List l = artifact.getDependencyTrail();
+                final Iterator i = l.iterator();
+                while (i.hasNext()) {
+                    msg.append("    ");
+                    msg.append(i.next().toString());
+                    msg.append(SystemUtils.LINE_SEPARATOR);
+                }
+                log.debug(msg.toString());
+            }
+
+        }
+        return files;
+    }
+}

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/AbstractDeployMojo.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/AbstractDeployMojo.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/AbstractDeployMojo.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/DeployExplodedMojo.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/DeployExplodedMojo.java?view=auto&rev=534014
==============================================================================
--- cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/DeployExplodedMojo.java (added)
+++ cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/DeployExplodedMojo.java Tue May  1 04:35:26 2007
@@ -0,0 +1,45 @@
+/*
+ * 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.cocoon.maven.deployer;
+
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+
+/**
+ * Create a web application that makes use of Cocoon blocks. In the case of a
+ * web application module, (packaging: war) all referenced blocks are added, in
+ * the case of block (packaging: jar) additionally a minimal Cocoon environemt
+ * is created and it is also possible to reference <i>other</i> locally
+ * available blocks and to set custom properties to make development highly
+ * dynamic.
+ * 
+ * @goal deploy
+ * @requiresProject true
+ * @phase package
+ * @requiresDependencyResolution runtime
+ */
+public class DeployExplodedMojo extends AbstractDeployMojo {
+
+    public void execute() throws MojoExecutionException, MojoFailureException {
+        if (this.getProject().getPackaging().equals("war")) {
+            this.deployWebapp();
+        } else {
+            throw new MojoExecutionException("This goal requires a project of packaging type 'war'.");
+        }
+    }
+
+}
\ No newline at end of file

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/DeployExplodedMojo.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/DeployExplodedMojo.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/DeployExplodedMojo.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/DeployWarMojo.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/DeployWarMojo.java?view=auto&rev=534014
==============================================================================
--- cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/DeployWarMojo.java (added)
+++ cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/DeployWarMojo.java Tue May  1 04:35:26 2007
@@ -0,0 +1,111 @@
+/*
+ * 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.cocoon.maven.deployer;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.maven.archiver.MavenArchiveConfiguration;
+import org.apache.maven.archiver.MavenArchiver;
+import org.apache.maven.artifact.DependencyResolutionRequiredException;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.codehaus.plexus.archiver.ArchiverException;
+import org.codehaus.plexus.archiver.jar.ManifestException;
+import org.codehaus.plexus.archiver.war.WarArchiver;
+
+/**
+ * Create a packaged Cocoon web application (.war file) based on a block
+ * deployment descriptor.
+ * 
+ * @goal deploy-war
+ * @requiresProject true
+ * @phase package
+ * @description Create a packaged Cocoon web application (.war file) based on a
+ *              block deployment descriptor.
+ */
+public class DeployWarMojo extends AbstractDeployMojo {
+
+    /**
+     * The directory for the generated WAR.
+     * 
+     * @parameter expression="${project.build.directory}"
+     * @required
+     */
+    private String outputDirectory;
+
+    /**
+     * The name of the generated war.
+     * 
+     * @parameter expression="${project.build.finalName}"
+     * @required
+     */
+    private String warName;
+
+    /**
+     * The Jar archiver.
+     * 
+     * @parameter expression="${component.org.codehaus.plexus.archiver.Archiver#war}"
+     * @required
+     */
+    private WarArchiver warArchiver;
+
+    /**
+     * The maven archive configuration to use.
+     * 
+     * @parameter
+     */
+    private MavenArchiveConfiguration archive = new MavenArchiveConfiguration();
+
+    public void execute() throws MojoExecutionException, MojoFailureException {
+        File warFile = new File(outputDirectory, warName + ".war");
+        this.deployWebapp();
+
+        try {
+            performPackaging(warFile);
+        } catch (Exception e) {
+            // TODO: improve error handling
+            throw new MojoExecutionException("Error assembling WAR", e);
+        }
+    }
+
+    /**
+     * Generates the webapp according to the <tt>mode</tt> attribute.
+     * 
+     * @param warFile
+     *            the target war file
+     * @throws IOException
+     * @throws ArchiverException
+     * @throws ManifestException
+     * @throws DependencyResolutionRequiredException
+     */
+    private void performPackaging(File warFile) throws IOException, ArchiverException, ManifestException,
+            DependencyResolutionRequiredException, MojoExecutionException {
+        getLog().info("Generating war " + warFile.getAbsolutePath());
+
+        MavenArchiver archiver = new MavenArchiver();
+        archiver.setArchiver(warArchiver);
+        archiver.setOutputFile(warFile);
+        warArchiver.addDirectory(getWebappDirectory(), getIncludes(), getExcludes());
+        warArchiver.setWebxml(new File(getWebappDirectory(), "WEB-INF/web.xml"));
+
+        // create archive
+        archiver.createArchive(getProject(), archive);
+        getProject().getArtifact().setFile(warFile);
+    }
+
+}
\ No newline at end of file

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/DeployWarMojo.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/DeployWarMojo.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/DeployWarMojo.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/WebApplicationRewriter.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/WebApplicationRewriter.java?view=auto&rev=534014
==============================================================================
--- cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/WebApplicationRewriter.java (added)
+++ cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/WebApplicationRewriter.java Tue May  1 04:35:26 2007
@@ -0,0 +1,348 @@
+/*
+ * 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.cocoon.maven.deployer;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.JarURLConnection;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+
+import org.apache.cocoon.maven.deployer.servlet.ShieldedClassLoaderManager;
+import org.apache.cocoon.maven.deployer.servlet.ShieldingListener;
+import org.apache.cocoon.maven.deployer.servlet.ShieldingServlet;
+import org.apache.cocoon.maven.deployer.servlet.ShieldingServletFilter;
+import org.apache.cocoon.maven.deployer.utils.XMLUtils;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.logging.Log;
+import org.codehaus.plexus.util.FileUtils;
+import org.codehaus.plexus.util.IOUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * @version $Id$
+ */
+public class WebApplicationRewriter {
+
+    protected static final String SERVLET_CLASS = ShieldingServlet.class.getName();
+
+    protected static final String LISTENER_CLASS = ShieldingListener.class.getName();
+
+    protected static final String FILTER_CLASS = ShieldingServletFilter.class.getName();
+
+    protected static final String CLASSLOADER_JAR = "cocoon-deployer-plugin-classloading.jar";
+
+    protected static final String JAR_ENTRY_PREFIX = ShieldedClassLoaderManager.class.getPackage().getName().replace('.', '/');
+
+    /**
+     * Prepare the web application to use the shielded class loader.
+     * The web.xml will be rewritten: all servlets, filters etc. are wrapped
+     * by a wrapper which uses the shielded class loader.
+     * In addition all libs are moved from WEB-INF/lib to WEB-INF/shielded/lib
+     * and all files from WEB-INF/classes are moved to WEB-INF/shielded/classes.
+     */
+    public static void shieldWebapp(File webInfDir, Log log, boolean useShieldingRepository)
+    throws MojoExecutionException {
+        if ( log.isDebugEnabled() ) {
+            log.debug("Shielding web application in " + webInfDir);
+        }
+        final String webInfSlashWebXml = webInfDir.getPath() + File.separatorChar + "web.xml";
+
+        if (!new File(webInfSlashWebXml).exists()) {
+            throw new MojoExecutionException("No web.xml present - can't add shielded class loading");
+        }
+        log.info("Adding shielded classloader configuration to web application configuration.");
+        if ( log.isDebugEnabled() ) {
+            log.debug("Reading web.xml: " + webInfSlashWebXml);
+        }
+
+        // load web.xml
+        InputStream is = null;
+        final Document webAppDoc;
+        try {
+            is = new BufferedInputStream(new FileInputStream(new File(webInfSlashWebXml)));
+            webAppDoc = XMLUtils.parseXml(is);
+        } catch (Exception e) {
+            throw new MojoExecutionException("Unable to read web.xml from " + webInfSlashWebXml, e);
+        } finally {
+            if ( is != null ) {
+                try {
+                    is.close();
+                } catch (IOException ignore) {
+                    // ignore
+                }
+            }
+        }
+
+        // rewrite
+        if ( WebApplicationRewriter.rewrite(webAppDoc, useShieldingRepository) ) {
+
+            // save web.xml
+            try {
+                if ( log.isDebugEnabled() ) {
+                    log.debug("Writing web.xml: " + webInfSlashWebXml);
+                }
+                XMLUtils.write(webAppDoc, new FileOutputStream(webInfSlashWebXml));
+            } catch (Exception e) {
+                throw new MojoExecutionException("Unable to write web.xml to " + webInfSlashWebXml, e);
+            }
+        }
+
+        // move classes and libs
+        if (useShieldingRepository) {
+            log.info("Moving classes and libs to shielded location.");
+            try {
+                move(webInfDir, "lib", ShieldedClassLoaderManager.WEB_INF_SHIELDED_LIB, log);
+                move(webInfDir, "classes", ShieldedClassLoaderManager.WEB_INF_SHIELDED_CLASSES, log);
+            } catch (IOException e) {
+                throw new MojoExecutionException("unable to shield classes/libs", e);
+            }
+        }
+
+        // add classloading stuff to WEB-INF/lib
+        // let's search our jar
+        final String rsrc = ShieldedClassLoaderManager.class.getName().replace('.', '/') + ".class";
+        if ( log.isDebugEnabled() ) {
+            log.debug("Searching class file for: " + rsrc);
+        }
+        try {
+            final Enumeration e = WebApplicationRewriter.class.getClassLoader().getResources(rsrc);
+            boolean found = false;
+            while ( e.hasMoreElements() ) {
+                final URL url = (URL)e.nextElement();
+                if ( log.isDebugEnabled() ) {
+                    log.debug("Found class in " + url);
+                }
+                if ( url.getProtocol().equals("jar")) {
+                    String jarUrlString = url.toExternalForm();
+                    int pos = jarUrlString.indexOf('!');
+                    // include !/
+                    jarUrlString = jarUrlString.substring(0, pos + 2);
+                    final URL jarUrl = new URL(jarUrlString);
+                    final JarURLConnection connection = (JarURLConnection)jarUrl.openConnection();
+                    final JarFile jarFile = connection.getJarFile();
+                    final File destFile = new File(webInfDir, "lib" + File.separator + CLASSLOADER_JAR);
+                    final JarOutputStream jos = new JarOutputStream(new FileOutputStream(destFile));
+                    final Enumeration entries = jarFile.entries();
+                    while ( entries.hasMoreElements() ) {
+                        final JarEntry current = (JarEntry)entries.nextElement();
+                        // only include classes from the shielded class loader package
+                        if ( current.getName().startsWith(JAR_ENTRY_PREFIX) ) {
+                            jos.putNextEntry(current);
+                            IOUtil.copy(jarFile.getInputStream(current), jos);
+                            jos.closeEntry();
+                        }
+                    }
+                    jos.close();
+                    found = true;
+                }
+            }
+            if (!found) {
+                throw new MojoExecutionException("Unable to find jar file for shielded class loading classes.");
+            }
+        } catch (IOException ioe) {
+            throw new MojoExecutionException("unable to find classes for shielded class loading.", ioe);            
+        }
+    }
+
+    private static void move(File parentDir, String srcDir, String destDirOrig, Log log) throws IOException {
+        String destDir = destDirOrig;
+        // use correct separators on windows
+        if ( File.separatorChar != '/' ) {
+            destDir = destDir.replace('/', File.separatorChar);
+        }
+        final File srcDirectory = new File(parentDir, srcDir);
+        if (srcDirectory.exists() && srcDirectory.isDirectory()) {
+            File destDirectory = new File(parentDir, destDir);
+            if (log.isDebugEnabled()) {
+                log.debug("Deleting directory " + destDirectory);
+            }
+            FileUtils.deleteDirectory(destDirectory);
+            destDirectory = new File(parentDir, destDir);
+            if (log.isDebugEnabled()) {
+                log.debug("Recreating directory " + destDirectory);
+            }
+            destDirectory.mkdirs();
+            final File[] files = srcDirectory.listFiles();
+            if (files != null && files.length > 0) {
+                for (int i = 0; i < files.length; i++) {
+                    // move everything but our own jar
+                    if ( !files[i].getName().equals(CLASSLOADER_JAR) ) {
+                        if (log.isDebugEnabled()) {
+                            log.debug("Moving " + files[i] + " to " + destDirectory);
+                        }
+                        files[i].renameTo(new File(destDirectory, files[i].getName()));
+                    }
+                }
+            }
+        }
+    }
+
+    public static boolean rewrite(Document webAppDoc, boolean useShieldingRepository) {
+        boolean rewritten = false;
+        final Element rootElement = webAppDoc.getDocumentElement();
+        // first rewrite servlets
+        final List servlets = XMLUtils.getChildNodes(rootElement, "servlet");
+        Iterator i = servlets.iterator();
+        while ( i.hasNext() ) {
+            final Element servletElement = (Element)i.next();
+            final Element servletClassElement = XMLUtils.getChildNode(servletElement, "servlet-class");
+            if ( servletClassElement != null ) {
+                final String className = XMLUtils.getValue(servletClassElement);
+                XMLUtils.setValue(servletClassElement, SERVLET_CLASS);
+                // create init-param with real servlet class
+                final Element initParamElem = webAppDoc.createElementNS(null, "init-param");
+                final Element initParamNameElem = webAppDoc.createElementNS(null, "param-name");
+                final Element initParamValueElem = webAppDoc.createElementNS(null, "param-value");
+                initParamElem.appendChild(initParamNameElem);
+                initParamElem.appendChild(initParamValueElem);
+                XMLUtils.setValue(initParamNameElem, "servlet-class");
+                XMLUtils.setValue(initParamValueElem, className);
+                Element beforeElement = XMLUtils.getChildNode(servletElement, "load-on-startup");
+                if ( beforeElement == null ) {
+                    beforeElement = XMLUtils.getChildNode(servletElement, "run-as");                    
+                    if ( beforeElement == null ) {
+                        beforeElement = XMLUtils.getChildNode(servletElement, "security-role-ref");                    
+                    }
+                }
+                if ( beforeElement == null ) {
+                    servletElement.appendChild(initParamElem);
+                } else {
+                    servletElement.insertBefore(initParamElem, beforeElement);
+                }
+                rewritten = true;
+            }
+        }
+
+        // now rewrite listeners
+        final List listeners = XMLUtils.getChildNodes(rootElement, "listener");
+        i = listeners.iterator();
+        boolean hasListener = false;
+        final StringBuffer rewrittenListeners = new StringBuffer();
+        while ( i.hasNext() ) {
+            final Element listenerElement = (Element)i.next();
+            final Element listenerClassElement = XMLUtils.getChildNode(listenerElement, "listener-class");
+            if ( listenerClassElement != null ) {
+                final String className = XMLUtils.getValue(listenerClassElement);
+                if ( rewrittenListeners.length() > 0 ) {
+                    rewrittenListeners.append(',');
+                }
+                rewrittenListeners.append(className);
+                if ( hasListener ) {
+                    rootElement.removeChild(listenerElement);                        
+                } else {
+                    XMLUtils.setValue(listenerClassElement, LISTENER_CLASS);
+                    hasListener = true;
+                }
+                rewritten = true;
+            }
+        }
+        // remove old parameter
+        i = XMLUtils.getChildNodes(rootElement, "context-param").iterator();
+        while ( i.hasNext() ) {
+            final Element child = (Element)i.next();
+            if ( LISTENER_CLASS.equals(XMLUtils.getValue(XMLUtils.getChildNode(child, "param-name")))) {
+                rootElement.removeChild(child);
+            }
+        }
+        if ( hasListener ) {
+            addContextParameter(rootElement, LISTENER_CLASS, rewrittenListeners.toString());
+        }
+
+        // and now filters
+        i = XMLUtils.getChildNodes(rootElement, "filter").iterator();
+        while ( i.hasNext() ) {
+            final Element filterElement = (Element)i.next();
+            final Element filterClassElement = XMLUtils.getChildNode(filterElement, "filter-class");
+            if ( filterClassElement != null ) {
+                final String className = XMLUtils.getValue(filterClassElement);
+                XMLUtils.setValue(filterClassElement, FILTER_CLASS);
+                // create init-param with real servlet class
+                final Element initParamElem = webAppDoc.createElementNS(null, "init-param");
+                final Element initParamNameElem = webAppDoc.createElementNS(null, "param-name");
+                final Element initParamValueElem = webAppDoc.createElementNS(null, "param-value");
+                initParamElem.appendChild(initParamNameElem);
+                initParamElem.appendChild(initParamValueElem);
+                XMLUtils.setValue(initParamNameElem, "filter-class");
+                XMLUtils.setValue(initParamValueElem, className);
+                filterElement.appendChild(initParamElem);
+                rewritten = true;
+            }
+        }
+
+        if ( !useShieldingRepository ) {
+            addContextParameter(rootElement,
+                                ShieldedClassLoaderManager.SHIELDED_CLASSLOADER_USE_REPOSITORY,
+                                "false");
+            rewritten = true;
+        } else {
+            if ( removeContextParameter(rootElement, ShieldedClassLoaderManager.SHIELDED_CLASSLOADER_USE_REPOSITORY) ) {
+                rewritten = true;
+            }
+        }
+
+        return rewritten;
+    }
+
+    protected static boolean removeContextParameter(Element root, String name) {
+        boolean removed = false;
+        final Iterator i = XMLUtils.getChildNodes(root, "context-param").iterator();
+        while ( !removed && i.hasNext() ) {
+            final Element parameterElement = (Element)i.next();
+            final String paramName = XMLUtils.getValue(XMLUtils.getChildNode(parameterElement, "param-name"));
+            if ( name.equals(paramName) ) {
+                parameterElement.getParentNode().removeChild(parameterElement);
+                removed = true;
+            }
+        }
+        return removed;
+    }
+
+    protected static void addContextParameter(Element root, String name, String value) {
+        removeContextParameter(root, name);
+        // search the element where we have to put the new context parameter before!
+        // we know that we have listeners so this is the last element to search for
+        Element searchElement = XMLUtils.getChildNode(root, "context-param");
+        if ( searchElement == null ) {
+            searchElement = XMLUtils.getChildNode(root, "filter");
+            if ( searchElement == null ) {
+                searchElement = XMLUtils.getChildNode(root, "filter-mapping");
+                if ( searchElement == null ) {
+                    searchElement = XMLUtils.getChildNode(root, "listener");
+                }
+            }
+        }
+        final Element contextParamElement = root.getOwnerDocument().createElementNS(null, "context-param");
+        final Element contextParamNameElement = root.getOwnerDocument().createElementNS(null, "param-name");
+        final Element contextParamValueElement = root.getOwnerDocument().createElementNS(null, "param-value");
+        contextParamElement.appendChild(contextParamNameElement);
+        contextParamElement.appendChild(contextParamValueElement);
+        XMLUtils.setValue(contextParamNameElement, name);
+        XMLUtils.setValue(contextParamValueElement, value);
+        root.insertBefore(contextParamElement, searchElement);
+    }
+}
\ No newline at end of file

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/WebApplicationRewriter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/WebApplicationRewriter.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/WebApplicationRewriter.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/DeploymentException.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/DeploymentException.java?view=auto&rev=534014
==============================================================================
--- cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/DeploymentException.java (added)
+++ cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/DeploymentException.java Tue May  1 04:35:26 2007
@@ -0,0 +1,33 @@
+/*
+ * 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.cocoon.maven.deployer.monolithic;
+
+
+/**
+ * Unchecked exception that signals a problem at block deployment.
+ */
+public class DeploymentException extends RuntimeException {
+
+	public DeploymentException(String message) {
+		super(message);
+	}
+
+	public DeploymentException(String message, Exception ex) {
+		super(message, ex);
+	}
+
+}

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/DeploymentException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/DeploymentException.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/DeploymentException.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/FileAlreadyDeployedException.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/FileAlreadyDeployedException.java?view=auto&rev=534014
==============================================================================
--- cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/FileAlreadyDeployedException.java (added)
+++ cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/FileAlreadyDeployedException.java Tue May  1 04:35:26 2007
@@ -0,0 +1,30 @@
+/*
+ * 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.cocoon.maven.deployer.monolithic;
+
+/**
+ * Use it to indicate that a file has already been deployed.
+ * 
+ * @version $Id$
+ */
+public class FileAlreadyDeployedException extends DeploymentException {
+
+	public FileAlreadyDeployedException(String message) {
+		super(message);
+	}
+
+}

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/FileAlreadyDeployedException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/FileAlreadyDeployedException.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/FileAlreadyDeployedException.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/FileDeployer.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/FileDeployer.java?view=auto&rev=534014
==============================================================================
--- cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/FileDeployer.java (added)
+++ cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/FileDeployer.java Tue May  1 04:35:26 2007
@@ -0,0 +1,44 @@
+/*
+ * 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.cocoon.maven.deployer.monolithic;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Set;
+
+import org.apache.maven.plugin.logging.Log;
+
+/**
+ * Use this interface for classes that are used by the @link org.apache.cocoon.maven.deployer.monolithic.ZipExtractor
+ * to extract ZIP files. Classes implementing this interface can be added together with a rule to the
+ * @link org.apache.cocoon.maven.deployer.monolithic.ZipExtractor and when the rule matches, the execute method
+ * is called.
+ * 
+ * @version $Id$
+ */
+public interface FileDeployer {
+
+	OutputStream writeResource(String documentName) throws IOException;
+
+	void setBasedir(File file);
+
+	void setLogger(Log logger);
+
+	void setAlreadyDeployedFilesSet(Set alreadyDeployedFilesSet);
+	
+}

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/FileDeployer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/FileDeployer.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/FileDeployer.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/MonolithicCocoonDeployer.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/MonolithicCocoonDeployer.java?view=auto&rev=534014
==============================================================================
--- cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/MonolithicCocoonDeployer.java (added)
+++ cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/MonolithicCocoonDeployer.java Tue May  1 04:35:26 2007
@@ -0,0 +1,85 @@
+/*
+ * 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.cocoon.maven.deployer.monolithic;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.maven.plugin.logging.Log;
+
+/**
+ * Deploy blocks to a monolithic Cocoon web application. The files contained by
+ * a block are copied based on rules to the right places.
+ * 
+ * @version $Id: MonolithicCocoonDeployer.java 438198 2006-08-29 20:38:09Z
+ *          lgawron $
+ */
+public class MonolithicCocoonDeployer {
+
+    private Log logger;
+
+    public MonolithicCocoonDeployer(Log logger) {
+        this.logger = logger;
+    }
+
+    public void deploy(final Map libraries, final File basedir) throws DeploymentException {
+        XPatchDeployer xwebPatcher = new XPatchDeployer("WEB-INF");
+        xwebPatcher.setLogger(logger);
+        // iterate over all blocks that need to be installed into a J2EE web
+        // application
+        for (Iterator it = libraries.entrySet().iterator(); it.hasNext();) {
+            final Map.Entry entry = (Map.Entry) it.next();
+            final Object id = entry.getKey();
+            File lib = (File) entry.getValue();
+            try {
+                this.logger.info("Deploying " + id);
+                RuleBasedZipExtractor zipExtractor = new RuleBasedZipExtractor(basedir, logger);
+
+                // TODO clearly a hack, there should be a parameter what part of
+                // source path should be removed, the rest should stay
+                // preserving directory structure (currently only filename
+                // stays)
+                zipExtractor.addRule("WEB-INF/db/**", new SingleFileDeployer("WEB-INF/db"));
+                zipExtractor.addRule("META-INF/xpatch/*.xweb", xwebPatcher);
+
+                // extract all configurations files
+                zipExtractor.extract(lib);
+            } catch (IOException e) {
+                throw new DeploymentException("Can't deploy '" + lib.getAbsolutePath() + "'.", e);
+            }
+        }
+
+        InputStream sourceWebXmlFile = null;
+        File webXml = new File(basedir, "WEB-INF/web.xml");
+        try {
+            sourceWebXmlFile = new FileInputStream(webXml);
+            xwebPatcher.applyPatches(sourceWebXmlFile, "WEB-INF/web.xml");
+        } catch (FileNotFoundException e) {
+            throw new DeploymentException("Can't apply patches on " + webXml + ".", e);
+        } finally {
+            IOUtils.closeQuietly(sourceWebXmlFile);
+        }
+
+    }
+
+}

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/MonolithicCocoonDeployer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/MonolithicCocoonDeployer.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/MonolithicCocoonDeployer.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/RuleBasedZipExtractor.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/RuleBasedZipExtractor.java?view=auto&rev=534014
==============================================================================
--- cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/RuleBasedZipExtractor.java (added)
+++ cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/RuleBasedZipExtractor.java Tue May  1 04:35:26 2007
@@ -0,0 +1,130 @@
+/*
+ * 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.cocoon.maven.deployer.monolithic;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.apache.cocoon.maven.deployer.utils.WildcardHelper;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.Validate;
+import org.apache.maven.plugin.logging.Log;
+
+/**
+ * This class performs the actual deployment based on rules. A rule is mapped to
+ * a <code>FileDeployer</code> and when the rule is executed and returns true,
+ * the file deployer is executed.
+ * 
+ * @version $Id$
+ */
+public class RuleBasedZipExtractor {
+    private Log logger;
+    private File basedir;
+    private List rules = new ArrayList();
+    private Set alreadyDeployedFilesSet = new HashSet();
+
+    public RuleBasedZipExtractor(File basedir, Log logger) {
+        Validate.notNull(basedir, "The basedir of the server mustn't be null.");
+        Validate.notNull(logger, "A logger must be set.");
+        this.basedir = basedir;
+        this.logger = logger;
+        this.logger.debug("Basedir: " + basedir.getAbsolutePath());
+    }
+
+    public void addRule(String pattern, FileDeployer fileDeployer) {
+        fileDeployer.setBasedir(this.basedir);
+        fileDeployer.setLogger(this.logger);
+        fileDeployer.setAlreadyDeployedFilesSet(alreadyDeployedFilesSet);
+        rules.add(new Rule(pattern, fileDeployer));
+    }
+
+    public void extract(File zipFile) throws IOException {
+        ZipInputStream zipStream = new ZipInputStream(new FileInputStream(zipFile));
+        ZipEntry document = null;
+        try {
+            do {
+                document = zipStream.getNextEntry();
+                if (document != null) {
+                    // skip directories (only files have to be written)
+                    if (document.isDirectory()) {
+                        zipStream.closeEntry();
+                        continue;
+                    }
+                    OutputStream out = null;
+                    try {
+                        FileDeployer fileDeployer = findFileDeployer(document.getName());
+                        if (fileDeployer == null) {
+                            continue;
+                        }
+
+                        out = new BufferedOutputStream(fileDeployer.writeResource(document.getName()));
+                        IOUtils.copy(zipStream, out);
+                    } finally {
+                        if (out != null) {
+                            out.close();
+                        }
+                    }
+                    // go to next entry
+                    zipStream.closeEntry();
+                }
+            } while (document != null);
+        } finally {
+            zipStream.close();
+        }
+    }
+
+    /**
+     * Loop over all rules and if one matches, the corresponding
+     * 
+     * @link FileDeployer is returned.
+     */
+    protected FileDeployer findFileDeployer(String name) {
+        for (Iterator it = this.rules.iterator(); it.hasNext();) {
+            Rule rule = (Rule) it.next();
+            HashMap resultMap = new HashMap();
+            if (WildcardHelper.match(resultMap, name, rule.compiledPattern)) {
+                logger.debug("findFileDeployer: " + name + " matched with pattern '" + rule.patternString);
+                return rule.fileDeployer;
+            }
+        }
+        return null;
+    }
+
+    private static class Rule {
+        String patternString;
+        int[] compiledPattern;
+        FileDeployer fileDeployer;
+
+        public Rule(String pattern, FileDeployer fileDeployer) {
+            this.patternString = pattern;
+            this.compiledPattern = WildcardHelper.compilePattern(pattern);
+            this.fileDeployer = fileDeployer;
+        }
+    }
+
+}

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/RuleBasedZipExtractor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/RuleBasedZipExtractor.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/RuleBasedZipExtractor.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/SingleFileDeployer.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/SingleFileDeployer.java?view=auto&rev=534014
==============================================================================
--- cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/SingleFileDeployer.java (added)
+++ cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/SingleFileDeployer.java Tue May  1 04:35:26 2007
@@ -0,0 +1,112 @@
+/*
+ * 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.cocoon.maven.deployer.monolithic;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Set;
+
+import org.apache.cocoon.maven.deployer.utils.FileUtils;
+import org.apache.commons.lang.Validate;
+import org.apache.maven.plugin.logging.Log;
+
+/**
+ * Deploy a single file.
+ * 
+ * @version $Id$
+ */
+public class SingleFileDeployer implements FileDeployer {
+    private File basedir;
+    private Log logger;
+    private String outputDir;
+    private boolean skipRootDirectory;
+    private Set alreadyDeployedFilesSet;
+
+    public SingleFileDeployer(final String outputDir, final boolean skipRootDirectory) {
+        Validate.notNull(outputDir, "An outputDir has to be set.");
+        this.outputDir = outputDir;
+        this.skipRootDirectory = skipRootDirectory;
+    }
+
+    public SingleFileDeployer(final String outputDir) {
+        this(outputDir, false);
+    }
+
+    public void setBasedir(final File basedir) {
+        this.basedir = basedir;
+    }
+
+    protected File getBasedir() {
+        return this.basedir;
+    }
+
+    public void setLogger(final Log logger) {
+        this.logger = logger;
+    }
+
+    protected Log getLogger() {
+        return this.logger;
+    }
+
+    public void setAlreadyDeployedFilesSet(Set alreadyDeployedFilesSet) {
+        this.alreadyDeployedFilesSet = alreadyDeployedFilesSet;
+    }
+
+    protected String getFileName(final String documentName) {
+        return documentName.substring(documentName.lastIndexOf('/') + 1);
+    }
+
+    protected String getOutputDir() {
+        return this.outputDir;
+    }
+
+    public OutputStream writeResource(final String documentName) throws IOException {
+        File outDir = new File(this.getBasedir(), getOutputDir());
+        if (!outDir.exists()) {
+            outDir.mkdirs();
+        }
+
+        String outputDocumentName = documentName;
+        // if the root directory is has to be skipped, the remaining path will
+        // be used
+        if (this.skipRootDirectory) {
+            outputDocumentName = removeRootDirectory(documentName);
+            this.logger.debug("Changing output document name from '" + documentName + "', to '" + outputDocumentName
+                    + "'.");
+        }
+        // only take the filename
+        else {
+            outputDocumentName = this.getFileName(documentName);
+        }
+
+        File targetFile = FileUtils.createPath(new File(outDir, outputDocumentName));
+        if (this.alreadyDeployedFilesSet.contains(targetFile.getCanonicalFile())) {
+            throw new FileAlreadyDeployedException("File '" + targetFile + "' already exists!");
+        }
+
+        this.alreadyDeployedFilesSet.add(targetFile.getCanonicalFile());
+        this.logger.debug("Deploying block resource to " + getOutputDir() + "/" + outputDocumentName);
+
+        return new FileOutputStream(FileUtils.createPath(targetFile));
+    }
+
+    protected String removeRootDirectory(final String documentName) {
+        return documentName.substring(documentName.indexOf('/') + 1);
+    }
+}

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/SingleFileDeployer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/SingleFileDeployer.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/SingleFileDeployer.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/XPatchDeployer.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/XPatchDeployer.java?view=auto&rev=534014
==============================================================================
--- cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/XPatchDeployer.java (added)
+++ cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/XPatchDeployer.java Tue May  1 04:35:26 2007
@@ -0,0 +1,232 @@
+/*
+ * 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.cocoon.maven.deployer.monolithic;
+
+import java.io.BufferedOutputStream;
+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.io.OutputStream;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import javax.xml.parsers.ParserConfigurationException;
+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.cocoon.maven.deployer.utils.CopyUtils;
+import org.apache.cocoon.maven.deployer.utils.FileUtils;
+import org.apache.cocoon.maven.deployer.utils.XMLUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.xpath.XPathAPI;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+// TODO should this extend SingleFileDeployer at all?
+// TODO decouple patch collecting from logic that applies patches
+public class XPatchDeployer extends SingleFileDeployer {
+    final List patches = new Vector();
+
+    public XPatchDeployer(String outputDir) {
+        super(outputDir, false);
+    }
+
+    public OutputStream writeResource(String documentName) throws IOException {
+        getLogger().debug("catching patch: " + documentName);
+        PatchCachingOutputStream out = new PatchCachingOutputStream(documentName);
+        patches.add(out);
+        return out;
+    }
+
+    public void addPatch(File file) throws IOException {
+        getLogger().debug("catching patch: " + file.getAbsolutePath());
+        PatchCachingOutputStream pcis = new PatchCachingOutputStream(file.getCanonicalPath());
+        CopyUtils.copy(new FileInputStream(file), pcis);
+        patches.add(pcis);
+    }
+
+    public void applyPatches(InputStream source, final String fileName) {
+        if (patches.size() == 0) {
+            // TODO should just copy the file without any transform
+        }
+        try {
+            getLogger().info("Applying patches to: " + fileName);
+            Document original = XMLUtils.parseXml(source);
+            File outFile = FileUtils.createPath(new File(getBasedir(), fileName));
+
+            Iterator it = patches.iterator();
+            while (it.hasNext()) {
+                PatchCachingOutputStream pcis = (PatchCachingOutputStream) it.next();
+                Document component = (pcis).getPatch();
+
+                Element elem = component.getDocumentElement();
+                if (!elem.getTagName().equals("xweb")) {
+                    throw new DeploymentException("not a valid xweb patch file: " + pcis.getDocumentName());
+                }
+
+                String xpath = elem.getAttribute("xpath");
+                if (xpath == null) {
+                    throw new DeploymentException("no xpath parameter in patch file: " + pcis.getDocumentName());
+                }
+
+                NodeList nodes = XPathAPI.selectNodeList(original, xpath);
+
+                if (nodes.getLength() == 0) {
+                    throw new DeploymentException("no matches for xpath: [" + xpath + "] in patch file: "
+                            + pcis.getDocumentName());
+                }
+                if (nodes.getLength() > 1) {
+                    throw new DeploymentException("multiple matches for xpath: [" + xpath + "] in patch file: "
+                            + pcis.getDocumentName());
+                }
+
+                Node root = nodes.item(0);
+                // Test that 'root' node satisfies 'component'
+                // insertion criteria
+                String testPath = elem.getAttribute("unless-path");
+                if (testPath == null || testPath.length() == 0) {
+                    // only look for old "unless" attr if
+                    // unless-path is not present
+                    testPath = elem.getAttribute("unless");
+                }
+
+                if (testPath != null && testPath.length() > 0 && XPathAPI.eval(root, testPath).bool()) {
+                    // no test path or 'unless' condition is satisfied
+                    getLogger().debug("skipping application of patch file: " + pcis.getDocumentName());
+                } else {
+                    // Test if component wants us to remove
+                    // a list of nodes first
+                    xpath = elem.getAttribute("remove");
+                    if (xpath != null && xpath.length() > 0) {
+                        nodes = XPathAPI.selectNodeList(original, xpath);
+                        for (int i = 0, length = nodes.getLength(); i < length; i++) {
+                            Node node = nodes.item(i);
+                            Node parent = node.getParentNode();
+                            parent.removeChild(node);
+                        }
+                    }
+                    // Test for an attribute that needs to be
+                    // added to an element
+                    String name = elem.getAttribute("add-attribute");
+                    String value = elem.getAttribute("value");
+
+                    if (name != null && name.length() > 0 && value != null && root instanceof Element) {
+                        ((Element) root).setAttribute(name, value);
+                    }
+
+                    // Allow multiple attributes to be added or
+                    // modified
+                    if (root instanceof Element) {
+                        NamedNodeMap attrMap = elem.getAttributes();
+                        for (int i = 0; i < attrMap.getLength(); ++i) {
+                            Attr attr = (Attr) attrMap.item(i);
+                            final String addAttr = "add-attribute-";
+                            if (attr.getName().startsWith(addAttr)) {
+                                String key = attr.getName().substring(addAttr.length());
+                                ((Element) root).setAttribute(key, attr.getValue());
+                            }
+                        }
+                    }
+
+                    // Test if 'component' provides desired
+                    // insertion point
+                    xpath = elem.getAttribute("insert-before");
+                    Node before = null;
+
+                    if (xpath != null && xpath.length() > 0) {
+                        nodes = XPathAPI.selectNodeList(root, xpath);
+                        if (nodes.getLength() != 0) {
+                            before = nodes.item(0);
+                        }
+                    } else {
+                        xpath = elem.getAttribute("insert-after");
+                        if (xpath != null && xpath.length() > 0) {
+                            nodes = XPathAPI.selectNodeList(root, xpath);
+                            if (nodes.getLength() != 0) {
+                                before = nodes.item(nodes.getLength() - 1).getNextSibling();
+                            }
+                        }
+                    }
+
+                    NodeList componentNodes = component.getDocumentElement().getChildNodes();
+                    for (int i = 0; i < componentNodes.getLength(); i++) {
+                        Node node = original.importNode(componentNodes.item(i), true);
+
+                        if (before == null) {
+                            root.appendChild(node);
+                        } else {
+                            root.insertBefore(node, before);
+                        }
+                    }
+                }
+            }
+
+            TransformerFactory tFactory = TransformerFactory.newInstance();
+            Transformer transformer = tFactory.newTransformer();
+            OutputStream os = new BufferedOutputStream(new FileOutputStream(outFile));
+            try {
+                getLogger().debug("Deploying resource file to " + fileName);
+                transformer.transform(new DOMSource(original), new StreamResult(os));
+            } finally {
+                IOUtils.closeQuietly(os);
+            }
+        } catch (FileNotFoundException e) {
+            throw new DeploymentException("Can't write to nonexistant file " + fileName, e);
+        } catch (IOException e) {
+            throw new DeploymentException("Can't write to " + fileName, e);
+        } catch (ParserConfigurationException e) {
+            throw new DeploymentException("Unable to configure parser " + fileName, e);
+        } catch (SAXException e) {
+            throw new DeploymentException("Unable to parse XML " + fileName, e);
+        } catch (TransformerConfigurationException e) {
+            throw new DeploymentException("Unable to configure transformer " + fileName, e);
+        } catch (TransformerException e) {
+            throw new DeploymentException("Unable to transform XML " + fileName, e);
+        }
+    }
+
+    private class PatchCachingOutputStream extends ByteArrayOutputStream {
+        private String documentName;
+
+        public String getDocumentName() {
+            return documentName;
+        }
+
+        public PatchCachingOutputStream(String documentName) {
+            this.documentName = documentName;
+        }
+
+        public Document getPatch() throws SAXException, IOException, ParserConfigurationException {
+            return XMLUtils.parseXml(new ByteArrayInputStream(this.buf, 0, this.count));
+        }
+    }
+}

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/XPatchDeployer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/XPatchDeployer.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/trunk/tools/cocoon-maven-plugin/src/main/java/org/apache/cocoon/maven/deployer/monolithic/XPatchDeployer.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain