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