Bug 55652 - JavaSampler silently resets classname if class can not be found

Bugzilla Id: 55652

git-svn-id: https://svn.apache.org/repos/asf/jmeter/trunk@1780121 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Philippe Mouawad 2017-01-24 22:18:10 +00:00
parent 290bbd72a3
commit 5a8fc583d8
4 changed files with 70 additions and 35 deletions

View File

@ -442,6 +442,7 @@ ja=Japanese
jar_file=Jar Files
java_request=Java Request
java_request_defaults=Java Request Defaults
java_request_warning=Classname not found in classpath, ensure you add the required jar
javascript_expression=JavaScript expression to evaluate
jexl_expression=JEXL expression to evaluate
jms_auth_required=Required

View File

@ -435,6 +435,7 @@ ja=Japonais
jar_file=Fichiers .jar
java_request=Requ\u00EAte Java
java_request_defaults=Requ\u00EAte Java par d\u00E9faut
java_request_warning=Class introuvable dans le classpath, veuillez ajouter le jar la contenant
javascript_expression=Expression JavaScript \u00E0 \u00E9valuer
jexl_expression=Expression JEXL \u00E0 \u00E9valuer
jms_auth_required=Obligatoire

View File

@ -19,31 +19,35 @@
package org.apache.jmeter.protocol.java.config.gui;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Color;
import java.awt.Font;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.ComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.jmeter.config.Argument;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.config.gui.AbstractConfigGui;
import org.apache.jmeter.config.gui.ArgumentsPanel;
import org.apache.jmeter.gui.util.HorizontalPanel;
import org.apache.jmeter.gui.util.VerticalPanel;
import org.apache.jmeter.protocol.java.config.JavaConfig;
import org.apache.jmeter.protocol.java.sampler.JavaSampler;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerClient;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.testelement.property.JMeterProperty;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.gui.JLabeledChoice;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.jorphan.reflect.ClassFinder;
import org.apache.log.Logger;
@ -53,14 +57,14 @@ import org.apache.log.Logger;
* {@link JavaConfig} object.
*
*/
public class JavaConfigGui extends AbstractConfigGui implements ActionListener {
private static final long serialVersionUID = 240L;
public class JavaConfigGui extends AbstractConfigGui implements ChangeListener {
private static final long serialVersionUID = 241L;
/** Logging */
private static final Logger log = LoggingManager.getLoggerForClass();
/** A combo box allowing the user to choose a test class. */
private JComboBox<String> classnameCombo;
private JLabeledChoice classNameLabeledChoice;
/**
* Indicates whether or not the name of this component should be displayed
@ -72,6 +76,12 @@ public class JavaConfigGui extends AbstractConfigGui implements ActionListener {
/** A panel allowing the user to set arguments for this test. */
private ArgumentsPanel argsPanel;
/**
* Used in case the referenced class is not in classpath or does not implement {@link JavaSamplerClient}
*/
private final JLabel warningLabel;
/**
* Create a new JavaConfigGui as a standalone component.
*/
@ -90,6 +100,8 @@ public class JavaConfigGui extends AbstractConfigGui implements ActionListener {
*/
public JavaConfigGui(boolean displayNameField) {
this.displayName = displayNameField;
ImageIcon image = JMeterUtils.getImage("warning.png");
warningLabel = new JLabel(JMeterUtils.getResString("java_request_warning"), image, SwingConstants.LEFT); // $NON-NLS-1$
init();
}
@ -102,7 +114,7 @@ public class JavaConfigGui extends AbstractConfigGui implements ActionListener {
/**
* Initialize the GUI components and layout.
*/
private void init() {// called from ctor, so must not be overridable
private final void init() {// called from ctor, so must not be overridable
setLayout(new BorderLayout(0, 5));
if (displayName) {
@ -140,31 +152,31 @@ public class JavaConfigGui extends AbstractConfigGui implements ActionListener {
log.debug("Exception getting interfaces.", e);
}
JLabel label = new JLabel(JMeterUtils.getResString("protocol_java_classname")); // $NON-NLS-1$
classNameLabeledChoice = new JLabeledChoice(JMeterUtils.getResString("protocol_java_classname"), possibleClasses.toArray(ArrayUtils.EMPTY_STRING_ARRAY), true, false);
classNameLabeledChoice.addChangeListener(this);
classnameCombo = new JComboBox<>(possibleClasses.toArray(ArrayUtils.EMPTY_STRING_ARRAY));
classnameCombo.addActionListener(this);
classnameCombo.setEditable(false);
label.setLabelFor(classnameCombo);
HorizontalPanel panel = new HorizontalPanel();
panel.add(label);
panel.add(classnameCombo);
warningLabel.setForeground(Color.RED);
Font font = warningLabel.getFont();
warningLabel.setFont(new Font(font.getFontName(), Font.BOLD, (int)(font.getSize()*1.1)));
warningLabel.setVisible(false);
VerticalPanel panel = new VerticalPanel();
panel.add(classNameLabeledChoice);
panel.add(warningLabel);
return panel;
}
/**
* Handle action events for this component. This method currently handles
* events for the classname combo box.
* Handle change events for this component. This method currently handles
* events for the classname JLabeledChoice
*
* @param evt
* the ActionEvent to be handled
*/
@Override
public void actionPerformed(ActionEvent evt) {
if (evt.getSource() == classnameCombo) {
String className = ((String) classnameCombo.getSelectedItem()).trim();
public void stateChanged(ChangeEvent evt) {
if (evt.getSource() == classNameLabeledChoice) {
String className = classNameLabeledChoice.getText().trim();
try {
JavaSamplerClient client = (JavaSamplerClient) Class.forName(className, true,
Thread.currentThread().getContextClassLoader()).newInstance();
@ -204,8 +216,10 @@ public class JavaConfigGui extends AbstractConfigGui implements ActionListener {
}
argsPanel.configure(newArgs);
warningLabel.setVisible(false);
} catch (Exception e) {
log.error("Error getting argument list for " + className, e);
warningLabel.setVisible(true);
}
}
}
@ -229,25 +243,42 @@ public class JavaConfigGui extends AbstractConfigGui implements ActionListener {
argsPanel.configure((Arguments) config.getProperty(JavaSampler.ARGUMENTS).getObjectValue());
String className = config.getPropertyAsString(JavaSampler.CLASSNAME);
if(checkContainsClassName(classnameCombo.getModel(), className)) {
classnameCombo.setSelectedItem(className);
} else {
if(!checkContainsClassName(classNameLabeledChoice, className)) {
classNameLabeledChoice.addValue(className);
}
if(!classOk(className)) {
log.error("Error setting class:'"+className+"' in JavaSampler "+getName()+", check for a missing jar in your jmeter 'search_paths' and 'plugin_dependency_paths' properties");
warningLabel.setVisible(true);
} else {
warningLabel.setVisible(false);
}
classNameLabeledChoice.setText(className);
}
/**
*
* @param className String class name
* @return true if class is ok (exist in classpath and instanceof {@link JavaSamplerClient}
*/
private static boolean classOk(String className) {
try {
JavaSamplerClient client = (JavaSamplerClient) Class.forName(className, true,
Thread.currentThread().getContextClassLoader()).newInstance();
return client instanceof JavaSamplerClient;
} catch (Exception ex) {
return false;
}
}
/**
* Check combo contains className
* @param model ComboBoxModel
* @param classnameChoice ComboBoxModel
* @param className String class name
* @return boolean
*/
private static boolean checkContainsClassName(ComboBoxModel<String> model, String className) {
int size = model.getSize();
Set<String> set = new HashSet<>(size);
for (int i = 0; i < size; i++) {
set.add(model.getElementAt(i));
}
private static boolean checkContainsClassName(JLabeledChoice classnameChoice, String className) {
Set<String> set = new HashSet<>(Arrays.asList(classnameChoice.getItems()));
return set.contains(className);
}
@ -264,7 +295,7 @@ public class JavaConfigGui extends AbstractConfigGui implements ActionListener {
public void modifyTestElement(TestElement config) {
configureTestElement(config);
((JavaConfig) config).setArguments((Arguments) argsPanel.createTestElement());
((JavaConfig) config).setClassname(String.valueOf(classnameCombo.getSelectedItem()));
((JavaConfig) config).setClassname(classNameLabeledChoice.getText().trim());
}
/* (non-Javadoc)
@ -274,7 +305,8 @@ public class JavaConfigGui extends AbstractConfigGui implements ActionListener {
public void clearGui() {
super.clearGui();
this.displayName = true;
this.warningLabel.setVisible(false);
argsPanel.clearGui();
classnameCombo.setSelectedIndex(0);
classNameLabeledChoice.setSelectedIndex(0);
}
}

View File

@ -190,6 +190,7 @@ JMeter now requires Java 8. Ensure you use most up to date version.
<h3>Other Samplers</h3>
<ul>
<li><bug>603982</bug>Guard Exception handler of the <code>JDBCSampler</code> against null messages</li>
<li><bug>55652</bug>JavaSampler silently resets classname if class can not be found</li>
</ul>
<h3>Controllers</h3>