View Javadoc

1   package org.codehaus.mojo.rat;
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.IOException;
24  import java.io.InputStream;
25  import java.io.PrintWriter;
26  import java.lang.reflect.UndeclaredThrowableException;
27  import java.util.ArrayList;
28  import java.util.Arrays;
29  import java.util.Iterator;
30  import java.util.List;
31  
32  import javax.xml.transform.TransformerConfigurationException;
33  
34  import org.apache.maven.plugin.AbstractMojo;
35  import org.apache.maven.plugin.MojoExecutionException;
36  import org.apache.maven.plugin.MojoFailureException;
37  import org.apache.maven.project.MavenProject;
38  import org.codehaus.plexus.util.DirectoryScanner;
39  
40  import rat.Defaults;
41  import rat.analysis.IHeaderMatcher;
42  import rat.analysis.util.HeaderMatcherMultiplexer;
43  import rat.license.ILicenseFamily;
44  import rat.report.IReportable;
45  import rat.report.RatReportFailedException;
46  
47  /**
48   * Abstract base class for Mojos, which are running RAT.
49   */
50  public abstract class AbstractRatMojo extends AbstractMojo
51  {
52      /**
53       * The Maven specific default excludes.
54       */
55      public static final String[] MAVEN_DEFAULT_EXCLUDES = new String[] { "target/**/*", "cobertura.ser" };
56  
57      /**
58       * The Eclipse specific default excludes.
59       */
60      public static final String[] ECLIPSE_DEFAULT_EXCLUDES = new String[] { ".classpath", ".project", ".settings/**/*" };
61  
62      /**
63       * The IDEA specific default excludes.
64       */
65      public static final String[] IDEA_DEFAULT_EXCLUDES = new String[] { "*.iml", "*.ipr", "*.iws" };
66  
67      /**
68       * The base directory, in which to search for files.
69       * 
70       * @parameter expression="${rat.basedir}" default-value="${basedir}"
71       * @required
72       */
73      protected File basedir;
74  
75      /**
76       * The licenses we want to match on.
77       * 
78       * @parameter
79       */
80      private HeaderMatcherSpecification[] licenseMatchers;
81  
82      /**
83       * The set of approved license family names.
84       */
85      private LicenseFamilySpecification[] licenseFamilyNames;
86  
87      /**
88       * Whether to add the default list of license matchers.
89       * 
90       * @parameter expression="${rat.addDefaultLicenseMatchers}" default-value="true"
91       */
92      private boolean addDefaultLicenseMatchers;
93  
94      /**
95       * Specifies files, which are included in the report. By default, all files are included.
96       * 
97       * @parameter
98       */
99      private String[] includes;
100 
101     /**
102      * Specifies files, which are excluded in the report. By default, no files are excluded.
103      * 
104      * @parameter
105      */
106     private String[] excludes;
107 
108     /**
109      * Whether to use the default excludes when scanning for files.
110      * 
111      * @parameter expression="${rat.useDefaultExcludes}" default-value="true"
112      */
113     private boolean useDefaultExcludes;
114 
115     /**
116      * Whether to use the Maven specific default excludes when scanning for files. Maven specific default excludes are
117      * given by the constant MAVEN_DEFAULT_EXCLUDES: The target directory, the cobertura.ser file, and so on.
118      * 
119      * @parameter expression="${rat.useMavenDefaultExcludes}" default-value="true"
120      */
121     private boolean useMavenDefaultExcludes;
122 
123     /**
124      * Whether to use the Eclipse specific default excludes when scanning for files. Eclipse specific default excludes
125      * are given by the constant ECLIPSE_DEFAULT_EXCLUDES: The .classpath and .project files, the .settings directory,
126      * and so on.
127      * 
128      * @parameter expression="${rat.useEclipseDefaultExcludes}" default-value="true"
129      */
130     private boolean useEclipseDefaultExcludes;
131 
132     /**
133      * Whether to use the IDEA specific default excludes when scanning for files. IDEA specific default excludes are
134      * given by the constant IDEA_DEFAULT_EXCLUDES: The *.iml, *.ipr and *.iws files.
135      * 
136      * @parameter expression="${rat.useIdeaDefaultExcludes}" default-value="true"
137      */
138     private boolean useIdeaDefaultExcludes;
139 
140     /**
141      * Whether to exclude subprojects. This is recommended, if you want a separate rat-maven-plugin report for each
142      * subproject.
143      * 
144      * @parameter expression="${rat.excludeSubprojects}" default-value="true"
145      */
146     private boolean excludeSubProjects;
147 
148     /**
149      * @parameter default-value="${project}"
150      * @required
151      * @readonly
152      */
153     private MavenProject project;
154 
155     /**
156      * Returns the Maven project.
157      */
158     protected MavenProject getProject()
159     {
160         return project;
161     }
162 
163     /**
164      * Returns the set of {@link IHeaderMatcher header matchers} to use.
165      * 
166      * @throws MojoFailureException
167      *             An error in the plugin configuration was detected.
168      * @throws MojoExecutionException
169      *             An error occurred while calculating the result.
170      * @return Array of license matchers to use
171      */
172     protected IHeaderMatcher[] getLicenseMatchers() throws MojoFailureException, MojoExecutionException
173     {
174         final List list = new ArrayList();
175         if ( licenseMatchers != null )
176         {
177             for ( int i = 0; i < licenseMatchers.length; i++ )
178             {
179                 final HeaderMatcherSpecification spec = licenseMatchers[i];
180                 final String className = spec.getClassName();
181                 final IHeaderMatcher headerMatcher = (IHeaderMatcher) newInstance( IHeaderMatcher.class, className );
182                 list.add( headerMatcher );
183             }
184         }
185 
186         if ( addDefaultLicenseMatchers )
187         {
188             list.addAll( Arrays.asList( Defaults.DEFAULT_MATCHERS ) );
189         }
190         return (IHeaderMatcher[]) list.toArray( new IHeaderMatcher[list.size()] );
191     }
192 
193     private Object newInstance( final Class clazz, final String className )
194         throws MojoExecutionException, MojoFailureException
195     {
196         final Object o;
197         try
198         {
199             final ClassLoader cl = Thread.currentThread().getContextClassLoader();
200             o = cl.loadClass( className ).newInstance();
201         }
202         catch ( InstantiationException e )
203         {
204             throw new MojoExecutionException( "Failed to instantiate class " + className + ": " + e.getMessage(), e );
205         }
206         catch ( ClassCastException e )
207         {
208             throw new MojoExecutionException( "The class " + className + " is not implementing " + clazz.getName()
209                             + ": " + e.getMessage(), e );
210         }
211         catch ( IllegalAccessException e )
212         {
213             throw new MojoExecutionException( "Illegal access to class " + className + ": " + e.getMessage(), e );
214         }
215         catch ( ClassNotFoundException e )
216         {
217             throw new MojoExecutionException( "Class " + className + " not found: " + e.getMessage(), e );
218         }
219 
220         if ( !clazz.isAssignableFrom( o.getClass() ) )
221         {
222             throw new MojoFailureException( "The class " + o.getClass().getName() + " does not implement "
223                             + clazz.getName() );
224         }
225         return o;
226     }
227 
228     /**
229      * Adds the given string array to the list.
230      * 
231      * @param pList
232      *            The list to which the array elements are being added.
233      * @param pArray
234      *            The strings to add to the list.
235      */
236     private void add( List pList, String[] pArray )
237     {
238         if ( pArray != null )
239         {
240             for ( int i = 0; i < pArray.length; i++ )
241             {
242                 pList.add( pArray[i] );
243             }
244         }
245     }
246 
247     /**
248      * Creates an iterator over the files to check.
249      * 
250      * @return A container of files, which are being checked.
251      */
252     protected IReportable getResources()
253     {
254         DirectoryScanner ds = new DirectoryScanner();
255         ds.setBasedir( basedir );
256         setExcludes( ds );
257         setIncludes( ds );
258         ds.scan();
259         final String[] files = ds.getIncludedFiles();
260         try
261         {
262             return new FilesReportable( basedir, files );
263         }
264         catch ( IOException e )
265         {
266             throw new UndeclaredThrowableException( e );
267         }
268     }
269 
270     private void setIncludes( DirectoryScanner ds )
271     {
272         if ( includes != null )
273         {
274             ds.setIncludes( includes );
275         }
276     }
277 
278     private void setExcludes( DirectoryScanner ds )
279     {
280         final List excludeList1 = new ArrayList();
281         if ( useDefaultExcludes )
282         {
283             add( excludeList1, DirectoryScanner.DEFAULTEXCLUDES );
284         }
285         if ( useMavenDefaultExcludes )
286         {
287             add( excludeList1, MAVEN_DEFAULT_EXCLUDES );
288         }
289         if ( useEclipseDefaultExcludes )
290         {
291             add( excludeList1, ECLIPSE_DEFAULT_EXCLUDES );
292         }
293         if ( useIdeaDefaultExcludes )
294         {
295             add( excludeList1, IDEA_DEFAULT_EXCLUDES );
296         }
297         if ( excludeSubProjects && project != null && project.getModules() != null )
298         {
299             for ( Iterator it = project.getModules().iterator(); it.hasNext(); )
300             {
301                 String moduleSubPath = (String) it.next();
302                 excludeList1.add( moduleSubPath + "/**/*" );
303             }
304         }
305         final List excludeList = excludeList1;
306         add( excludeList, excludes );
307         if ( !excludeList.isEmpty() )
308         {
309             String[] allExcludes = (String[]) excludeList.toArray( new String[excludeList.size()] );
310             ds.setExcludes( allExcludes );
311         }
312     }
313 
314     /**
315      * Writes the report to the given stream.
316      * 
317      * @param out The target writer, to which the report is being written.
318      * @param style The stylesheet to use
319      * @throws MojoFailureException
320      *             An error in the plugin configuration was detected.
321      * @throws MojoExecutionException
322      *             Another error occurred while creating the report.
323      */
324     protected void createReport( PrintWriter out, InputStream style ) throws MojoExecutionException, MojoFailureException
325     {
326         HeaderMatcherMultiplexer m = new HeaderMatcherMultiplexer( getLicenseMatchers() );
327         try
328         {
329             rat.Report.report( out, getResources(), style, m, getApprovedLicenseNames() );
330         }
331         catch ( TransformerConfigurationException e )
332         {
333             throw new MojoExecutionException( e.getMessage(), e );
334         }
335         catch ( IOException e )
336         {
337             throw new MojoExecutionException( e.getMessage(), e );
338         }
339         catch ( InterruptedException e )
340         {
341             throw new MojoExecutionException( e.getMessage(), e );
342         }
343         catch ( RatReportFailedException e )
344         {
345             throw new MojoExecutionException( e.getMessage(), e );
346         }
347     }
348 
349     private ILicenseFamily[] getApprovedLicenseNames() throws MojoExecutionException, MojoFailureException
350     {
351         if ( licenseFamilyNames == null || licenseFamilyNames.length == 0 )
352         {
353             return null;
354         }
355         ILicenseFamily[] results = new ILicenseFamily[licenseFamilyNames.length];
356         for ( int i = 0; i < licenseFamilyNames.length; i++ )
357         {
358             LicenseFamilySpecification spec = licenseFamilyNames[i];
359             ILicenseFamily licenseFamily = (ILicenseFamily) newInstance( ILicenseFamily.class, spec.getClassName() );
360             results[i] = licenseFamily;
361         }
362         return results;
363     }
364 }