/* * 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.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; 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"); 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 Map of java.io.File 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; } }