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 final SecurityManager sm = System.getSecurityManager();
95 try {
96 if (!allowSystemExits) {
97 System.setSecurityManager(new NoExitSecurityManager());
98 }
99
100
101 Class<?> shellClass = classWrangler.getClass(groovyAtLeast(GROOVY_4_0_0_ALPHA1) ? "org.apache.groovy.groovysh.Groovysh" : "org.codehaus.groovy.tools.shell.Groovysh");
102 Class<?> bindingClass = classWrangler.getClass("groovy.lang.Binding");
103 Class<?> ioClass = classWrangler.getClass("org.codehaus.groovy.tools.shell.IO");
104 Class<?> verbosityClass = classWrangler.getClass("org.codehaus.groovy.tools.shell.IO$Verbosity");
105 Class<?> loggerClass = classWrangler.getClass("org.codehaus.groovy.tools.shell.util.Logger");
106
107
108 Object shell = setupShell(shellClass, bindingClass, ioClass, verbosityClass, loggerClass);
109
110
111 invokeMethod(findMethod(shellClass, "run", String.class), shell, (String) null);
112 } catch (ClassNotFoundException e) {
113 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);
114 } catch (InvocationTargetException e) {
115 if (e.getCause() instanceof NoClassDefFoundError && e.getCause().getMessage() != null && e.getCause().getMessage().contains("jline")) {
116 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);
117 } else {
118 throw new MojoExecutionException("Error occurred while calling a method on a Groovy class from classpath.", e);
119 }
120 } catch (IllegalAccessException e) {
121 throw new MojoExecutionException("Unable to access a method on a Groovy class from classpath.", e);
122 } catch (InstantiationException e) {
123 throw new MojoExecutionException("Error occurred while instantiating a Groovy class from classpath.", e);
124 } finally {
125 if (!allowSystemExits) {
126 System.setSecurityManager(sm);
127 }
128 }
129 } else {
130 getLog().error("Your Groovy version (" + classWrangler.getGroovyVersionString() + ") doesn't support running a shell. The minimum version of Groovy required is " + minGroovyVersion + ". Skipping shell startup.");
131 }
132 }
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147 protected Object setupShell(final Class<?> shellClass, final Class<?> bindingClass, final Class<?> ioClass, final Class<?> verbosityClass, final Class<?> loggerClass) throws InvocationTargetException, IllegalAccessException, InstantiationException {
148 Object binding = invokeConstructor(findConstructor(bindingClass));
149 initializeProperties();
150 Method setVariable = findMethod(bindingClass, "setVariable", String.class, Object.class);
151 if (bindPropertiesToSeparateVariables) {
152 for (Object k : properties.keySet()) {
153 invokeMethod(setVariable, binding, k, properties.get(k));
154 }
155 } else {
156 if (groovyOlderThan(GROOVY_4_0_0_RC_1)) {
157 invokeMethod(setVariable, binding, "properties", properties);
158 } else {
159 throw new IllegalArgumentException("properties is a read-only property in Groovy " + GROOVY_4_0_0_RC_1 + " and later.");
160 }
161 }
162 Object io = invokeConstructor(findConstructor(ioClass));
163 invokeMethod(findMethod(ioClass, "setVerbosity", verbosityClass), io, invokeStaticMethod(findMethod(verbosityClass, "forName", String.class), verbosity));
164 findField(loggerClass, "io", ioClass).set(null, io);
165
166 return invokeConstructor(findConstructor(shellClass, ClassLoader.class, bindingClass, ioClass), classWrangler.getClassLoader(), binding, io);
167 }
168
169 }