View Javadoc

1   package org.apache.maven.plugin.descriptor;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.io.FileInputStream;
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.io.Reader;
27  import java.net.MalformedURLException;
28  import java.net.URL;
29  import java.util.Collections;
30  import java.util.HashMap;
31  import java.util.List;
32  import java.util.Map;
33  import java.util.Set;
34  
35  import org.apache.maven.artifact.Artifact;
36  import org.apache.maven.artifact.ArtifactUtils;
37  import org.apache.maven.model.Plugin;
38  import org.apache.maven.plugin.lifecycle.Lifecycle;
39  import org.apache.maven.plugin.lifecycle.LifecycleConfiguration;
40  import org.apache.maven.plugin.lifecycle.io.xpp3.LifecycleMappingsXpp3Reader;
41  import org.codehaus.plexus.classworlds.realm.ClassRealm;
42  import org.codehaus.plexus.component.repository.ComponentSetDescriptor;
43  import org.codehaus.plexus.util.IOUtil;
44  import org.codehaus.plexus.util.ReaderFactory;
45  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
46  
47  /**
48   * @author Jason van Zyl
49   */
50  public class PluginDescriptor
51      extends ComponentSetDescriptor
52      implements Cloneable
53  {
54  
55      private static final String LIFECYCLE_DESCRIPTOR = "META-INF/maven/lifecycle.xml";
56  
57      private String groupId;
58  
59      private String artifactId;
60  
61      private String version;
62  
63      private String goalPrefix;
64  
65      private String source;
66  
67      private boolean inheritedByDefault = true;
68  
69      private List<Artifact> artifacts;
70  
71      private ClassRealm classRealm;
72  
73      // calculated on-demand.
74      private Map<String, Artifact> artifactMap;
75  
76      private Set<Artifact> introducedDependencyArtifacts;
77  
78      private String name;
79  
80      private String description;
81  
82      private Plugin plugin;
83  
84      private Artifact pluginArtifact;
85  
86      private Map<String, Lifecycle> lifecycleMappings;
87  
88      // ----------------------------------------------------------------------
89      //
90      // ----------------------------------------------------------------------
91  
92      @SuppressWarnings( "unchecked" )
93      public List<MojoDescriptor> getMojos()
94      {
95          return (List) getComponents();
96      }
97  
98      public void addMojo( MojoDescriptor mojoDescriptor )
99          throws DuplicateMojoDescriptorException
100     {
101         MojoDescriptor existing = null;
102         // this relies heavily on the equals() and hashCode() for ComponentDescriptor,
103         // which uses role:roleHint for identity...and roleHint == goalPrefix:goal.
104         // role does not vary for Mojos.
105         List<MojoDescriptor> mojos = getMojos();
106 
107         if ( mojos != null && mojos.contains( mojoDescriptor ) )
108         {
109             int indexOf = mojos.indexOf( mojoDescriptor );
110 
111             existing = mojos.get( indexOf );
112         }
113 
114         if ( existing != null )
115         {
116             throw new DuplicateMojoDescriptorException( getGoalPrefix(), mojoDescriptor.getGoal(), existing
117                 .getImplementation(), mojoDescriptor.getImplementation() );
118         }
119         else
120         {
121             addComponentDescriptor( mojoDescriptor );
122         }
123     }
124 
125     public String getGroupId()
126     {
127         return groupId;
128     }
129 
130     public void setGroupId( String groupId )
131     {
132         this.groupId = groupId;
133     }
134 
135     public String getArtifactId()
136     {
137         return artifactId;
138     }
139 
140     public void setArtifactId( String artifactId )
141     {
142         this.artifactId = artifactId;
143     }
144 
145     // ----------------------------------------------------------------------
146     // Dependencies
147     // ----------------------------------------------------------------------
148 
149     public static String constructPluginKey( String groupId, String artifactId, String version )
150     {
151         return groupId + ":" + artifactId + ":" + version;
152     }
153 
154     public String getPluginLookupKey()
155     {
156         return groupId + ":" + artifactId;
157     }
158 
159     public String getId()
160     {
161         return constructPluginKey( groupId, artifactId, version );
162     }
163 
164     public static String getDefaultPluginArtifactId( String id )
165     {
166         return "maven-" + id + "-plugin";
167     }
168 
169     public static String getDefaultPluginGroupId()
170     {
171         return "org.apache.maven.plugins";
172     }
173 
174     /**
175      * Parse maven-...-plugin.
176      *
177      * @todo move to plugin-tools-api as a default only
178      */
179     public static String getGoalPrefixFromArtifactId( String artifactId )
180     {
181         if ( "maven-plugin-plugin".equals( artifactId ) )
182         {
183             return "plugin";
184         }
185         else
186         {
187             return artifactId.replaceAll( "-?maven-?", "" ).replaceAll( "-?plugin-?", "" );
188         }
189     }
190 
191     public String getGoalPrefix()
192     {
193         return goalPrefix;
194     }
195 
196     public void setGoalPrefix( String goalPrefix )
197     {
198         this.goalPrefix = goalPrefix;
199     }
200 
201     public void setVersion( String version )
202     {
203         this.version = version;
204     }
205 
206     public String getVersion()
207     {
208         return version;
209     }
210 
211     public void setSource( String source )
212     {
213         this.source = source;
214     }
215 
216     public String getSource()
217     {
218         return source;
219     }
220 
221     public boolean isInheritedByDefault()
222     {
223         return inheritedByDefault;
224     }
225 
226     public void setInheritedByDefault( boolean inheritedByDefault )
227     {
228         this.inheritedByDefault = inheritedByDefault;
229     }
230 
231     /**
232      * Gets the artifacts that make up the plugin's class realm, excluding artifacts shadowed by the Maven core realm
233      * like {@code maven-project}.
234      *
235      * @return The plugin artifacts, never {@code null}.
236      */
237     public List<Artifact> getArtifacts()
238     {
239         return artifacts;
240     }
241 
242     public void setArtifacts( List<Artifact> artifacts )
243     {
244         this.artifacts = artifacts;
245 
246         // clear the calculated artifactMap
247         artifactMap = null;
248     }
249 
250     public Map<String, Artifact> getArtifactMap()
251     {
252         if ( artifactMap == null )
253         {
254             artifactMap = ArtifactUtils.artifactMapByVersionlessId( getArtifacts() );
255         }
256 
257         return artifactMap;
258     }
259 
260     public boolean equals( Object object )
261     {
262         if ( this == object )
263         {
264             return true;
265         }
266 
267         return getId().equals( ( (PluginDescriptor) object ).getId() );
268     }
269 
270     public int hashCode()
271     {
272         return 10 + getId().hashCode();
273     }
274 
275     public MojoDescriptor getMojo( String goal )
276     {
277         if ( getMojos() == null )
278         {
279             return null; // no mojo in this POM
280         }
281 
282         // TODO: could we use a map? Maybe if the parent did that for components too, as this is too vulnerable to
283         // changes above not being propagated to the map
284         for ( MojoDescriptor desc : getMojos() )
285         {
286             if ( goal.equals( desc.getGoal() ) )
287             {
288                 return desc;
289             }
290         }
291         return null;
292     }
293 
294     public void setClassRealm( ClassRealm classRealm )
295     {
296         this.classRealm = classRealm;
297     }
298 
299     public ClassRealm getClassRealm()
300     {
301         return classRealm;
302     }
303 
304     public void setIntroducedDependencyArtifacts( Set<Artifact> introducedDependencyArtifacts )
305     {
306         this.introducedDependencyArtifacts = introducedDependencyArtifacts;
307     }
308 
309     public Set<Artifact> getIntroducedDependencyArtifacts()
310     {
311         return ( introducedDependencyArtifacts != null ) ? introducedDependencyArtifacts
312                         : Collections.<Artifact> emptySet();
313     }
314 
315     public void setName( String name )
316     {
317         this.name = name;
318     }
319 
320     public String getName()
321     {
322         return name;
323     }
324 
325     public void setDescription( String description )
326     {
327         this.description = description;
328     }
329 
330     public String getDescription()
331     {
332         return description;
333     }
334 
335     public void setPlugin( Plugin plugin )
336     {
337         this.plugin = plugin;
338     }
339 
340     public Plugin getPlugin()
341     {
342         return plugin;
343     }
344 
345     public Artifact getPluginArtifact()
346     {
347         return pluginArtifact;
348     }
349 
350     public void setPluginArtifact( Artifact pluginArtifact )
351     {
352         this.pluginArtifact = pluginArtifact;
353     }
354 
355     public Lifecycle getLifecycleMapping( String lifecycleId )
356         throws IOException, XmlPullParserException
357     {
358         if ( lifecycleMappings == null )
359         {
360             LifecycleConfiguration lifecycleConfiguration;
361 
362             Reader reader = null;
363             try
364             {
365                 reader = ReaderFactory.newXmlReader( getDescriptorStream( LIFECYCLE_DESCRIPTOR ) );
366 
367                 lifecycleConfiguration = new LifecycleMappingsXpp3Reader().read( reader );
368             }
369             finally
370             {
371                 IOUtil.close( reader );
372             }
373 
374             lifecycleMappings = new HashMap<String, Lifecycle>();
375 
376             for ( Lifecycle lifecycle : lifecycleConfiguration.getLifecycles() )
377             {
378                 lifecycleMappings.put( lifecycle.getId(), lifecycle );
379             }
380         }
381 
382         return lifecycleMappings.get( lifecycleId );
383     }
384 
385     private InputStream getDescriptorStream( String descriptor )
386         throws IOException
387     {
388         File pluginFile = ( pluginArtifact != null ) ? pluginArtifact.getFile() : null;
389         if ( pluginFile == null )
390         {
391             throw new IllegalStateException( "plugin main artifact has not been resolved for " + getId() );
392         }
393 
394         if ( pluginFile.isFile() )
395         {
396             try
397             {
398                 return new URL( "jar:" + pluginFile.toURI() + "!/" + descriptor ).openStream();
399             }
400             catch ( MalformedURLException e )
401             {
402                 throw new IllegalStateException( e );
403             }
404         }
405         else
406         {
407             return new FileInputStream( new File( pluginFile, descriptor ) );
408         }
409     }
410 
411     /**
412      * Creates a shallow copy of this plugin descriptor.
413      */
414     @Override
415     public PluginDescriptor clone()
416     {
417         try
418         {
419             return (PluginDescriptor) super.clone();
420         }
421         catch ( CloneNotSupportedException e )
422         {
423             throw new UnsupportedOperationException( e );
424         }
425     }
426 
427 }