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