1 /*
2 * Copyright (C) 2011 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.artifact.Artifact;
20 import org.apache.maven.execution.MavenSession;
21 import org.apache.maven.plugin.AbstractMojo;
22 import org.apache.maven.plugin.MojoExecution;
23 import org.apache.maven.plugins.annotations.Parameter;
24 import org.apache.maven.project.MavenProject;
25 import org.codehaus.gmavenplus.model.IncludeClasspath;
26 import org.codehaus.gmavenplus.model.internal.Version;
27 import org.codehaus.gmavenplus.util.ClassWrangler;
28
29 import java.io.File;
30 import java.net.MalformedURLException;
31 import java.util.List;
32
33 import static java.util.Collections.emptyList;
34
35
36 /**
37 * The base mojo class, which all other mojos extend.
38 *
39 * @author Keegan Witt
40 * @since 1.0-beta-1
41 */
42 public abstract class AbstractGroovyMojo extends AbstractMojo {
43
44 /**
45 * The pattern defining Groovy files.
46 */
47 protected static final String GROOVY_SOURCES_PATTERN = "**" + File.separator + "*.groovy";
48
49 /**
50 * The pattern defining Java stub files.
51 */
52 protected static final String JAVA_SOURCES_PATTERN = "**" + File.separator + "*.java";
53
54 /**
55 * Java 1.7 version.
56 */
57 protected static final Version JAVA_1_7 = new Version(1, 7);
58
59 /**
60 * Java 1.8 version.
61 */
62 protected static final Version JAVA_1_8 = new Version(1, 8);
63
64 /**
65 * Java 1.8 version.
66 */
67 protected static final Version JAVA_12 = new Version(12);
68
69 /**
70 * Groovy 1.5.0 version.
71 */
72 protected static final Version GROOVY_1_5_0 = new Version(1, 5, 0);
73
74 /**
75 * The wrangler to use to work with Groovy classes, classpaths, classLoaders, and versions.
76 */
77 protected ClassWrangler classWrangler;
78
79 // note that all supported parameter expressions can be found here: https://git-wip-us.apache.org/repos/asf?p=maven.git;a=blob;f=maven-core/src/main/java/org/apache/maven/plugin/PluginParameterExpressionEvaluator.java;hb=HEAD
80
81 /**
82 * The Maven project this plugin is being used on.
83 */
84 @Parameter(property = "project", required = true, readonly = true)
85 protected MavenProject project;
86
87 /**
88 * The Maven Session this plugin is being used on.
89 */
90 @Parameter(property = "session", required = true, readonly = true)
91 protected MavenSession session;
92
93 /**
94 * The plugin dependencies.
95 */
96 @Parameter(property = "plugin.artifacts", required = true, readonly = true)
97 protected List<Artifact> pluginArtifacts;
98
99 /**
100 * The plugin's mojo execution.
101 */
102 @Parameter(property = "mojoExecution", required = true, readonly = true)
103 protected MojoExecution mojoExecution;
104
105 /**
106 * The minimum version of Groovy that this mojo supports (1.5.0 by
107 * default, but other mojos can override).
108 */
109 protected Version minGroovyVersion = GROOVY_1_5_0;
110
111 /**
112 * Logs the plugin classpath.
113 */
114 protected void logPluginClasspath() {
115 if (getLog().isDebugEnabled()) {
116 StringBuilder sb = new StringBuilder();
117 for (int i = 0; i < pluginArtifacts.size(); i++) {
118 sb.append(pluginArtifacts.get(i).getFile());
119 if (i < pluginArtifacts.size() - 1) {
120 sb.append(", ");
121 }
122 }
123 getLog().debug("Plugin classpath:\n" + sb);
124 }
125 }
126
127 /**
128 * Determines whether the version of Java executing this mojo supports invokedynamic (is at least 1.7).
129 *
130 * @return <code>true</code> if the running Java supports invokedynamic, <code>false</code> otherwise
131 */
132 protected boolean isJavaSupportIndy() {
133 return getJavaVersion().compareTo(JAVA_1_7, false) >= 0;
134 }
135
136 /**
137 * Determines whether the version of Java executing this mojo supports preview features (is at least 12).
138 *
139 * @return <code>true</code> if the running Java supports preview features, <code>false</code> otherwise
140 */
141 protected boolean isJavaSupportPreviewFeatures() {
142 return getJavaVersion().compareTo(JAVA_12, false) >= 0;
143 }
144
145 /**
146 * Determines whether the version of Java executing this mojo supports JEP 118 (is at least 1.8).
147 *
148 * @return <code>true</code> if the running Java supports parameters, <code>false</code> otherwise
149 */
150 protected boolean isJavaSupportParameters() {
151 return getJavaVersion().compareTo(JAVA_1_8, false) >= 0;
152 }
153
154 /**
155 * Gets the version of Java executing this mojo as a Version object.
156 *
157 * @return a Version object of the running Java version
158 */
159 protected Version getJavaVersion() {
160 return Version.parseFromString(getJavaVersionString());
161 }
162
163 /**
164 * Gets the version of Java executing this mojo as a String.
165 *
166 * @return a String of the running Java version
167 */
168 protected String getJavaVersionString() {
169 return System.getProperty("java.version");
170 }
171
172 /**
173 * Determines whether this mojo can be run with the version of Groovy supplied.
174 *
175 * @return <code>true</code> only if the version of Groovy supports this mojo
176 */
177 protected boolean groovyVersionSupportsAction() {
178 return classWrangler.getGroovyVersion() != null && groovyAtLeast(minGroovyVersion);
179 }
180
181 /**
182 * Determines whether the detected Groovy version is the specified version or newer.
183 *
184 * @param version the version to compare the detected Groovy version to
185 * @return <code>true</code> if the detected Groovy version is the specified version or newer, <code>false</code> otherwise
186 */
187 protected boolean groovyAtLeast(Version version) {
188 return ClassWrangler.groovyAtLeast(classWrangler.getGroovyVersion(), version);
189 }
190
191 /**
192 * Determines whether the detected Groovy version is the specified version.
193 *
194 * @param version the version to compare the detected Groovy version to
195 * @return <code>true</code> if the detected Groovy version is the specified version, <code>false</code> otherwise
196 */
197 protected boolean groovyIs(Version version) {
198 return ClassWrangler.groovyIs(classWrangler.getGroovyVersion(), version);
199 }
200
201 /**
202 * Determines whether the detected Groovy version is newer than the specified version.
203 *
204 * @param version the version to compare the detected Groovy version to
205 * @return <code>true</code> if the detected Groovy version is newer than the specified version, <code>false</code> otherwise
206 */
207 protected boolean groovyNewerThan(Version version) {
208 return ClassWrangler.groovyNewerThan(classWrangler.getGroovyVersion(), version);
209 }
210
211 /**
212 * Determines whether the detected Groovy version is older than the specified version.
213 *
214 * @param version the version to compare the detected Groovy version to
215 * @return <code>true</code> if the detected Groovy version is older than the specified version, <code>false</code> otherwise
216 */
217 protected boolean groovyOlderThan(Version version) {
218 return ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), version);
219 }
220
221 /**
222 * Gets whether the version of Groovy on the classpath supports invokedynamic.
223 *
224 * @return <code>true</code> if the version of Groovy uses invokedynamic,
225 * <code>false</code> if not or Groovy dependency cannot be found
226 */
227 protected boolean isGroovyIndy() {
228 return classWrangler.isGroovyIndy();
229 }
230
231 /**
232 * Instantiate a ClassWrangler.
233 *
234 * @param classpath the classpath to load onto a new classloader (if includeClasspath is <code>PROJECT_ONLY</code>)
235 * @param includeClasspath whether to use a shared classloader that includes both the project classpath and plugin classpath.
236 * @throws MalformedURLException when a classpath element provides a malformed URL
237 */
238 protected void setupClassWrangler(List<?> classpath, IncludeClasspath includeClasspath) throws MalformedURLException {
239 if (IncludeClasspath.PROJECT_ONLY.equals(includeClasspath)) {
240 getLog().info("Using isolated classloader, without GMavenPlus classpath.");
241 classWrangler = new ClassWrangler(classpath, ClassLoader.getSystemClassLoader(), getLog());
242 } else if (IncludeClasspath.PROJECT_AND_PLUGIN.equals(includeClasspath)) {
243 getLog().info("Using plugin classloader, includes GMavenPlus and project classpath.");
244 classWrangler = new ClassWrangler(classpath, getClass().getClassLoader(), getLog());
245 } else {
246 getLog().info("Using plugin classloader, includes GMavenPlus classpath, but not project classpath.");
247 classWrangler = new ClassWrangler(emptyList(), getClass().getClassLoader(), getLog());
248 }
249 }
250 }