1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.codehaus.gmavenplus.mojo;
18
19 import org.apache.maven.artifact.DependencyResolutionRequiredException;
20 import org.apache.maven.plugin.MojoExecutionException;
21 import org.apache.maven.plugins.annotations.Mojo;
22 import org.apache.maven.plugins.annotations.Parameter;
23 import org.apache.maven.plugins.annotations.ResolutionScope;
24 import org.codehaus.gmavenplus.model.internal.Version;
25 import org.codehaus.gmavenplus.util.NoExitSecurityManager;
26
27 import java.lang.reflect.InvocationTargetException;
28 import java.lang.reflect.Method;
29 import java.net.MalformedURLException;
30
31 import static org.codehaus.gmavenplus.mojo.ExecuteMojo.GROOVY_4_0_0_RC_1;
32 import static org.codehaus.gmavenplus.util.ReflectionUtils.findConstructor;
33 import static org.codehaus.gmavenplus.util.ReflectionUtils.findField;
34 import static org.codehaus.gmavenplus.util.ReflectionUtils.findMethod;
35 import static org.codehaus.gmavenplus.util.ReflectionUtils.invokeConstructor;
36 import static org.codehaus.gmavenplus.util.ReflectionUtils.invokeMethod;
37 import static org.codehaus.gmavenplus.util.ReflectionUtils.invokeStaticMethod;
38
39
40
41
42
43
44
45
46
47
48
49 @Mojo(name = "shell", requiresDependencyResolution = ResolutionScope.TEST)
50 public class ShellMojo extends AbstractToolsMojo {
51
52
53
54
55 protected static final Version GROOVY_4_0_0_ALPHA1 = new Version(4, 0, 0, "alpha-1");
56
57
58
59
60
61
62
63
64
65
66 @Parameter(defaultValue = "QUIET")
67 protected String verbosity;
68
69
70
71
72
73
74 @Override
75 public void execute() throws MojoExecutionException {
76 try {
77 setupClassWrangler(project.getTestClasspathElements(), includeClasspath);
78 } catch (MalformedURLException e) {
79 throw new MojoExecutionException("Unable to add project test dependencies to classpath.", e);
80 } catch (DependencyResolutionRequiredException e) {
81 throw new MojoExecutionException("Test dependencies weren't resolved.", e);
82 }
83
84 logPluginClasspath();
85 classWrangler.logGroovyVersion(mojoExecution.getMojoDescriptor().getGoal());
86
87 try {
88 getLog().debug("Project test classpath:\n" + project.getTestClasspathElements());
89 } catch (DependencyResolutionRequiredException e) {
90 getLog().debug("Unable to log project test classpath");
91 }
92
93 if (!groovyVersionSupportsAction()) {
94 getLog().error("Your Groovy version (" + classWrangler.getGroovyVersionString() + ") doesn't support running a shell. The minimum version of Groovy required is " + minGroovyVersion + ". Skipping shell startup.");
95 return;
96 }
97
98 final SecurityManager defaultSecurityManager = System.getSecurityManager();
99 try {
100 if (!allowSystemExits) {
101 getLog().warn("JEP 411 deprecated Security Manager in Java 17 for removal. Therefore `allowSystemExits` is also deprecated for removal.");
102 try {
103 System.setSecurityManager(new NoExitSecurityManager());
104 } catch (UnsupportedOperationException e) {
105 getLog().warn("Attempted to use Security Manager in a JVM where it's disabled by default. You might try `-Djava.security.manager=allow` to override this.");
106 }
107 }
108
109
110 Class<?> shellClass = classWrangler.getClass(groovyAtLeast(GROOVY_4_0_0_ALPHA1) ? "org.apache.groovy.groovysh.Groovysh" : "org.codehaus.groovy.tools.shell.Groovysh");
111 Class<?> bindingClass = classWrangler.getClass("groovy.lang.Binding");
112 Class<?> ioClass = classWrangler.getClass("org.codehaus.groovy.tools.shell.IO");
113 Class<?> verbosityClass = classWrangler.getClass("org.codehaus.groovy.tools.shell.IO$Verbosity");
114 Class<?> loggerClass = classWrangler.getClass("org.codehaus.groovy.tools.shell.util.Logger");
115
116
117 Object shell = setupShell(shellClass, bindingClass, ioClass, verbosityClass, loggerClass);
118
119
120 invokeMethod(findMethod(shellClass, "run", String.class), shell, (String) null);
121 } catch (ClassNotFoundException e) {
122 throw new MojoExecutionException("Unable to get a Groovy class from classpath (" + e.getMessage() + "). Do you have Groovy as a compile dependency in your project or the plugin?", e);
123 } catch (InvocationTargetException e) {
124 if (e.getCause() instanceof NoClassDefFoundError && e.getCause().getMessage() != null && e.getCause().getMessage().contains("jline")) {
125 throw new MojoExecutionException("Unable to get a JLine class from classpath. This might be because of a JLine version mismatch. If you are using Groovy < 2.2.0-beta-1, make sure you include JLine 1.0 as a runtime dependency in your project or the plugin.", e);
126 } else {
127 throw new MojoExecutionException("Error occurred while calling a method on a Groovy class from classpath.", e);
128 }
129 } catch (IllegalAccessException e) {
130 throw new MojoExecutionException("Unable to access a method on a Groovy class from classpath.", e);
131 } catch (InstantiationException e) {
132 throw new MojoExecutionException("Error occurred while instantiating a Groovy class from classpath.", e);
133 } finally {
134 if (!allowSystemExits) {
135 try {
136 System.setSecurityManager(defaultSecurityManager);
137 } catch (UnsupportedOperationException e) {
138 getLog().warn("Attempted to use Security Manager in a JVM where it's disabled by default. You might try `-Djava.security.manager=allow` to override this.");
139 }
140 }
141 }
142 }
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157 protected Object setupShell(final Class<?> shellClass, final Class<?> bindingClass, final Class<?> ioClass, final Class<?> verbosityClass, final Class<?> loggerClass) throws InvocationTargetException, IllegalAccessException, InstantiationException {
158 Object binding = invokeConstructor(findConstructor(bindingClass));
159 initializeProperties();
160 Method setVariable = findMethod(bindingClass, "setVariable", String.class, Object.class);
161 if (bindPropertiesToSeparateVariables) {
162 for (Object k : properties.keySet()) {
163 invokeMethod(setVariable, binding, k, properties.get(k));
164 }
165 } else {
166 if (groovyOlderThan(GROOVY_4_0_0_RC_1)) {
167 invokeMethod(setVariable, binding, "properties", properties);
168 } else {
169 throw new IllegalArgumentException("properties is a read-only property in Groovy " + GROOVY_4_0_0_RC_1 + " and later.");
170 }
171 }
172 Object io = invokeConstructor(findConstructor(ioClass));
173 invokeMethod(findMethod(ioClass, "setVerbosity", verbosityClass), io, invokeStaticMethod(findMethod(verbosityClass, "forName", String.class), verbosity));
174 findField(loggerClass, "io", ioClass).set(null, io);
175
176 return invokeConstructor(findConstructor(shellClass, ClassLoader.class, bindingClass, ioClass), classWrangler.getClassLoader(), binding, io);
177 }
178
179 }