1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.shared.scriptinterpreter;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.PrintStream;
24 import java.io.UncheckedIOException;
25 import java.net.MalformedURLException;
26 import java.net.URL;
27 import java.net.URLClassLoader;
28 import java.util.List;
29 import java.util.Map;
30
31 import bsh.Capabilities;
32 import bsh.EvalError;
33 import bsh.Interpreter;
34 import bsh.TargetError;
35
36
37
38
39
40
41 class BeanShellScriptInterpreter implements ScriptInterpreter {
42
43 private static class ChildFirstURLClassLoader extends URLClassLoader {
44 ChildFirstURLClassLoader() {
45 super(new URL[] {}, Thread.currentThread().getContextClassLoader());
46 }
47
48 @Override
49 public void addURL(URL url) {
50 super.addURL(url);
51 }
52
53 @Override
54 protected synchronized Class<?> loadClass(final String name, final boolean resolve)
55 throws ClassNotFoundException {
56
57 Class<?> c = findLoadedClass(name);
58 if (c != null) {
59 return c;
60 }
61
62 try {
63 c = super.findClass(name);
64 } catch (ClassNotFoundException e) {
65
66 }
67
68 if (c == null) {
69 c = super.loadClass(name, resolve);
70 }
71
72 if (resolve) {
73 resolveClass(c);
74 }
75
76 return c;
77 }
78
79 @Override
80 public URL getResource(final String name) {
81 URL url = findResource(name);
82 return url != null ? url : super.getResource(name);
83 }
84 }
85
86 private final ChildFirstURLClassLoader classLoader = new ChildFirstURLClassLoader();
87
88 @Override
89 public void setClassPath(List<String> classPath) {
90 if (classPath == null || classPath.isEmpty()) {
91 return;
92 }
93
94 classPath.stream().map(this::toUrl).forEach(classLoader::addURL);
95 }
96
97 private URL toUrl(String path) {
98 try {
99 return new File(path).toURI().toURL();
100 } catch (MalformedURLException e) {
101 throw new UncheckedIOException(e);
102 }
103 }
104
105 @Override
106 public Object evaluateScript(String script, Map<String, ?> globalVariables, PrintStream scriptOutput)
107 throws ScriptEvaluationException {
108 PrintStream origOut = System.out;
109 PrintStream origErr = System.err;
110
111 try {
112 Interpreter engine = new Interpreter();
113
114 if (scriptOutput != null) {
115 System.setErr(scriptOutput);
116 System.setOut(scriptOutput);
117 engine.setErr(scriptOutput);
118 engine.setOut(scriptOutput);
119 }
120
121 if (!Capabilities.haveAccessibility()) {
122 try {
123 Capabilities.setAccessibility(true);
124 } catch (Exception e) {
125 if (scriptOutput != null) {
126 e.printStackTrace(scriptOutput);
127 }
128 }
129 }
130
131 engine.setClassLoader(classLoader);
132
133 if (globalVariables != null) {
134 for (Map.Entry<String, ?> entry : globalVariables.entrySet()) {
135 try {
136 engine.set(entry.getKey(), entry.getValue());
137 } catch (EvalError e) {
138 throw new RuntimeException(e);
139 }
140 }
141 }
142 ClassLoader curentClassLoader = Thread.currentThread().getContextClassLoader();
143 try {
144 Thread.currentThread().setContextClassLoader(classLoader);
145 return engine.eval(script);
146 } catch (TargetError e) {
147 throw new ScriptEvaluationException(e.getTarget());
148 } catch (ThreadDeath e) {
149 throw e;
150 } catch (Throwable e) {
151 throw new ScriptEvaluationException(e);
152 } finally {
153 Thread.currentThread().setContextClassLoader(curentClassLoader);
154 }
155 } finally {
156 System.setErr(origErr);
157 System.setOut(origOut);
158 }
159 }
160
161 @Override
162 public void close() throws IOException {
163 classLoader.close();
164 }
165 }