View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *  http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.geronimo.genesis;
21  
22  import java.io.File;
23  import java.util.ArrayList;
24  import java.util.HashSet;
25  import java.util.Iterator;
26  import java.util.List;
27  import java.util.Set;
28  import java.util.Collections;
29  
30  import org.apache.maven.artifact.Artifact;
31  import org.apache.maven.artifact.factory.ArtifactFactory;
32  import org.apache.maven.artifact.repository.ArtifactRepository;
33  import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
34  import org.apache.maven.artifact.resolver.ArtifactResolutionException;
35  import org.apache.maven.artifact.resolver.ArtifactResolver;
36  import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
37  import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter;
38  import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
39  import org.apache.maven.artifact.versioning.VersionRange;
40  import org.apache.maven.model.Dependency;
41  import org.apache.maven.model.Exclusion;
42  import org.apache.maven.plugin.AbstractMojo;
43  import org.apache.maven.plugin.MojoExecutionException;
44  import org.apache.maven.plugin.MojoFailureException;
45  import org.apache.maven.plugin.logging.Log;
46  import org.apache.maven.project.MavenProject;
47  import org.codehaus.plexus.PlexusConstants;
48  import org.codehaus.plexus.PlexusContainer;
49  import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
50  import org.codehaus.plexus.context.Context;
51  import org.codehaus.plexus.context.ContextException;
52  import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
53  
54  import org.apache.geronimo.genesis.dependency.DependencyHelper;
55  import org.apache.geronimo.genesis.util.ArtifactItem;
56  import org.apache.geronimo.genesis.logging.MavenPluginLog;
57  import org.apache.geronimo.genesis.logging.Logging;
58  import org.apache.geronimo.genesis.logging.DelegatingLog;
59  
60  /**
61   * Support for Mojo implementations.
62   *
63   * @version $Rev: 470159 $ $Date: 2006-11-01 17:19:16 -0800 (Wed, 01 Nov 2006) $
64   */
65  public abstract class MojoSupport
66      extends AbstractMojo
67      implements Contextualizable
68  {
69      protected PlexusContainer container;
70  
71      /**
72       * Instance logger.  This is initialized to the value of {@link #getLog}
73       * on execution.
74       */
75      protected Log log;
76      
77      private DependencyHelper dependencyHelper;
78  
79      protected MojoSupport() {
80          // Need to init our logging support before components are initialized and attached
81          Logging.init();
82      }
83  
84      /**
85       * Initializes logging.  Called by {@link #execute}.
86       *
87       * @throws MojoExecutionException   Initialization failed
88       * @throws MojoFailureException     Initialization failed
89       */
90      protected void init() throws MojoExecutionException, MojoFailureException {
91          this.log = getLog();
92  
93          // Install the bridge from JCL to this plugins Log
94          MavenPluginLog.setMojo(this);
95          DelegatingLog.setDelegateType(MavenPluginLog.class);
96          
97          //
98          // NOTE: Using direct lookup because this class may not have been directly configured
99          //
100         try {
101             this.dependencyHelper = (DependencyHelper)container.lookup(DependencyHelper.class.getName());
102         }
103         catch (ComponentLookupException e) {
104             throw new MojoExecutionException("Failed to lookup required components", e);
105         }
106     }
107 
108     public void contextualize(final Context context) throws ContextException {
109         container = (PlexusContainer) context.get(PlexusConstants.PLEXUS_KEY);
110     }
111 
112     /**
113      * Main Mojo execution hook.  Sub-class should use {@link #doExecute} instead.
114      *
115      * @throws MojoExecutionException
116      * @throws MojoFailureException
117      */
118     public void execute() throws MojoExecutionException, MojoFailureException {
119         init();
120 
121         try {
122             doExecute();
123         }
124         catch (Exception e) {
125             //
126             // NOTE: Wrap to avoid truncating the stacktrace
127             //
128             if (e instanceof MojoExecutionException) {
129                 throw new MojoExecutionException(e.getMessage(), e);
130             }
131             else if (e instanceof MojoFailureException) {
132                 MojoFailureException x = new MojoFailureException(e.getMessage());
133                 x.initCause(e);
134                 throw x;
135             }
136             else {
137                 throw new MojoExecutionException(e.getMessage(), e);
138             }
139         }
140         finally {
141             // Reset logging after we are done to avoid complications with other plugins using JCL
142             Logging.reset();
143         }
144     }
145 
146     /**
147      * Sub-class should override to provide custom execution logic.
148      *
149      * @throws Exception    Execution failed
150      */
151     protected void doExecute() throws Exception {
152         // Empty
153     }
154 
155     //
156     // NOTE: These are not abstract because not all sub-classes will need this functionality
157     //
158     
159     /**
160      * Get the Maven project.
161      *
162      * <p>
163      * Sub-class must overridde to provide access.
164      * </p>
165      *
166      * @return  The maven project; never null
167      */
168     protected MavenProject getProject() {
169         throw new Error("Sub-class must override to provide access to : " + MavenProject.class);
170     }
171 
172     /**
173      * Get the artifact repository.
174      *
175      * <p>
176      * Sub-class must overridde to provide access.
177      * </p>
178      *
179      * @return  An artifact repository; never null
180      */
181     protected ArtifactRepository getArtifactRepository() {
182         throw new Error("Sub-class must override to provide access to: " + ArtifactRepository.class);
183     }
184 
185     /**
186      * Get the artifact factory.
187      *
188      * @return  An artifact factory; never null
189      */
190     protected final ArtifactFactory getArtifactFactory() {
191         return dependencyHelper.getArtifactFactory();
192     }
193 
194     /**
195      * Get the artifact resolver.
196      *
197      * @return  An artifact resolver; never null
198      */
199     protected final ArtifactResolver getArtifactResolver() {
200         return dependencyHelper.getArtifactResolver();
201     }
202 
203     /**
204      * Create a new artifact. If no version is specified, it will be retrieved from the dependency
205      * list or from the DependencyManagement section of the pom.
206      *
207      * @param item  The item to create an artifact for
208      * @return      An unresolved artifact for the given item.
209      *
210      * @throws MojoExecutionException   Failed to create artifact
211      */
212     protected Artifact createArtifact(final ArtifactItem item) throws MojoExecutionException {
213         assert item != null;
214 
215         if (item.getVersion() == null) {
216             fillMissingArtifactVersion(item);
217 
218             if (item.getVersion() == null) {
219                 throw new MojoExecutionException("Unable to find artifact version of " + item.getGroupId()
220                     + ":" + item.getArtifactId() + " in either dependency list or in project's dependency management.");
221             }
222         }
223 
224         // Convert the string version to a range
225         VersionRange range;
226         try {
227             range = VersionRange.createFromVersionSpec(item.getVersion());
228             if (log.isDebugEnabled()) {
229                 log.debug("Using version range: " + range);
230             }
231         }
232         catch (InvalidVersionSpecificationException e) {
233             throw new MojoExecutionException("Could not create range for version: " + item.getVersion(), e);
234         }
235         
236         return getArtifactFactory().createDependencyArtifact(
237             item.getGroupId(),
238             item.getArtifactId(),
239             range,
240             item.getType(),
241             item.getClassifier(),
242             Artifact.SCOPE_PROVIDED);
243     }
244 
245     /**
246      * Resolves the Artifact from the remote repository if nessessary. If no version is specified, it will
247      * be retrieved from the dependency list or from the DependencyManagement section of the pom.
248      *
249      *
250      * @param item  The item to create an artifact for; must not be null
251      * @return      The artifact for the given item
252      *
253      * @throws MojoExecutionException   Failed to create artifact
254      */
255     protected Artifact getArtifact(final ArtifactItem item) throws MojoExecutionException {
256         assert item != null;
257         
258         Artifact artifact = createArtifact(item);
259         
260         return resolveArtifact(artifact);
261     }
262 
263     /**
264      * Resolves the Artifact from the remote repository if nessessary. If no version is specified, it will
265      * be retrieved from the dependency list or from the DependencyManagement section of the pom.
266      *
267      * @param artifact      The artifact to be resolved; must not be null
268      * @param transitive    True to resolve the artifact transitivly
269      * @return              The resolved artifact; never null
270      *
271      * @throws MojoExecutionException   Failed to resolve artifact
272      */
273     protected Artifact resolveArtifact(final Artifact artifact, final boolean transitive) throws MojoExecutionException {
274         assert artifact != null;
275 
276         try {
277             if (transitive) {
278                 getArtifactResolver().resolveTransitively(
279                         Collections.singleton(artifact),
280                         getProject().getArtifact(),
281                         getProject().getRemoteArtifactRepositories(),
282                         getArtifactRepository(),
283                         dependencyHelper.getArtifactMetadataSource());
284             }
285             else {
286                 getArtifactResolver().resolve(
287                         artifact,
288                         getProject().getRemoteArtifactRepositories(),
289                         getArtifactRepository());
290             }
291         }
292         catch (ArtifactResolutionException e) {
293             throw new MojoExecutionException("Unable to resolve artifact.", e);
294         }
295         catch (ArtifactNotFoundException e) {
296             throw new MojoExecutionException("Unable to find artifact.", e);
297         }
298 
299         return artifact;
300     }
301 
302     /**
303      * Resolves the Artifact from the remote repository non-transitivly.
304      *
305      * @param artifact  The artifact to be resolved; must not be null
306      * @return          The resolved artifact; never null
307      *
308      * @throws MojoExecutionException   Failed to resolve artifact
309      *
310      * @see #resolveArtifact(Artifact,boolean)
311      */
312     protected Artifact resolveArtifact(final Artifact artifact) throws MojoExecutionException {
313         return resolveArtifact(artifact, false);
314     }
315 
316     /**
317      * Tries to find missing version from dependancy list and dependency management.
318      * If found, the artifact is updated with the correct version.
319      *
320      * @param item  The item to fill in missing version details into
321      */
322     private void fillMissingArtifactVersion(final ArtifactItem item) {
323         log.debug("Attempting to find missing version in " + item.getGroupId() + ":" + item.getArtifactId());
324 
325         List list = getProject().getDependencies();
326 
327         for (int i = 0; i < list.size(); ++i) {
328             Dependency dependency = (Dependency) list.get(i);
329 
330             if (dependency.getGroupId().equals(item.getGroupId())
331                 && dependency.getArtifactId().equals(item.getArtifactId())
332                 && dependency.getType().equals(item.getType()))
333             {
334                 log.debug("Found missing version: " + dependency.getVersion() + " in dependency list.");
335 
336                 item.setVersion(dependency.getVersion());
337 
338                 return;
339             }
340         }
341 
342         list = getProject().getDependencyManagement().getDependencies();
343 
344         for (int i = 0; i < list.size(); i++) {
345             Dependency dependency = (Dependency) list.get(i);
346 
347             if (dependency.getGroupId().equals(item.getGroupId())
348                 && dependency.getArtifactId().equals(item.getArtifactId())
349                 && dependency.getType().equals(item.getType()))
350             {
351                 log.debug("Found missing version: " + dependency.getVersion() + " in dependency management list");
352 
353                 item.setVersion(dependency.getVersion());
354             }
355         }
356     }
357     
358     //
359     // Access to Project artifacts
360     //
361 
362     protected Set getProjectArtifacts(final MavenProject project, final boolean resolve) throws MojoExecutionException {
363         Set artifacts = new HashSet();
364 
365         Iterator dependencies = project.getDependencies().iterator();
366         while (dependencies.hasNext()) {
367             Dependency dep = (Dependency) dependencies.next();
368 
369             String groupId = dep.getGroupId();
370             String artifactId = dep.getArtifactId();
371             VersionRange versionRange = VersionRange.createFromVersion(dep.getVersion());
372             String type = dep.getType();
373             if (type == null) {
374                 type = "jar";
375             }
376 
377             String classifier = dep.getClassifier();
378             boolean optional = dep.isOptional();
379             String scope = dep.getScope();
380             if (scope == null) {
381                 scope = Artifact.SCOPE_COMPILE;
382             }
383 
384             Artifact artifact = getArtifactFactory().createDependencyArtifact(
385                 groupId,
386                 artifactId,
387                 versionRange,
388                 type,
389                 classifier,
390                 scope,
391                 optional);
392 
393             if (scope.equalsIgnoreCase(Artifact.SCOPE_SYSTEM)) {
394                 artifact.setFile(new File(dep.getSystemPath()));
395             }
396 
397             List exclusions = new ArrayList();
398             for (Iterator j = dep.getExclusions().iterator(); j.hasNext();) {
399                 Exclusion e = (Exclusion) j.next();
400                 exclusions.add(e.getGroupId() + ":" + e.getArtifactId());
401             }
402 
403             ArtifactFilter newFilter = new ExcludesArtifactFilter(exclusions);
404             artifact.setDependencyFilter(newFilter);
405             
406             if (resolve && !artifact.isResolved()) {
407                 log.debug("Resolving artifact: " + artifact);
408                 artifact = resolveArtifact(artifact);
409             }
410 
411             artifacts.add(artifact);
412         }
413 
414         return artifacts;
415     }
416 
417     protected Set getProjectArtifacts(final boolean resolve) throws MojoExecutionException {
418         return getProjectArtifacts(getProject(), resolve);
419     }
420 
421     protected Set getProjectArtifacts() throws MojoExecutionException {
422         return getProjectArtifacts(false);
423     }
424 }