001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 020 package org.apache.geronimo.mavenplugins.car; 021 022 import java.io.File; 023 import java.net.URI; 024 import java.util.ArrayList; 025 import java.util.Arrays; 026 import java.util.HashMap; 027 import java.util.HashSet; 028 import java.util.Iterator; 029 import java.util.List; 030 import java.util.Set; 031 032 import org.apache.geronimo.deployment.PluginBootstrap2; 033 import org.apache.geronimo.gbean.AbstractName; 034 import org.apache.geronimo.gbean.AbstractNameQuery; 035 import org.apache.geronimo.gbean.GBeanData; 036 import org.apache.geronimo.gbean.GBeanInfo; 037 import org.apache.geronimo.gbean.ReferencePatterns; 038 import org.apache.geronimo.kernel.Kernel; 039 import org.apache.geronimo.kernel.KernelFactory; 040 import org.apache.geronimo.kernel.KernelRegistry; 041 import org.apache.geronimo.kernel.Naming; 042 import org.apache.geronimo.kernel.config.ConfigurationData; 043 import org.apache.geronimo.kernel.config.ConfigurationManager; 044 import org.apache.geronimo.kernel.config.ConfigurationUtil; 045 import org.apache.geronimo.kernel.config.KernelConfigurationManager; 046 import org.apache.geronimo.kernel.config.LifecycleException; 047 import org.apache.geronimo.kernel.config.RecordingLifecycleMonitor; 048 import org.apache.geronimo.kernel.log.GeronimoLogging; 049 import org.apache.geronimo.kernel.management.State; 050 import org.apache.geronimo.kernel.repository.DefaultArtifactManager; 051 import org.apache.geronimo.system.configuration.RepositoryConfigurationStore; 052 import org.apache.geronimo.system.repository.Maven2Repository; 053 import org.apache.geronimo.system.resolver.ExplicitDefaultArtifactResolver; 054 import org.apache.maven.archiver.MavenArchiveConfiguration; 055 import org.apache.maven.archiver.MavenArchiver; 056 import org.apache.maven.artifact.Artifact; 057 import org.apache.maven.artifact.factory.ArtifactFactory; 058 import org.apache.maven.plugin.MojoExecutionException; 059 import org.apache.maven.project.MavenProject; 060 import org.codehaus.mojo.pluginsupport.dependency.DependencyTree; 061 import org.codehaus.mojo.pluginsupport.util.ArtifactItem; 062 import org.codehaus.plexus.archiver.jar.JarArchiver; 063 import org.codehaus.plexus.util.FileUtils; 064 065 /** 066 * Jar up a packaged plugin 067 * 068 * @goal archive-car 069 * @requiresDependencyResolution runtime 070 * 071 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $ 072 */ 073 public class ArchiveCarMojo 074 extends AbstractCarMojo 075 { 076 077 /** 078 * The maven archive configuration to use. 079 * 080 * See <a href="http://maven.apache.org/ref/current/maven-archiver/apidocs/org/apache/maven/archiver/MavenArchiveConfiguration.html">the Javadocs for MavenArchiveConfiguration</a>. 081 * 082 * @parameter 083 */ 084 private MavenArchiveConfiguration archive = new MavenArchiveConfiguration(); 085 086 /** 087 * The Jar archiver. 088 * 089 * @parameter expression="${component.org.codehaus.plexus.archiver.Archiver#jar}" 090 * @required 091 * @readonly 092 */ 093 private JarArchiver jarArchiver = null; 094 095 /** 096 * The module base directory. 097 * 098 * @parameter expression="${project.basedir}" 099 * @required 100 * @readonly 101 */ 102 private File baseDirectory = null; 103 104 /** 105 * Directory containing the generated archive. 106 * 107 * @parameter expression="${project.build.directory}" 108 * @required 109 */ 110 private File outputDirectory = null; 111 112 /** 113 * Directory containing the classes/resources. 114 * 115 * @parameter expression="${project.build.outputDirectory}" 116 * @required 117 */ 118 private File classesDirectory = null; 119 120 /** 121 * Name of the generated archive. 122 * 123 * @parameter expression="${project.build.finalName}" 124 * @required 125 */ 126 private String finalName = null; 127 128 /** 129 * The Geronimo repository where modules will be packaged up from. 130 * 131 * @parameter expression="${project.build.directory}/repository" 132 * @required 133 */ 134 private File targetRepository = null; 135 136 /** 137 * The location where the properties mapping will be generated. 138 * 139 * <p> 140 * Probably don't want to change this. 141 * </p> 142 * 143 * @parameter expression="${project.build.directory}/explicit-versions.properties" 144 */ 145 private File explicitResolutionProperties = null; 146 147 /** 148 * An array of {@link org.apache.geronimo.mavenplugins.car.ClasspathElement} objects which will be used to construct the 149 * Class-Path entry of the manifest. 150 * 151 * This is needed to allow per-element prefixes to be added, which the standard Maven archiver 152 * does not provide. 153 * 154 * @parameter 155 */ 156 private ClasspathElement[] classpath = null; 157 158 /** 159 * The default prefix to be applied to all elements of the <tt>classpath</tt> which 160 * do not provide a prefix. 161 * 162 * @parameter 163 */ 164 private String classpathPrefix = null; 165 166 /** 167 * Location of resources directory for additional content to include in the car. 168 * 169 * @parameter expression="${project.build.directory}/resources" 170 */ 171 private File resourcesDir; 172 173 // 174 // Mojo 175 // 176 177 protected void doExecute() throws Exception { 178 179 // Build the archive 180 File archive = createArchive(); 181 182 // Attach the generated archive for install/deploy 183 project.getArtifact().setFile(archive); 184 } 185 186 private File getArtifactInRepositoryDir() { 187 // 188 // HACK: Generate the filename in the repo... really should delegate this to the repo impl 189 // 190 191 File dir = new File(targetRepository, project.getGroupId().replace('.', '/')); 192 dir = new File(dir, project.getArtifactId()); 193 dir = new File(dir, project.getVersion()); 194 dir = new File(dir, project.getArtifactId() + "-" + project.getVersion() + ".car"); 195 196 return dir; 197 } 198 199 200 /** 201 * Generates the configuration archive. 202 */ 203 private File createArchive() throws MojoExecutionException { 204 File archiveFile = getArchiveFile(outputDirectory, finalName, null); 205 206 MavenArchiver archiver = new MavenArchiver(); 207 archiver.setArchiver(jarArchiver); 208 archiver.setOutputFile(archiveFile); 209 210 try { 211 // Incldue the generated artifact contents 212 archiver.getArchiver().addDirectory(getArtifactInRepositoryDir()); 213 214 // Include the optional classes.resources 215 if (classesDirectory.isDirectory()) { 216 archiver.getArchiver().addDirectory(classesDirectory); 217 } 218 219 if (resourcesDir.isDirectory()) { 220 archiver.getArchiver().addDirectory(resourcesDir); 221 } 222 223 // 224 // HACK: Include legal files here for sanity 225 // 226 227 // 228 // NOTE: Would be nice to share this with the copy-legal-files mojo 229 // 230 String[] includes = { 231 "LICENSE.txt", 232 "LICENSE", 233 "NOTICE.txt", 234 "NOTICE", 235 "DISCLAIMER.txt", 236 "DISCLAIMER" 237 }; 238 239 archiver.getArchiver().addDirectory(baseDirectory, "META-INF/", includes, new String[0]); 240 241 if (classpath != null) { 242 archive.addManifestEntry("Class-Path", getClassPath()); 243 } 244 245 archiver.createArchive(project, archive); 246 247 return archiveFile; 248 } 249 catch (Exception e) { 250 throw new MojoExecutionException("Failed to create archive", e); 251 } 252 } 253 254 private String getClassPath() throws MojoExecutionException { 255 StringBuffer buff = new StringBuffer(); 256 257 for (int i=0; i < classpath.length; i++) { 258 String entry = classpath[i].getEntry(); 259 if (entry != null) { 260 buff.append(entry); 261 } else { 262 Artifact artifact = getArtifact(classpath[i]); 263 264 // 265 // TODO: Need to optionally get all transitive dependencies... but dunno how to get that intel from m2 266 // 267 268 String prefix = classpath[i].getClasspathPrefix(); 269 if (prefix == null) { 270 prefix = classpathPrefix; 271 } 272 273 if (prefix != null) { 274 buff.append(prefix); 275 276 if (!prefix.endsWith("/")) { 277 buff.append("/"); 278 } 279 } 280 281 File file = artifact.getFile(); 282 buff.append(file.getName()); 283 } 284 285 if (i + 1< classpath.length) { 286 buff.append(" "); 287 } 288 } 289 290 log.debug("Using classpath: " + buff); 291 292 return buff.toString(); 293 } 294 295 }