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 }