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