View Javadoc
1   /*
2    * Copyright 2014 the original author or authors.
3    *
4    * Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0
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  
17  package org.codehaus.gmavenplus.mojo;
18  
19  import org.apache.maven.plugins.annotations.Component;
20  import org.apache.maven.plugins.annotations.Parameter;
21  import org.apache.maven.project.MavenProjectHelper;
22  import org.codehaus.gmavenplus.model.IncludeClasspath;
23  
24  import java.lang.reflect.InvocationTargetException;
25  import java.util.Properties;
26  
27  import static org.codehaus.gmavenplus.util.ReflectionUtils.findConstructor;
28  import static org.codehaus.gmavenplus.util.ReflectionUtils.invokeConstructor;
29  
30  
31  /**
32   * The base tools mojo, which all tool mojos extend.
33   * Note that it references the plugin classloader to pull in dependencies
34   * Groovy didn't include (for things like Ant for AntBuilder, Ivy for @grab, and Jansi for Groovysh).
35   * Note that using the <code>ant</code> property requires Java 8, as the included Ant version was compiled for Java 8.
36   *
37   * @author Keegan Witt
38   * @since 1.1
39   */
40  public abstract class AbstractToolsMojo extends AbstractGroovyMojo {
41  
42      /**
43       * Maven ProjectHelper to use in properties.
44       *
45       * @since 1.3
46       */
47      @Component
48      protected MavenProjectHelper projectHelper;
49  
50      /**
51       * Properties to make available in scripts as variables using the property name. By default will include
52       * <dl>
53       *   <dt>project</dt>
54       *     <dd>A org.apache.maven.project.Project object of the current Maven project.</dd>
55       *   <dt>session</dt>
56       *     <dd>A org.apache.maven.execution.MavenSession object of the current Maven session.</dd>
57       *   <dt>pluginArtifacts</dt>
58       *     <dd>A list of org.apache.maven.artifact.Artifact objects of this plugin's artifacts.</dd>
59       *   <dt>mojoExecution</dt>
60       *     <dd>A org.apache.maven.plugin.MojoExecution object of this plugin's mojo execution.</dd>
61       *   <dt>log</dt>
62       *     <dd>A org.apache.maven.plugin.logging.Log object of Maven's log.</dd>
63       *   <dt>ant</dt>
64       *     <dd>A groovy.util.AntBuilder object (if groovy.ant.AntBuilder or groovy.util.AntBuilder is available).</dd>
65       * </dl>
66       * These can be overridden.
67       *
68       * @since 1.0-beta-3
69       */
70      @Parameter
71      protected Properties properties = new Properties();
72  
73      /**
74       * Whether to allow System.exit() to be used. Should not be set to <code>false</code> when using parallel
75       * execution, as it isn't thread-safe.
76       *
77       * @since 1.2
78       */
79      @Parameter(defaultValue = "true")
80      protected boolean allowSystemExits;
81  
82      /**
83       * Whether to bind each property to a separate variable (otherwise binds properties to a single 'properties' variable).
84       *
85       * @since 1.2
86       */
87      @Parameter(defaultValue = "true")
88      protected boolean bindPropertiesToSeparateVariables;
89  
90      /**
91       * What classpath to include. One of
92       * <ul>
93       *   <li>PROJECT_ONLY</li>
94       *   <li>PROJECT_AND_PLUGIN</li>
95       *   <li>PLUGIN_ONLY</li>
96       * </ul>
97       * Uses the same scope as the required dependency resolution of this mojo. Use only if you know what you're doing.
98       *
99       * @since 1.8.0
100      */
101     @Parameter(defaultValue = "PROJECT_AND_PLUGIN")
102     protected IncludeClasspath includeClasspath;
103 
104     /**
105      * Whether to add all properties from <code>project.properties</code> into properties.
106      *
107      * @since 1.10.1
108      */
109     @Parameter(defaultValue = "false")
110     protected boolean bindAllProjectProperties;
111 
112     /**
113      * Whether to add user session properties from <code>session.userProperties</code> that override project properties
114      * into properties. <code>bindAllSessionUserProperties</code> takes priority over this property if present. Has no
115      * effect if <code>bindAllProjectProperties</code> is <code>false</code>.
116      *
117      * @since 1.10.1
118      */
119     @Parameter(defaultValue = "false")
120     protected boolean bindSessionUserOverrideProperties;
121 
122     /**
123      * Whether to add all properties from <code>session.userProperties</code> into properties. If both
124      * <code>bindAllProjectProperties</code> and <code>bindAllSessionUserProperties</code> are specified, the session
125      * properties will override the project properties, but it will also include properties not present in project
126      * properties. To only include user session properties that are also in project properties, use
127      * <code>bindSessionUserOverrideProperties</code>.
128      *
129      * @since 1.10.1
130      */
131     @Parameter(defaultValue = "false")
132     protected boolean bindAllSessionUserProperties;
133 
134     /**
135      * Initializes the properties field.
136      */
137     protected void initializeProperties() {
138         if (project != null && !properties.containsKey("project")) {
139             properties.put("project", project);
140         }
141         if (session != null && !properties.containsKey("session")) {
142             properties.put("session", session);
143         }
144         if (pluginArtifacts != null && !properties.containsKey("pluginArtifacts")) {
145             properties.put("pluginArtifacts", pluginArtifacts);
146         }
147         if (mojoExecution != null && !properties.containsKey("mojoExecution")) {
148             properties.put("mojoExecution", mojoExecution);
149         }
150         if (!properties.containsKey("log")) {
151             properties.put("log", getLog());
152         }
153         if (projectHelper != null && !properties.containsKey("projectHelper")) {
154             properties.put("projectHelper", projectHelper);
155         }
156         if (!properties.containsKey("ant")) {
157             Object antBuilder = null;
158             try {
159                 antBuilder = invokeConstructor(findConstructor(classWrangler.getClass("groovy.ant.AntBuilder")));
160             } catch (ClassNotFoundException e1) {
161                 getLog().debug("groovy.ant.AntBuilder not available, trying groovy.util.AntBuilder.");
162                 try {
163                     antBuilder = invokeConstructor(findConstructor(classWrangler.getClass("groovy.util.AntBuilder")));
164                 } catch (ClassNotFoundException | IllegalAccessException | InstantiationException | InvocationTargetException e2) {
165                     logUnableToInitializeAntBuilder(e2);
166                 }
167             } catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
168                 logUnableToInitializeAntBuilder(e);
169             }
170             if (antBuilder != null) {
171                 properties.put("ant", antBuilder);
172             }
173         }
174         if (bindSessionUserOverrideProperties && !bindAllProjectProperties) {
175             getLog().warn("bindSessionUserOverrideProperties set without bindAllProjectProperties, ignoring.");
176         }
177         if (bindAllSessionUserProperties && bindSessionUserOverrideProperties) {
178             getLog().warn("bindAllSessionUserProperties and bindSessionUserOverrideProperties both set, bindAllSessionUserProperties will take precedence.");
179         }
180         if (bindAllProjectProperties && project != null) {
181             properties.putAll(project.getProperties());
182         }
183         if (session != null) {
184             if (bindAllSessionUserProperties) {
185                 properties.putAll(session.getUserProperties());
186             } else if (bindAllProjectProperties && bindSessionUserOverrideProperties && project != null) {
187                 for (Object key : project.getProperties().keySet()) {
188                     if (session.getUserProperties().get(key) != null) {
189                         properties.put(key, session.getUserProperties().get(key));
190                     }
191                 }
192             }
193         }
194     }
195 
196     /**
197      * Logs errors that caused the 'ant' object to not be populated.
198      *
199      * @param e the exception causing the failure
200      */
201     protected void logUnableToInitializeAntBuilder(final Throwable e) {
202         getLog().warn("Unable to initialize 'ant' with a new AntBuilder object. Is Groovy a dependency?  If you are using Groovy >= 2.3.0-rc-1, remember to include groovy-ant as a dependency.");
203     }
204 
205 }