001    /**
002     *
003     * Copyright 2005 The Apache Software Foundation
004     *
005     *  Licensed under the Apache License, Version 2.0 (the "License");
006     *  you may not use this file except in compliance with the License.
007     *  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    
018    package org.apache.geronimo.plugin.car;
019    
020    import java.io.File;
021    import java.util.ArrayList;
022    import java.util.List;
023    
024    import org.apache.geronimo.system.configuration.RepositoryConfigurationStore;
025    import org.apache.geronimo.system.repository.Maven2Repository;
026    
027    import org.apache.maven.archiver.MavenArchiveConfiguration;
028    import org.apache.maven.archiver.MavenArchiver;
029    import org.apache.maven.plugin.MojoExecutionException;
030    import org.apache.maven.artifact.Artifact;
031    
032    import org.codehaus.plexus.util.FileUtils;
033    import org.codehaus.plexus.archiver.jar.JarArchiver;
034    
035    /**
036     * Build a Geronimo Configuration using the local Maven infrastructure.
037     *
038     * <p>
039     * <b>NOTE:</b> Calling pom.xml must have defined a ${geronimoVersion} property.
040     * </p>
041     *
042     * @goal package
043     * @requiresDependencyResolution runtime
044     *
045     * @version $Rev: 434144 $ $Date: 2006-08-23 21:56:43 +0200 (mer., 23 août 2006) $
046     */
047    public class PackageMojo
048        extends AbstractCarMojo
049    {
050        /**
051         * The maven archive configuration to use.
052         *
053         * See <a href="http://maven.apache.org/ref/current/maven-archiver/apidocs/org/apache/maven/archiver/MavenArchiveConfiguration.html">the Javadocs for MavenArchiveConfiguration</a>.
054         *
055         * @parameter
056         */
057        private MavenArchiveConfiguration archive = new MavenArchiveConfiguration();
058    
059        /**
060         * The Jar archiver.
061         *
062         * @parameter expression="${component.org.codehaus.plexus.archiver.Archiver#jar}"
063         * @required
064         * @readonly
065         */
066        private JarArchiver jarArchiver = null;
067    
068        /**
069         * Directory containing the generated archive.
070         *
071         * @parameter expression="${project.build.directory}"
072         * @required
073         */
074        private File outputDirectory = null;
075    
076        /**
077         * Directory containing the classes/resources.
078         *
079         * @parameter expression="${project.build.outputDirectory}"
080         * @required
081         */
082        private File classesDirectory = null;
083    
084        /**
085         * Name of the generated archive.
086         *
087         * @parameter expression="${project.build.finalName}"
088         * @required
089         */
090        private String finalName = null;
091    
092        /**
093         * ???
094         *
095         * @parameter expression="${settings.localRepository}"
096         * @required
097         * @readonly
098         */
099        private File repository = null;
100    
101        /**
102         * ???
103         *
104         * @parameter expression="${project.build.directory}/repository"
105         * @required
106         */
107        private File targetRepository = null;
108    
109        /**
110         * ???
111         *
112         * @parameter expression="org.apache.geronimo.configs/geronimo-gbean-deployer/${geronimoVersion}/car"
113         * @required
114         * @readonly
115         */
116        private String deafultDeploymentConfig = null;
117    
118        /**
119         * ???
120         *
121         * @parameter
122         */
123        private ArrayList deploymentConfigs;
124    
125        /**
126         * ???
127         *
128         * @parameter expression="org.apache.geronimo.configs/geronimo-gbean-deployer/${geronimoVersion}/car?j2eeType=Deployer,name=Deployer"
129         * @required
130         */
131        private String deployerName = null;
132    
133        /**
134         * ???
135         *
136         * @parameter expression="${project.build.directory}/plan/plan.xml"
137         * @required
138         */
139        private File planFile = null;
140    
141        /**
142         * ???
143         *
144         * @parameter
145         */
146        private File moduleFile = null;
147    
148        /**
149         * ???
150         *
151         * @parameter
152         */
153        private ArtifactItem module = null;
154        
155        /**
156         * The location where the properties mapping will be generated.
157         *
158         * @parameter expression="${project.build.directory}/explicit-versions.properties"
159         */
160        private File explicitResolutionProperties = null;
161    
162        /**
163         * A list of {@link ClasspathElement} objects which will be used to construct the
164         * Class-Path entry of the manifest.
165         *
166         * This is needed to allow per-element prefixes to be added, which the standard Maven archiver
167         * does not provide.
168         *
169         * @parameter
170         */
171        private List classpath = null;
172    
173        /**
174         * The default prefix to be applied to all elements of the <tt>classpath</tt> which
175         * do not provide a prefix.
176         *
177         * @parameter
178         */
179        private String classpathPrefix = null;
180    
181        //
182        // Mojo
183        //
184    
185        protected void doExecute() throws Exception {
186            // We need to make sure to clean up any previous work first or this operation will fail
187            FileUtils.forceDelete(targetRepository);
188            FileUtils.forceMkdir(targetRepository);
189    
190            // Use the default configs if none specified
191            if (deploymentConfigs == null) {
192                deploymentConfigs = new ArrayList();
193                deploymentConfigs.add(deafultDeploymentConfig);
194            }
195            log.debug("Deployment configs: " + deploymentConfigs);
196    
197            // If module is set, then resolve the artifact and set moduleFile
198            if (module != null) {
199                Artifact artifact = getArtifact(module);
200                moduleFile = artifact.getFile();
201                log.debug("Using module file: " + moduleFile);
202            }
203    
204            generateExplicitVersionProperties(explicitResolutionProperties);
205            
206            executePackageBuilderShell();
207    
208            // Build the archive
209            File archive = createArchive();
210    
211            // Attach the generated archive for install/deploy
212            project.getArtifact().setFile(archive);
213        }
214    
215        private File getArtifactInRepositoryDir() {
216            //
217            // HACK: Generate the filename in the repo... really should delegate this to the
218            //       repo impl, but need to condense PackageMojo and PackageBuilder first
219            //
220    
221            File dir = new File(targetRepository, project.getGroupId().replace('.', '/'));
222                dir = new File(dir, project.getArtifactId());
223                dir = new File(dir, project.getVersion());
224                dir = new File(dir, project.getArtifactId() + "-" + project.getVersion() + ".car");
225    
226            return dir;
227        }
228    
229        public void executePackageBuilderShell() throws Exception {
230            log.debug("Starting builder shell...");
231    
232            PackageBuilder builder = new PackageBuilder();
233    
234            //
235            // NOTE: May need to run this in a controlled classloader (w/reflection or a proxy)
236            //
237            //       http://www.nabble.com/PackageBuilderShellMojo-%28m2%29-and-classloaders-p5271991.html
238            //
239    
240            builder.setDeployerName(deployerName);
241            builder.setDeploymentConfig(deploymentConfigs);
242            builder.setModuleFile(moduleFile);
243            builder.setPlanFile(planFile);
244            builder.setRepository(repository);
245            builder.setRepositoryClass(Maven2Repository.class.getName());
246            builder.setConfigurationStoreClass(MavenConfigStore.class.getName());
247            builder.setTargetRepository(targetRepository);
248            builder.setTargetRepositoryClass(Maven2Repository.class.getName());
249            builder.setTargetConfigurationStoreClass(RepositoryConfigurationStore.class.getName());
250            builder.setExplicitResolutionLocation(explicitResolutionProperties.getAbsolutePath());
251    
252            builder.execute();
253        }
254    
255        /**
256         * Generates the configuration archive.
257         */
258        private File createArchive() throws MojoExecutionException {
259            File archiveFile = getArchiveFile(outputDirectory, finalName, null);
260    
261            MavenArchiver archiver = new MavenArchiver();
262            archiver.setArchiver(jarArchiver);
263            archiver.setOutputFile(archiveFile);
264    
265            try {
266                // Incldue the generated artifact contents
267                archiver.getArchiver().addDirectory(getArtifactInRepositoryDir());
268    
269                // Include the optional classes.resources
270                archiver.getArchiver().addDirectory(classesDirectory);
271    
272                if (classpath != null) {
273                    archive.addManifestEntry("Class-Path", getClassPath());
274                }
275    
276                archiver.createArchive(project, archive);
277    
278                return archiveFile;
279            }
280            catch (Exception e) {
281                throw new MojoExecutionException("Failed to create archive", e);
282            }
283        }
284    
285        private String getClassPath() throws MojoExecutionException {
286            StringBuffer buff = new StringBuffer();
287    
288            ClasspathElement[] elements = (ClasspathElement[]) classpath.toArray(new ClasspathElement[classpath.size()]);
289            for (int i=0; i < elements.length; i++) {
290                Artifact artifact = getArtifact(elements[i]);
291    
292                //
293                // TODO: Need to optionally get all transitive dependencies... but dunno how to get that intel from m2
294                //
295    
296                String prefix = elements[i].getClasspathPrefix();
297                if (prefix == null) {
298                    prefix = classpathPrefix;
299                }
300    
301                if (prefix != null) {
302                    buff.append(prefix);
303    
304                    if (!prefix.endsWith("/")) {
305                        buff.append("/");
306                    }
307                }
308    
309                File file = artifact.getFile();
310                buff.append(file.getName());
311    
312                if (i + 1< elements.length) {
313                    buff.append(" ");
314                }
315            }
316    
317            log.debug("Using classpath: " + buff);
318    
319            return buff.toString();
320        }
321    }