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.io.IOException;
024    import java.io.FileOutputStream;
025    import java.io.BufferedOutputStream;
026    
027    import java.util.Iterator;
028    import java.util.Properties;
029    import java.util.Map;
030    
031    import org.codehaus.mojo.pluginsupport.MojoSupport;
032    import org.codehaus.mojo.pluginsupport.util.ArtifactItem;
033    import org.codehaus.mojo.pluginsupport.dependency.DependencyHelper;
034    import org.codehaus.mojo.pluginsupport.dependency.DependencyTree;
035    import org.codehaus.mojo.pluginsupport.dependency.DependencyTree.Node;
036    
037    import org.apache.maven.plugin.MojoExecutionException;
038    import org.apache.maven.plugin.MojoFailureException;
039    import org.apache.maven.project.MavenProject;
040    import org.apache.maven.project.MavenProjectHelper;
041    import org.apache.maven.artifact.Artifact;
042    import org.apache.maven.artifact.repository.ArtifactRepository;
043    
044    /**
045     * Support for <em>packaging</em> Mojos.
046     *
047     * @version $Rev: 524717 $ $Date: 2007-04-01 23:39:19 -0400 (Sun, 01 Apr 2007) $
048     */
049    public abstract class AbstractCarMojo
050        extends MojoSupport
051    {
052        /**
053         * The maven project.
054         *
055         * @parameter expression="${project}"
056         * @required
057         * @readonly
058         */
059        protected MavenProject project;
060    
061        /**
062         * The basedir of the project.
063         *
064         * @parameter expression="${basedir}"
065         * @required
066         * @readonly
067         */
068        protected File basedir;
069    
070        /**
071         * The maven project's helper.
072         *
073         * @component
074         * @required
075         * @readonly
076         */
077        protected MavenProjectHelper projectHelper;
078        
079        /**
080         * @component
081         */
082        protected DependencyHelper dependencyHelper = null;
083        
084        //
085        // MojoSupport Hooks
086        //
087    
088        protected MavenProject getProject() {
089            return project;
090        }
091    
092        /**
093         * @parameter expression="${localRepository}"
094         * @readonly
095         * @required
096         */
097        protected ArtifactRepository artifactRepository = null;
098    
099        protected ArtifactRepository getArtifactRepository() {
100            return artifactRepository;
101        }
102        
103        protected void init() throws MojoExecutionException, MojoFailureException {
104            super.init();
105            
106            dependencyHelper.setArtifactRepository(artifactRepository);
107        }
108        
109        /**
110         * Generates a properties file with explicit versions of artifacts of the current project transitivly.
111         */
112        protected void generateExplicitVersionProperties(final File outputFile, DependencyTree dependencies) throws MojoExecutionException, IOException {
113            log.debug("Generating explicit version properties: " + outputFile);
114    
115            // Generate explicit_versions for all our dependencies...
116            Properties props = new Properties();
117            
118            try {
119    
120                Node root = dependencies.getRootNode();
121                
122                // Skip the root node
123                Iterator children = root.getChildren().iterator();
124                while (children.hasNext()) {
125                    Node child = (Node) children.next();
126                    appendExplicitVersionProperties(child, props);
127                }
128            }
129            catch (Exception e) {
130                throw new MojoExecutionException("Failed to determine project dependencies", e);
131            }
132            
133            BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(outputFile));
134            props.store(output, null);
135            output.flush();
136            output.close();
137        }
138        
139        private void appendExplicitVersionProperties(final Node node, final Properties props) {
140            assert node != null;
141            assert props != null;
142            
143            Artifact artifact = node.getArtifact();
144            if ("test".equals(artifact.getScope())) {
145                if (log.isDebugEnabled()) {
146                    log.debug("Skipping artifact with scope test: " + artifact);
147                }
148                return;
149            }
150            
151            String name = artifact.getGroupId() + "/" + artifact.getArtifactId() + "//" + artifact.getType();
152            String value = artifact.getGroupId() + "/" + artifact.getArtifactId() + "/" + artifact.getVersion() + "/" + artifact.getType();
153            
154            if (log.isDebugEnabled()) {
155                log.debug("Setting " + name + "=" + value);
156            }
157            props.setProperty(name, value);
158            
159            if (!node.getChildren().isEmpty()) {
160                Iterator children = node.getChildren().iterator();
161                
162                while (children.hasNext()) {
163                    Node child = (Node) children.next();
164                    appendExplicitVersionProperties(child, props);
165                }
166            }
167        }
168    
169        protected static File getArchiveFile(final File basedir, final String finalName, String classifier) {
170            if (classifier == null) {
171                classifier = "";
172            }
173            else if (classifier.trim().length() > 0 && !classifier.startsWith("-")) {
174                classifier = "-" + classifier;
175            }
176    
177            return new File(basedir, finalName + classifier + ".car");
178        }
179    
180        //
181        // Geronimo/Maven Artifact Interop
182        //
183    
184        protected org.apache.geronimo.kernel.repository.Artifact mavenToGeronimoArtifact(final org.apache.maven.artifact.Artifact artifact) {
185            assert artifact != null;
186    
187            return new org.apache.geronimo.kernel.repository.Artifact(artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(), artifact.getType());
188        }
189    
190        protected org.apache.maven.artifact.Artifact geronimoToMavenArtifact(final org.apache.geronimo.kernel.repository.Artifact artifact) throws MojoExecutionException {
191            assert artifact != null;
192    
193            ArtifactItem item = new ArtifactItem();
194            item.setGroupId(artifact.getGroupId());
195            item.setArtifactId(artifact.getArtifactId());
196            item.setVersion(artifact.getVersion().toString());
197            item.setType(artifact.getType());
198    
199            return createArtifact(item);
200        }
201    
202        /**
203         * Determine if the given artifact is a Geronimo module.
204         *
205         * @param artifact  The artifact to check; must not be null.
206         * @return          True if the artifact is a Geronimo module.
207         */
208        protected boolean isModuleArtifact(final org.apache.geronimo.kernel.repository.Artifact artifact) {
209            assert artifact != null;
210    
211            return "car".equals(artifact.getType());
212        }
213    
214        protected class ArtifactLookupImpl
215            implements Maven2RepositoryAdapter.ArtifactLookup
216        {
217    
218            private final Map resolvedArtifacts;
219    
220            public ArtifactLookupImpl(Map resolvedArtifacts) {
221                this.resolvedArtifacts = resolvedArtifacts;
222            }
223    
224            public File getBasedir() {
225                String path = getArtifactRepository().getBasedir();
226                return new File(path);
227            }
228    
229            private boolean isProjectArtifact(final org.apache.geronimo.kernel.repository.Artifact artifact) {
230                MavenProject project = getProject();
231    
232                return artifact.getGroupId().equals(project.getGroupId()) &&
233                       artifact.getArtifactId().equals(project.getArtifactId());
234            }
235    
236            public File getLocation(final org.apache.geronimo.kernel.repository.Artifact artifact) {
237                assert artifact != null;
238    
239                boolean debug = log.isDebugEnabled();
240    
241                Artifact mavenArtifact = (Artifact)resolvedArtifacts.get(artifact);
242    
243                // If not cached, then make a new artifact
244                if (mavenArtifact == null) {
245                    mavenArtifact = getArtifactFactory().createArtifact(
246                            artifact.getGroupId(),
247                            artifact.getArtifactId(),
248                            artifact.getVersion().toString(),
249                            null,
250                            artifact.getType()
251                    );
252                }
253    
254                // Do not attempt to resolve an artifact that is the same as the project
255                if (isProjectArtifact(artifact)) {
256                    if (debug) {
257                        log.debug("Skipping resolution of project artifact: " + artifact);
258                    }
259    
260                    //
261                    // HACK: Still have to return something, otherwise some CAR packaging will fail...
262                    //       no idea what is using this file, or if the files does exist if that will be
263                    //       used instead of any details we are currently building
264                    //
265                    return new File(getBasedir(), getArtifactRepository().pathOf(mavenArtifact));
266                }
267    
268                File file;
269                try {
270                    if (!mavenArtifact.isResolved()) {
271                        if (debug) {
272                            log.debug("Resolving artifact: " + mavenArtifact);
273                        }
274                        mavenArtifact = resolveArtifact(mavenArtifact);
275    
276                        // Cache the resolved artifact
277                        resolvedArtifacts.put(artifact, mavenArtifact);
278                    }
279    
280                    //
281                    // HACK: Construct the real local filename from the path and resolved artifact file.
282                    //       Probably a better way to do this with the Maven API directly, but this is the
283                    //       best I can do for now.
284                    //
285                    String path = getArtifactRepository().pathOf(mavenArtifact);
286                    file = new File(getBasedir(), path);
287                    file = new File(mavenArtifact.getFile().getParentFile(), file.getName());
288                }
289                catch (MojoExecutionException e) {
290                    throw new RuntimeException("Failed to resolve: " + mavenArtifact, e);
291                }
292    
293                return file;
294            }
295        }
296        
297    }