Skip to content

Commit d154f27

Browse files
Alioth4Jvlsi
authored andcommitted
remove reflection
1 parent 96ea3c0 commit d154f27

File tree

6 files changed

+101
-112
lines changed

6 files changed

+101
-112
lines changed

src/core/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ dependencies {
9595
implementation("commons-codec:commons-codec") {
9696
because("DigestUtils")
9797
}
98+
implementation("org.apache-extras.beanshell:bsh:2.0b6") {
99+
because("Direct dependency required from BeanShellInterpreter")
100+
}
98101
runtimeOnly("commons-collections:commons-collections") {
99102
because("Compatibility for old plugins")
100103
}

src/core/src/main/java/org/apache/jmeter/JMeter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,7 @@ static void runInitScripts() {
632632
try {
633633
BeanShellInterpreter bsi = new BeanShellInterpreter();
634634
bsi.source(bshinit);
635-
} catch (ClassNotFoundException|JMeterException e) {
635+
} catch (JMeterException e) {
636636
if (log.isWarnEnabled()) {
637637
log.warn("Could not process Beanshell file: {}", e.getMessage());
638638
}

src/core/src/main/java/org/apache/jmeter/util/BeanShellInterpreter.java

Lines changed: 90 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -18,103 +18,55 @@
1818
package org.apache.jmeter.util;
1919

2020
import java.io.File;
21-
import java.lang.reflect.InvocationTargetException;
22-
import java.lang.reflect.Method;
21+
import java.io.IOException;
2322

2423
import org.apache.commons.lang3.StringUtils;
25-
import org.apache.jorphan.util.JMeterError;
2624
import org.apache.jorphan.util.JMeterException;
2725
import org.slf4j.Logger;
2826
import org.slf4j.LoggerFactory;
2927

28+
import bsh.EvalError;
29+
import bsh.Interpreter;
30+
3031
/**
3132
* BeanShell setup function - encapsulates all the access to the BeanShell
3233
* Interpreter in a single class.
3334
*
34-
* The class uses dynamic class loading to access BeanShell, which means that
35-
* all the source files can be built without needing access to the bsh jar.
36-
*
37-
* If the beanshell jar is not present at run-time, an error will be logged
35+
* This class wraps a BeanShell instance.
3836
*
37+
* Note that reflection-based dynamic class loading has been removed, so the
38+
* bsh jar must be available at compile-time and runtime.
3939
*/
40-
4140
public class BeanShellInterpreter {
4241
private static final Logger log = LoggerFactory.getLogger(BeanShellInterpreter.class);
4342

44-
private static final Method bshGet;
45-
46-
private static final Method bshSet;
47-
48-
private static final Method bshEval;
49-
50-
private static final Method bshSource;
51-
52-
private static final Class<?> bshClass;
53-
54-
private static final String BSH_INTERPRETER = "bsh.Interpreter"; //$NON-NLS-1$
55-
56-
static {
57-
// Temporary copies, so can set the final ones
58-
Method get = null;
59-
Method eval = null;
60-
Method set = null;
61-
Method source = null;
62-
Class<?> clazz = null;
63-
ClassLoader loader = Thread.currentThread().getContextClassLoader();
64-
try {
65-
clazz = loader.loadClass(BSH_INTERPRETER);
66-
Class<String> string = String.class;
67-
Class<Object> object = Object.class;
68-
69-
get = clazz.getMethod("get", string); //$NON-NLS-1$
70-
eval = clazz.getMethod("eval", string); //$NON-NLS-1$
71-
set = clazz.getMethod("set", string, object); //$NON-NLS-1$
72-
source = clazz.getMethod("source", string); //$NON-NLS-1$
73-
} catch (ClassNotFoundException|SecurityException | NoSuchMethodException e) {
74-
log.error("Beanshell Interpreter not found", e);
75-
} finally {
76-
bshEval = eval;
77-
bshGet = get;
78-
bshSet = set;
79-
bshSource = source;
80-
bshClass = clazz;
81-
}
82-
}
83-
8443
// This class is not serialised
85-
private Object bshInstance = null; // The interpreter instance for this class
44+
private Interpreter bshInstance = null; // The interpreter instance for this class
8645

8746
private final String initFile; // Script file to initialize the Interpreter with
8847

8948
private final Logger logger; // Logger to use during initialization and script run
9049

91-
public BeanShellInterpreter() throws ClassNotFoundException {
50+
private static final String BSH_ERROR_TEMPLATE = "Error invoking bsh method: %s";
51+
52+
public BeanShellInterpreter() {
9253
this(null, null);
9354
}
9455

9556
/**
9657
*
9758
* @param init initialisation file
9859
* @param log logger to pass to interpreter
99-
* @throws ClassNotFoundException when beanshell can not be instantiated
10060
*/
101-
public BeanShellInterpreter(String init, Logger log) throws ClassNotFoundException {
61+
public BeanShellInterpreter(String init, Logger log) {
10262
initFile = init;
10363
logger = log;
10464
init();
10565
}
10666

10767
// Called from ctor, so must be private (or final, but it does not seem useful elsewhere)
108-
private void init() throws ClassNotFoundException {
109-
if (bshClass == null) {
110-
throw new ClassNotFoundException(BSH_INTERPRETER);
111-
}
112-
try {
113-
bshInstance = bshClass.getDeclaredConstructor().newInstance();
114-
} catch (IllegalArgumentException | ReflectiveOperationException | SecurityException e) {
115-
log.error("Can't instantiate BeanShell", e);
116-
throw new ClassNotFoundException("Can't instantiate BeanShell", e);
117-
}
68+
private void init() {
69+
bshInstance = new Interpreter();
11870
if (logger != null) {// Do this before starting the script
11971
try {
12072
set("log", logger);//$NON-NLS-1$
@@ -148,65 +100,111 @@ private void init() throws ClassNotFoundException {
148100

149101
/**
150102
* Resets the BeanShell interpreter.
151-
*
152-
* @throws ClassNotFoundException if interpreter cannot be instantiated
153103
*/
154-
public void reset() throws ClassNotFoundException {
104+
public void reset() {
155105
init();
156106
}
157107

158-
private Object bshInvoke(Method m, Object[] o, boolean shouldLog) throws JMeterException {
108+
public Object eval(String s) throws JMeterException {
159109
Object r = null;
160-
final String errorString = "Error invoking bsh method: ";
161110
try {
162-
r = m.invoke(bshInstance, o);
163-
} catch (IllegalArgumentException | IllegalAccessException e) { // Programming error
164-
final String message = errorString + m.getName();
165-
log.error(message);
166-
throw new JMeterError(message, e);
167-
} catch (InvocationTargetException e) { // Can occur at run-time
168-
// could be caused by the bsh Exceptions:
169-
// EvalError, ParseException or TargetError
170-
String message = errorString + m.getName();
111+
r = bshInstance.eval(s);
112+
} catch (EvalError e) {
113+
String message = String.format(BSH_ERROR_TEMPLATE, "eval");
171114
Throwable cause = e.getCause();
172115
if (cause != null) {
173116
message += "\t" + cause.getLocalizedMessage();
174117
}
175-
176-
if (shouldLog) {
177-
log.error(message);
178-
}
118+
log.error(message);
179119
throw new JMeterException(message, e);
180120
}
181121
return r;
182122
}
183123

184-
public Object eval(String s) throws JMeterException {
185-
return bshInvoke(bshEval, new Object[] { s }, true);
186-
}
187-
188124
public Object evalNoLog(String s) throws JMeterException {
189-
return bshInvoke(bshEval, new Object[] { s }, false);
125+
Object r = null;
126+
try {
127+
r = bshInstance.eval(s);
128+
} catch (EvalError e) {
129+
String message = String.format(BSH_ERROR_TEMPLATE, "eval");
130+
Throwable cause = e.getCause();
131+
if (cause != null) {
132+
message += "\t" + cause.getLocalizedMessage();
133+
}
134+
throw new JMeterException(message, e);
135+
}
136+
return r;
190137
}
191138

192-
public Object set(String s, Object o) throws JMeterException {
193-
return bshInvoke(bshSet, new Object[] { s, o }, true);
139+
public void set(String s, Object o) throws JMeterException {
140+
try {
141+
bshInstance.set(s, o);
142+
} catch (EvalError e) {
143+
String message = String.format(BSH_ERROR_TEMPLATE, "set");
144+
Throwable cause = e.getCause();
145+
if (cause != null) {
146+
message += "\t" + cause.getLocalizedMessage();
147+
}
148+
log.error(message);
149+
throw new JMeterException(message, e);
150+
}
194151
}
195152

196-
public Object set(String s, boolean b) throws JMeterException {
197-
return bshInvoke(bshSet, new Object[] { s, b}, true);
153+
public void set(String s, boolean b) throws JMeterException {
154+
try {
155+
bshInstance.set(s, b);
156+
} catch (EvalError e) {
157+
String message = String.format(BSH_ERROR_TEMPLATE, "set");
158+
Throwable cause = e.getCause();
159+
if (cause != null) {
160+
message += "\t" + cause.getLocalizedMessage();
161+
}
162+
log.error(message);
163+
throw new JMeterException(message, e);
164+
}
198165
}
199166

200167
public Object source(String s) throws JMeterException {
201-
return bshInvoke(bshSource, new Object[] { s }, true);
168+
Object r = null;
169+
try {
170+
r = bshInstance.source(s);
171+
} catch (EvalError | IOException e) {
172+
String message = String.format(BSH_ERROR_TEMPLATE, "source");
173+
Throwable cause = e.getCause();
174+
if (cause != null) {
175+
message += "\t" + cause.getLocalizedMessage();
176+
}
177+
log.error(message);
178+
throw new JMeterException(message, e);
179+
}
180+
return r;
202181
}
203182

204183
public Object get(String s) throws JMeterException {
205-
return bshInvoke(bshGet, new Object[] { s }, true);
184+
Object r = null;
185+
try {
186+
r = bshInstance.get(s);
187+
} catch (EvalError e) {
188+
String message = String.format(BSH_ERROR_TEMPLATE, "get");
189+
Throwable cause = e.getCause();
190+
if (cause != null) {
191+
message += "\t" + cause.getLocalizedMessage();
192+
}
193+
log.error(message);
194+
throw new JMeterException(message, e);
195+
}
196+
return r;
206197
}
207198

208199
// For use by Unit Tests
209-
public static boolean isInterpreterPresent(){
200+
public static boolean isInterpreterPresent() {
201+
Class<?> bshClass = null;
202+
ClassLoader loader = Thread.currentThread().getContextClassLoader();
203+
try {
204+
bshClass = loader.loadClass("bsh.Interpreter");
205+
} catch (ClassNotFoundException e) {
206+
log.error("Beanshell Interpreter not found", e);
207+
}
210208
return bshClass != null;
211209
}
212210
}

src/core/src/main/java/org/apache/jmeter/util/BeanShellTestElement.java

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,7 @@ protected BeanShellTestElement() {
7575
*/
7676
protected BeanShellInterpreter getBeanShellInterpreter() {
7777
if (isResetInterpreter()) {
78-
try {
79-
bshInterpreter.reset();
80-
} catch (ClassNotFoundException e) {
81-
log.error("Cannot reset BeanShell: {}", e.toString()); // NOSONAR last arg would be exception
82-
}
78+
bshInterpreter.reset();
8379
}
8480

8581
JMeterContext jmctx = JMeterContextService.getContext();
@@ -101,13 +97,9 @@ private void init() { // WARNING: called from ctor so must not be overridden (i.
10197
parameters=""; // ensure variables are not null
10298
filename="";
10399
script="";
104-
try {
105-
String initFileName = JMeterUtils.getProperty(getInitFileProperty());
106-
hasInitFile = initFileName != null;
107-
bshInterpreter = new BeanShellInterpreter(initFileName, log);
108-
} catch (ClassNotFoundException e) {
109-
log.error("Cannot find BeanShell: {}", e.toString()); // NOSONAR last arg would be exception
110-
}
100+
String initFileName = JMeterUtils.getProperty(getInitFileProperty());
101+
hasInitFile = initFileName != null;
102+
bshInterpreter = new BeanShellInterpreter(initFileName, log);
111103
}
112104

113105
protected Object readResolve() {

src/dist/src/dist/expected_release_jars.csv

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
462124,commons-jexl3-3.2.1.jar
3434
760623,commons-jvm-4.1.0.jar
3535
657952,commons-lang3-3.14.0.jar
36-
70816,commons-logging-1.3.0.jar
36+
73737,commons-logging-1.3.5.jar
3737
2213560,commons-math3-3.6.1.jar
3838
322780,commons-net-3.10.0.jar
3939
150048,commons-pool2-2.12.0.jar
@@ -137,4 +137,4 @@
137137
7188,xmlpull-1.1.3.1.jar
138138
1027769,xmlresolver-5.2.1-data.jar
139139
165689,xmlresolver-5.2.1.jar
140-
644649,xstream-1.4.20.jar
140+
646504,xstream-1.4.21.jar

src/functions/src/main/java/org/apache/jmeter/functions/BeanShell.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -131,11 +131,7 @@ public synchronized void setParameters(Collection<CompoundVariable> parameters)
131131

132132
values = parameters.toArray();
133133

134-
try {
135-
bshInterpreter = new BeanShellInterpreter(JMeterUtils.getProperty(INIT_FILE), log);
136-
} catch (ClassNotFoundException e) {
137-
throw new InvalidVariableException("BeanShell not found", e);
138-
}
134+
bshInterpreter = new BeanShellInterpreter(JMeterUtils.getProperty(INIT_FILE), log);
139135
}
140136

141137
/** {@inheritDoc} */

0 commit comments

Comments
 (0)