View Javadoc

1   /**
2    * Copyright 2010-2012 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.codehaus.mojo.license;
17  
18  import java.io.File;
19  import java.util.Arrays;
20  
21  import org.apache.commons.lang.StringUtils;
22  import org.apache.maven.execution.MavenSession;
23  import org.apache.maven.plugin.AbstractMojo;
24  import org.apache.maven.plugin.MojoExecutionException;
25  import org.apache.maven.plugin.MojoFailureException;
26  import org.apache.maven.project.MavenProject;
27  import org.codehaus.plexus.util.ReaderFactory;
28  
29  /**
30   * Abstract license mojo.
31   *
32   * @author tchemit <chemit@codelutin.com>
33   * @since 1.0
34   */
35  public abstract class AbstractLicenseMojo extends AbstractMojo {
36  
37      /**
38       * Current maven session. (used to launch certain mojo once by build).
39       *
40       * @parameter expression="${session}"
41       * @required
42       * @readonly
43       * @since 1.0
44       */
45      private MavenSession session;
46  
47      /**
48       * The reacted project.
49       *
50       * @parameter default-value="${project}"
51       * @required
52       * @since 1.0
53       */
54      private MavenProject project;
55  
56      /**
57       * Flag to activate verbose mode.
58       * <p/>
59       * <b>Note:</b> Verbose mode is always on if you starts a debug maven instance (says via {@code -X}).
60       *
61       * @parameter expression="${license.verbose}" default-value="${maven.verbose}"
62       * @since 1.0
63       */
64      private boolean verbose;
65  
66      /**
67       * Encoding used to read and writes files.
68       * <p/>
69       * <b>Note:</b> If nothing is filled here, we will use the system property {@code file.encoding}.
70       *
71       * @parameter expression="${license.encoding}" default-value="${project.build.sourceEncoding}"
72       * @since 1.0
73       */
74      private String encoding;
75  
76      public final String getEncoding() {
77          return encoding;
78      }
79  
80      public final void setEncoding(String encoding) {
81          this.encoding = encoding;
82      }
83  
84      /**
85       * Method to initialize the mojo before doing any concrete actions.
86       * <p/>
87       * <b>Note:</b> The method is invoked before the {@link #doAction()} method.
88       *
89       * @throws Exception
90       *             if any
91       */
92      protected abstract void init() throws Exception;
93  
94      /**
95       * Do plugin action.
96       * <p/>
97       * The method {@link #execute()} invoke this method only and only if :
98       * <ul>
99       * <li>{@link #checkPackaging()} returns {@code true}.</li>
100      * <li>method {@link #init()} returns {@code true}.</li>
101      * </ul>
102      *
103      * @throws Exception
104      *             if any
105      */
106     protected abstract void doAction() throws Exception;
107 
108     @Override
109     public final void execute() throws MojoExecutionException, MojoFailureException {
110         try {
111             if (getLog().isDebugEnabled()) {
112 
113                 // always be verbose in debug mode
114                 setVerbose(true);
115             }
116 
117             // check if project packaging is compatible with the mojo
118 
119             boolean canContinue = checkPackaging();
120             if (!canContinue) {
121                 getLog().debug("Skip for packaging '" + getProject().getPackaging() + "'");
122                 return;
123             }
124 
125             // init the mojo
126 
127             try {
128 
129                 checkEncoding();
130 
131                 init();
132 
133             } catch (MojoFailureException e) {
134                 throw e;
135             } catch (MojoExecutionException e) {
136                 throw e;
137             } catch (Exception e) {
138                 throw new MojoExecutionException("could not init goal " + getClass().getSimpleName() + " for reason : "
139                         + e.getMessage(), e);
140             }
141 
142             // check if mojo can be skipped
143 
144             canContinue = checkSkip();
145             if (!canContinue) {
146                 if (isVerbose()) {
147                     getLog().info("Goal will not be executed.");
148                 }
149                 return;
150             }
151 
152             // can really execute the mojo
153 
154             try {
155 
156                 doAction();
157 
158             } catch (MojoFailureException e) {
159                 throw e;
160             } catch (MojoExecutionException e) {
161                 throw e;
162             } catch (Exception e) {
163                 throw new MojoExecutionException("could not execute goal " + getClass().getSimpleName()
164                         + " for reason : " + e.getMessage(), e);
165             }
166         } finally {
167             afterExecute();
168         }
169     }
170 
171     /**
172      * A call back to execute after the {@link #execute()} is done
173      */
174     protected void afterExecute() {
175         // by default do nothing
176     }
177 
178     /**
179      * Check if the project packaging is acceptable for the mojo.
180      * <p/>
181      * By default, accept all packaging types.
182      * <p/>
183      * <b>Note:</b> This method is the first instruction to be executed in the {@link #execute()}.
184      * <p/>
185      * <b>Tip:</b> There is two method to simplify the packaging check :
186      * <p/>
187      * {@link #acceptPackaging(String...)}
188      * <p/>
189      * and
190      * <p/>
191      * {@link #rejectPackaging(String...)}
192      *
193      * @return {@code true} if can execute the goal for the packaging of the project, {@code false} otherwise.
194      */
195     protected boolean checkPackaging() {
196         // by default, accept every type of packaging
197         return true;
198     }
199 
200     /**
201      * Checks if the mojo execution should be skipped.
202      *
203      * @return {@code false} if the mojo should not be executed.
204      */
205     protected boolean checkSkip() {
206         // by default, never skip goal
207         return true;
208     }
209 
210     /**
211      * Accept the project's packaging between some given.
212      *
213      * @param packages
214      *            the accepted packaging
215      * @return {@code true} if the project's packaging is one of the given ones.
216      */
217     protected boolean acceptPackaging(String... packages) {
218         String projectPackaging = getProject().getPackaging();
219 
220         for (String p : packages) {
221             if (p.equals(projectPackaging)) {
222                 // accept packaging
223                 return true;
224             }
225         }
226         // reject packaging
227         return false;
228     }
229 
230     /**
231      * Accept the project's packaging if not in given one.
232      *
233      * @param packages
234      *            the rejecting packagings
235      * @return {@code true} if the project's packaging is not in the given ones.
236      */
237     protected boolean rejectPackaging(String... packages) {
238         String projectPackaging = getProject().getPackaging();
239 
240         for (String p : packages) {
241             if (p.equals(projectPackaging)) {
242                 // reject this packaging
243                 return false;
244             }
245         }
246         // accept packaging
247         return true;
248     }
249 
250     /**
251      * Method to be invoked in init phase to check sanity of {@link #getEncoding()}.
252      * <p/>
253      * If no encoding was filled, then use the default for system (via {@code file.encoding} environement property).
254      */
255     protected void checkEncoding() {
256 
257         if (isVerbose()) {
258             getLog().info("Will check encoding : " + getEncoding());
259         }
260         if (StringUtils.isEmpty(getEncoding())) {
261             getLog().warn(
262                     "File encoding has not been set, using platform encoding " + ReaderFactory.FILE_ENCODING
263                             + ", i.e. build is platform dependent!");
264             setEncoding(ReaderFactory.FILE_ENCODING);
265         }
266     }
267 
268     public final MavenProject getProject() {
269         return project;
270     }
271 
272     public final void setProject(MavenProject project) {
273         this.project = project;
274     }
275 
276     public final boolean isVerbose() {
277         return verbose;
278     }
279 
280     public final void setVerbose(boolean verbose) {
281         this.verbose = verbose;
282     }
283 
284     public final MavenSession getSession() {
285         return session;
286     }
287 
288     public final void setSession(MavenSession session) {
289         this.session = session;
290     }
291 
292     public final long getBuildTimestamp() {
293         return session.getStartTime().getTime();
294     }
295 
296     /**
297      * Add a new resource location to the maven project (in not already present).
298      *
299      * @param dir
300      *            the new resource location to add
301      * @param includes
302      *            files to include
303      */
304     protected void addResourceDir(File dir, String... includes) {
305         boolean added = MojoHelper.addResourceDir(dir, getProject(), includes);
306         if (added && isVerbose()) {
307             getLog().info("add resource " + dir + " with includes " + Arrays.toString(includes));
308         }
309     }
310 
311     /**
312      * @return {@code true} if project is not a pom, {@code false} otherwise.
313      */
314     protected boolean hasClassPath() {
315         return rejectPackaging("pom");
316     }
317 
318 }