View Javadoc

1   /*******************************************************************************
2    * Copyright (c) 2011 Sonatype, Inc.
3    * All rights reserved. This program and the accompanying materials
4    * are made available under the terms of the Eclipse Public License v1.0
5    * and Apache License v2.0 which accompanies this distribution.
6    * The Eclipse Public License is available at
7    *   http://www.eclipse.org/legal/epl-v10.html
8    * The Apache License v2.0 is available at
9    *   http://www.apache.org/licenses/LICENSE-2.0.html
10   * You may elect to redistribute this code under either of these licenses.
11   *******************************************************************************/
12  package org.sonatype.plugins.sisu;
13  
14  import java.io.File;
15  import java.net.MalformedURLException;
16  import java.net.URL;
17  import java.net.URLClassLoader;
18  import java.util.ArrayList;
19  import java.util.List;
20  
21  import org.apache.maven.artifact.Artifact;
22  import org.apache.maven.plugin.AbstractMojo;
23  import org.apache.maven.project.MavenProject;
24  import org.apache.maven.shared.artifact.filter.collection.ArtifactFilterException;
25  import org.apache.maven.shared.artifact.filter.collection.ArtifactIdFilter;
26  import org.apache.maven.shared.artifact.filter.collection.ClassifierFilter;
27  import org.apache.maven.shared.artifact.filter.collection.FilterArtifacts;
28  import org.apache.maven.shared.artifact.filter.collection.GroupIdFilter;
29  import org.apache.maven.shared.artifact.filter.collection.ProjectTransitivityFilter;
30  import org.apache.maven.shared.artifact.filter.collection.ScopeFilter;
31  import org.apache.maven.shared.artifact.filter.collection.TypeFilter;
32  import org.codehaus.plexus.util.StringUtils;
33  import org.sonatype.guice.bean.reflect.URLClassSpace;
34  import org.sonatype.guice.bean.scanners.index.SisuIndex;
35  
36  /**
37   * Generates a qualified class index for the current project and its dependencies.
38   * 
39   * @goal index
40   * @requiresDependencyResolution test
41   */
42  public class IndexMojo
43      extends AbstractMojo
44  {
45      // ----------------------------------------------------------------------
46      // Configurable parameters
47      // ----------------------------------------------------------------------
48  
49      /**
50       * @parameter expression="${outputDirectory}" default-value="${project.build.outputDirectory}"
51       * @optional
52       */
53      protected File outputDirectory;
54  
55      /**
56       * If we should include project dependencies when indexing.
57       * 
58       * @parameter expression="${includeDependencies}" default-value="true"
59       * @optional
60       */
61      protected boolean includeDependencies;
62  
63      /**
64       * Comma separated list of GroupIds to exclude when indexing.
65       * 
66       * @parameter expression="${excludeGroupIds}" default-value=""
67       * @optional
68       */
69      protected String excludeGroupIds;
70  
71      /**
72       * Comma separated list of GroupIds to include when indexing.
73       * 
74       * @parameter expression="${includeGroupIds}" default-value=""
75       * @optional
76       */
77      protected String includeGroupIds;
78  
79      /**
80       * Comma separated list of ArtifactIds to exclude when indexing.
81       * 
82       * @parameter expression="${excludeArtifactIds}" default-value=""
83       * @optional
84       */
85      protected String excludeArtifactIds;
86  
87      /**
88       * Comma separated list of ArtifactIds to include when indexing.
89       * 
90       * @parameter expression="${includeArtifactIds}" default-value=""
91       * @optional
92       */
93      protected String includeArtifactIds;
94  
95      /**
96       * Comma Separated list of Classifiers to exclude when indexing.
97       * 
98       * @parameter expression="${excludeClassifiers}" default-value=""
99       * @optional
100      */
101     protected String excludeClassifiers;
102 
103     /**
104      * Comma Separated list of Classifiers to include when indexing.
105      * 
106      * @parameter expression="${includeClassifiers}" default-value=""
107      * @optional
108      */
109     protected String includeClassifiers;
110 
111     /**
112      * Comma Separated list of Types to exclude when indexing.
113      * 
114      * @parameter expression="${excludeTypes}" default-value=""
115      * @optional
116      */
117     protected String excludeTypes;
118 
119     /**
120      * Comma Separated list of Types to include when indexing.
121      * 
122      * @parameter expression="${includeTypes}" default-value=""
123      * @optional
124      */
125     protected String includeTypes;
126 
127     /**
128      * Scope to exclude. Empty string indicates no scopes (default).
129      * 
130      * @parameter expression="${excludeScope}" default-value=""
131      * @optional
132      */
133     protected String excludeScope;
134 
135     /**
136      * Scope to include. Empty string indicates all scopes (default).
137      * 
138      * @parameter expression="${includeScope}" default-value=""
139      * @optional
140      */
141     protected String includeScope;
142 
143     /**
144      * If we should exclude transitive dependencies when indexing.
145      * 
146      * @parameter expression="${excludeTransitive}" default-value="false"
147      * @optional
148      */
149     protected boolean excludeTransitive;
150 
151     // ----------------------------------------------------------------------
152     // Implementation fields
153     // ----------------------------------------------------------------------
154 
155     /**
156      * The Maven project to index.
157      * 
158      * @parameter expression="${project}"
159      * @required
160      * @readonly
161      */
162     private MavenProject project;
163 
164     // ----------------------------------------------------------------------
165     // Public methods
166     // ----------------------------------------------------------------------
167 
168     public void setProject( final MavenProject project )
169     {
170         this.project = project;
171     }
172 
173     public void setOutputDirectory( final File outputDirectory )
174     {
175         this.outputDirectory = outputDirectory;
176     }
177 
178     public void execute()
179     {
180         new SisuIndex( outputDirectory ).index( new URLClassSpace( getProjectClassLoader(), getIndexPath() ) );
181     }
182 
183     // ----------------------------------------------------------------------
184     // Implementation methods
185     // ----------------------------------------------------------------------
186 
187     private ClassLoader getProjectClassLoader()
188     {
189         final List<URL> classPath = new ArrayList<URL>();
190         appendToClassPath( classPath, outputDirectory );
191         appendToClassPath( classPath, new File( project.getBuild().getOutputDirectory() ) );
192         for ( final Object artifact : project.getArtifacts() )
193         {
194             appendToClassPath( classPath, ( (Artifact) artifact ).getFile() );
195         }
196         return URLClassLoader.newInstance( classPath.toArray( new URL[classPath.size()] ) );
197     }
198 
199     private URL[] getIndexPath()
200     {
201         final List<URL> indexPath = new ArrayList<URL>();
202         appendToClassPath( indexPath, outputDirectory );
203         if ( includeDependencies )
204         {
205             final FilterArtifacts filter = new FilterArtifacts();
206 
207             filter.addFilter( new ProjectTransitivityFilter( project.getDependencyArtifacts(), excludeTransitive ) );
208             filter.addFilter( new ScopeFilter( cleanList( includeScope ), cleanList( excludeScope ) ) );
209             filter.addFilter( new TypeFilter( cleanList( includeTypes ), cleanList( excludeTypes ) ) );
210             filter.addFilter( new ClassifierFilter( cleanList( includeClassifiers ), cleanList( excludeClassifiers ) ) );
211             filter.addFilter( new GroupIdFilter( cleanList( includeGroupIds ), cleanList( excludeGroupIds ) ) );
212             filter.addFilter( new ArtifactIdFilter( cleanList( includeArtifactIds ), cleanList( excludeArtifactIds ) ) );
213 
214             try
215             {
216                 for ( final Object artifact : filter.filter( project.getArtifacts() ) )
217                 {
218                     appendToClassPath( indexPath, ( (Artifact) artifact ).getFile() );
219                 }
220             }
221             catch ( final ArtifactFilterException e )
222             {
223                 getLog().warn( e.getLocalizedMessage() );
224             }
225         }
226         return indexPath.toArray( new URL[indexPath.size()] );
227     }
228 
229     private void appendToClassPath( final List<URL> urls, final File file )
230     {
231         if ( null != file )
232         {
233             try
234             {
235                 urls.add( file.toURI().toURL() );
236             }
237             catch ( final MalformedURLException e )
238             {
239                 getLog().warn( e.getLocalizedMessage() );
240             }
241         }
242     }
243 
244     private static String cleanList( final String list )
245     {
246         return StringUtils.isEmpty( list ) ? "" : StringUtils.join( StringUtils.split( list ), "," );
247     }
248 }