mirror of https://github.com/apache/jmeter.git
feat: use ServiceLoader to find implementations instead of searching classes in jars (#5885)
ServiceLoader is Java standard approach for locating implementaitons, and it allows pluggability without relying on a filesystem layout. Fixes https://github.com/apache/jmeter/issues/5883
This commit is contained in:
parent
5542be18d8
commit
eedabdd6c0
|
@ -24,6 +24,7 @@ dependencies {
|
|||
api(projects.verification)
|
||||
api("com.github.vlsi.crlf:com.github.vlsi.crlf.gradle.plugin:1.88")
|
||||
api("com.github.vlsi.gradle-extensions:com.github.vlsi.gradle-extensions.gradle.plugin:1.88")
|
||||
api("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.21")
|
||||
api("org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.8.21")
|
||||
api("org.jetbrains.kotlin.kapt:org.jetbrains.kotlin.kapt.gradle.plugin:1.8.21")
|
||||
api("org.jetbrains.dokka:org.jetbrains.dokka.gradle.plugin:1.8.10")
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to you under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import com.github.vlsi.gradle.dsl.configureEach
|
||||
|
||||
plugins {
|
||||
id("java-library")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
annotationProcessor("com.google.auto.service:auto-service")
|
||||
compileOnlyApi("com.google.auto.service:auto-service-annotations")
|
||||
}
|
||||
|
||||
tasks.configureEach<JavaCompile> {
|
||||
// Verify @AutoService annotations
|
||||
options.compilerArgs.add("-Averify=true")
|
||||
}
|
||||
|
||||
plugins.withId("org.jetbrains.kotlin.jvm") {
|
||||
apply(plugin = "org.jetbrains.kotlin.kapt")
|
||||
|
||||
dependencies {
|
||||
"kapt"("com.google.auto.service:auto-service")
|
||||
// Unfortunately, plugins.withId("..kapt") can't be used as kapt plugin adds configuration via plugins.withId
|
||||
findProject(":src:bom-thirdparty")?.let {
|
||||
"kapt"(platform(it))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.configureEach<Jar> {
|
||||
manifest {
|
||||
attributes["JMeter-Skip-Class-Scanning"] = "true"
|
||||
}
|
||||
}
|
|
@ -18,4 +18,5 @@
|
|||
plugins {
|
||||
id("build-logic.java")
|
||||
id("java-library")
|
||||
id("build-logic.autoservice")
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@ dependencies {
|
|||
}
|
||||
findProject(":src:bom-thirdparty")?.let{
|
||||
api(platform(it))
|
||||
annotationProcessor(platform(it))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,7 @@
|
|||
*/
|
||||
|
||||
plugins {
|
||||
id("build-logic.java")
|
||||
id("java-library")
|
||||
id("build-logic.java-library")
|
||||
}
|
||||
|
||||
if (file("src/main/groovy").isDirectory || file("src/test/groovy").isDirectory) {
|
||||
|
|
|
@ -25,6 +25,7 @@ plugins {
|
|||
id("build-logic.test-base")
|
||||
id("com.github.autostyle")
|
||||
kotlin("jvm")
|
||||
kotlin("kapt") apply false
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
|
|
@ -27,4 +27,5 @@ dependencies {
|
|||
api("com.github.vlsi.gradle-extensions:com.github.vlsi.gradle-extensions.gradle.plugin:1.88")
|
||||
api("org.nosphere.apache.rat:org.nosphere.apache.rat.gradle.plugin:0.8.0")
|
||||
api("org.jetbrains.gradle.plugin.idea-ext:org.jetbrains.gradle.plugin.idea-ext.gradle.plugin:1.1.7")
|
||||
api("org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.8.21")
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ plugins {
|
|||
id("com.github.vlsi.ide")
|
||||
id("org.nosphere.apache.rat")
|
||||
id("org.jetbrains.gradle.plugin.idea-ext")
|
||||
kotlin("jvm") apply false
|
||||
}
|
||||
|
||||
ide {
|
||||
|
|
|
@ -61,6 +61,7 @@ val notPublishedProjects by extra {
|
|||
projects.src.release,
|
||||
projects.src.testkit,
|
||||
projects.src.testkitWiremock,
|
||||
projects.src.testServices,
|
||||
).mapTo(mutableSetOf()) { it.dependencyProject }
|
||||
}
|
||||
|
||||
|
@ -86,7 +87,7 @@ publishedProjects.forEach {project ->
|
|||
throw IllegalStateException(
|
||||
"Project ${project.path} is listed in publishedProjects, however it misses maven-publish plugin. " +
|
||||
"Please add maven-publish plugin (e.g. replace build-logic.jvm-library with build-logic.jvm-published-library) or " +
|
||||
"move the project to the list of published ones"
|
||||
"move the project to the list of notPublishedProjects"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ org.gradle.parallel=true
|
|||
org.gradle.caching=true
|
||||
#org.gradle.caching.debug=true
|
||||
|
||||
kapt.include.compile.classpath=false
|
||||
|
||||
# See https://github.com/gradle/gradle/pull/11358 , https://issues.apache.org/jira/browse/INFRA-14923
|
||||
# repository.apache.org does not yet support .sha256 and .sha512 checksums
|
||||
systemProp.org.gradle.internal.publish.checksums.insecure=true
|
||||
|
|
|
@ -76,6 +76,7 @@ include(
|
|||
"src:release",
|
||||
"src:testkit",
|
||||
"src:testkit-wiremock",
|
||||
"src:test-services",
|
||||
"src:dist",
|
||||
"src:dist-check"
|
||||
)
|
||||
|
|
|
@ -42,6 +42,8 @@ dependencies {
|
|||
|
||||
api("bsf:bsf:2.4.0")
|
||||
api("cglib:cglib-nodep:3.3.0")
|
||||
api("com.google.auto.service:auto-service:1.0.1")
|
||||
api("com.google.auto.service:auto-service-annotations:1.0.1")
|
||||
api("com.fasterxml.jackson.core:jackson-annotations:2.13.4")
|
||||
api("com.fasterxml.jackson.core:jackson-core:2.13.4")
|
||||
api("com.fasterxml.jackson.core:jackson-databind:2.13.4.2")
|
||||
|
|
|
@ -19,6 +19,7 @@ package org.apache.jmeter.extractor.json.render;
|
|||
|
||||
import org.apache.jmeter.extractor.json.jmespath.JMESPathCache;
|
||||
import org.apache.jmeter.util.JMeterUtils;
|
||||
import org.apache.jmeter.visualizers.ResultRenderer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -26,11 +27,13 @@ import com.fasterxml.jackson.core.JsonProcessingException;
|
|||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Implement ResultsRender for JMES Path tester
|
||||
* @since 5.2
|
||||
*/
|
||||
@AutoService(ResultRenderer.class)
|
||||
public class RenderAsJmesPathRenderer extends AbstractRenderAsJsonRenderer {
|
||||
private static final Logger log = LoggerFactory.getLogger(RenderAsJmesPathRenderer.class);
|
||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||
|
|
|
@ -21,13 +21,17 @@ import java.util.List;
|
|||
|
||||
import org.apache.jmeter.extractor.json.jsonpath.JSONManager;
|
||||
import org.apache.jmeter.util.JMeterUtils;
|
||||
import org.apache.jmeter.visualizers.ResultRenderer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Implement ResultsRender for JSON Path tester
|
||||
* @since 3.0
|
||||
*/
|
||||
@AutoService(ResultRenderer.class)
|
||||
public class RenderAsJsonRenderer extends AbstractRenderAsJsonRenderer {
|
||||
private static final Logger log = LoggerFactory.getLogger(RenderAsJsonRenderer.class);
|
||||
|
||||
|
|
|
@ -53,10 +53,16 @@ import org.apache.jorphan.gui.ComponentUtil;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Export transactions names for web report
|
||||
* @since 3.3
|
||||
*/
|
||||
@AutoService({
|
||||
Command.class,
|
||||
MenuCreator.class
|
||||
})
|
||||
public class ExportTransactionAndSamplerNames extends AbstractAction implements MenuCreator {
|
||||
private static final Logger log = LoggerFactory.getLogger(ExportTransactionAndSamplerNames.class);
|
||||
|
||||
|
|
|
@ -41,9 +41,12 @@ import org.apache.jmeter.util.JMeterUtils;
|
|||
import org.apache.jorphan.gui.GuiUtils;
|
||||
import org.apache.jorphan.gui.JLabeledTextField;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Implement ResultsRender for Boundary Extractor tester
|
||||
*/
|
||||
@AutoService(ResultRenderer.class)
|
||||
public class RenderAsBoundaryExtractor implements ResultRenderer, ActionListener {
|
||||
|
||||
private static final String BOUNDARY_EXTRACTOR_TESTER_COMMAND = "boundary_extractor_tester"; // $NON-NLS-1$
|
||||
|
|
|
@ -49,10 +49,13 @@ import org.apache.jorphan.gui.JLabeledChoice;
|
|||
import org.apache.jorphan.gui.JLabeledTextField;
|
||||
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Implement ResultsRender for CSS/JQuery tester
|
||||
* @since 2.10
|
||||
*/
|
||||
@AutoService(ResultRenderer.class)
|
||||
public class RenderAsCssJQuery implements ResultRenderer, ActionListener {
|
||||
|
||||
private static final String CSSJQUEY_TESTER_COMMAND = "cssjquery_tester"; // $NON-NLS-1$
|
||||
|
|
|
@ -23,6 +23,9 @@ import org.apache.jmeter.util.JMeterUtils;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
@AutoService(ResultRenderer.class)
|
||||
public class RenderAsDocument extends SamplerResultTab implements ResultRenderer {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(RenderAsDocument.class);
|
||||
|
|
|
@ -33,6 +33,9 @@ import org.apache.jmeter.util.JMeterUtils;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
@AutoService(ResultRenderer.class)
|
||||
public class RenderAsHTML extends SamplerResultTab implements ResultRenderer {
|
||||
private static final Logger log = LoggerFactory.getLogger(RenderAsHTML.class);
|
||||
|
||||
|
|
|
@ -21,6 +21,9 @@ import org.apache.jmeter.samplers.SampleResult;
|
|||
import org.apache.jmeter.util.JMeterUtils;
|
||||
import org.jsoup.Jsoup;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
@AutoService(ResultRenderer.class)
|
||||
public class RenderAsHTMLFormatted extends SamplerResultTab implements ResultRenderer {
|
||||
|
||||
/** {@inheritDoc} */
|
||||
|
|
|
@ -20,6 +20,9 @@ package org.apache.jmeter.visualizers;
|
|||
import org.apache.jmeter.samplers.SampleResult;
|
||||
import org.apache.jmeter.util.JMeterUtils;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
@AutoService(ResultRenderer.class)
|
||||
public class RenderAsHTMLWithEmbedded extends RenderAsHTML
|
||||
implements ResultRenderer {
|
||||
|
||||
|
|
|
@ -29,6 +29,9 @@ import net.minidev.json.JSONStyle;
|
|||
import net.minidev.json.parser.JSONParser;
|
||||
import net.minidev.json.parser.ParseException;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
@AutoService(ResultRenderer.class)
|
||||
public class RenderAsJSON extends SamplerResultTab implements ResultRenderer {
|
||||
private static final String TAB_SEPARATOR = " "; //$NON-NLS-1$
|
||||
|
||||
|
|
|
@ -50,9 +50,12 @@ import org.apache.oro.text.regex.PatternMatcherInput;
|
|||
import org.apache.oro.text.regex.Perl5Compiler;
|
||||
import org.apache.oro.text.regex.Perl5Matcher;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Implement ResultsRender for Regexp tester
|
||||
*/
|
||||
@AutoService(ResultRenderer.class)
|
||||
public class RenderAsRegexp implements ResultRenderer, ActionListener {
|
||||
|
||||
private static final String REGEXP_TESTER_COMMAND = "regexp_tester"; // $NON-NLS-1$
|
||||
|
|
|
@ -20,6 +20,9 @@ package org.apache.jmeter.visualizers;
|
|||
import org.apache.jmeter.samplers.SampleResult;
|
||||
import org.apache.jmeter.util.JMeterUtils;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
@AutoService(ResultRenderer.class)
|
||||
public class RenderAsText extends SamplerResultTab implements ResultRenderer {
|
||||
|
||||
/** {@inheritDoc} */
|
||||
|
|
|
@ -53,6 +53,9 @@ import org.w3c.dom.NodeList;
|
|||
import org.w3c.tidy.Tidy;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
@AutoService(ResultRenderer.class)
|
||||
public class RenderAsXML extends SamplerResultTab
|
||||
implements ResultRenderer {
|
||||
|
||||
|
|
|
@ -59,10 +59,13 @@ import org.slf4j.LoggerFactory;
|
|||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
|
||||
/**
|
||||
* Implement ResultsRender for XPath tester
|
||||
*/
|
||||
@AutoService(ResultRenderer.class)
|
||||
public class RenderAsXPath implements ResultRenderer, ActionListener {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(RenderAsXPath.class);
|
||||
|
|
|
@ -48,9 +48,12 @@ import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Implement ResultsRender for XPath tester
|
||||
*/
|
||||
@AutoService(ResultRenderer.class)
|
||||
public class RenderAsXPath2 implements ResultRenderer, ActionListener {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(RenderAsXPath2.class);
|
||||
|
|
|
@ -27,6 +27,8 @@ import javax.swing.JPanel;
|
|||
import javax.swing.JProgressBar;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
import org.apache.jmeter.samplers.SampleResult;
|
||||
import org.apache.jmeter.util.JMeterUtils;
|
||||
|
||||
|
@ -43,6 +45,7 @@ import javafx.scene.web.WebView;
|
|||
* {@link ResultRenderer} implementation that uses JAVAFX WebEngine to render as browser do
|
||||
* @since 3.2
|
||||
*/
|
||||
@AutoService(ResultRenderer.class)
|
||||
public class RenderInBrowser extends SamplerResultTab implements ResultRenderer {
|
||||
|
||||
private JFXPanel jfxPanel;
|
||||
|
|
|
@ -18,11 +18,9 @@
|
|||
package org.apache.jmeter.visualizers;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTabbedPane;
|
||||
|
@ -30,6 +28,7 @@ import javax.swing.SwingConstants;
|
|||
|
||||
import org.apache.jmeter.samplers.SampleResult;
|
||||
import org.apache.jmeter.util.JMeterUtils;
|
||||
import org.apache.jorphan.reflect.LogAndIgnoreServiceLoadExceptionHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -52,37 +51,23 @@ public class RequestPanel {
|
|||
*/
|
||||
public RequestPanel() {
|
||||
listRequestView = new ArrayDeque<>();
|
||||
List<String> classesToAdd = Collections.<String> emptyList();
|
||||
try {
|
||||
classesToAdd = JMeterUtils.findClassesThatExtend(RequestView.class);
|
||||
} catch (IOException e1) {
|
||||
// ignored
|
||||
}
|
||||
String rawTab = JMeterUtils.getResString(RequestViewRaw.KEY_LABEL); // $NON-NLS-1$
|
||||
Object rawObject = null;
|
||||
for (String clazz : classesToAdd) {
|
||||
try {
|
||||
// Instantiate requestview classes
|
||||
final RequestView requestView = Class.forName(clazz)
|
||||
.asSubclass(RequestView.class)
|
||||
.getDeclaredConstructor().newInstance();
|
||||
if (rawTab.equals(requestView.getLabel())) {
|
||||
rawObject = requestView; // use later
|
||||
} else {
|
||||
listRequestView.add(requestView);
|
||||
}
|
||||
}
|
||||
catch (NoClassDefFoundError e) {
|
||||
log.error("Exception registering implementation: [{}] of interface: [{}], a dependency used by the plugin class is missing",
|
||||
clazz, RequestView.class, e);
|
||||
} catch (Exception e) {
|
||||
log.error("Exception registering implementation: [{}] of interface: [{}], a jar is probably missing",
|
||||
clazz, RequestView.class, e);
|
||||
RequestView rawObject = null;
|
||||
for (RequestView requestView : JMeterUtils.loadServicesAndScanJars(
|
||||
RequestView.class,
|
||||
ServiceLoader.load(RequestView.class),
|
||||
Thread.currentThread().getContextClassLoader(),
|
||||
new LogAndIgnoreServiceLoadExceptionHandler(log)
|
||||
)) {
|
||||
if (rawTab.equals(requestView.getLabel())) {
|
||||
rawObject = requestView; // use later
|
||||
} else {
|
||||
listRequestView.add(requestView);
|
||||
}
|
||||
}
|
||||
// place raw tab in first position (first tab)
|
||||
if (rawObject != null) {
|
||||
listRequestView.addFirst((RequestView) rawObject);
|
||||
listRequestView.addFirst(rawObject);
|
||||
}
|
||||
|
||||
// Prepare the Request tabbed pane
|
||||
|
|
|
@ -19,12 +19,15 @@ package org.apache.jmeter.visualizers;
|
|||
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import org.apache.jorphan.reflect.JMeterService;
|
||||
|
||||
/**
|
||||
* Interface for request panel in View Results Tree
|
||||
* All classes which implements this interface is display
|
||||
* on bottom tab in request panel
|
||||
*
|
||||
*/
|
||||
@JMeterService
|
||||
public interface RequestView {
|
||||
|
||||
/**
|
||||
|
|
|
@ -30,10 +30,13 @@ import org.apache.jmeter.samplers.SampleResult;
|
|||
import org.apache.jmeter.util.JMeterUtils;
|
||||
import org.apache.jorphan.gui.GuiUtils;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* (historical) Panel to view request data
|
||||
*
|
||||
*/
|
||||
@AutoService(RequestView.class)
|
||||
public class RequestViewRaw implements RequestView {
|
||||
|
||||
// Used by Request Panel
|
||||
|
|
|
@ -22,11 +22,13 @@ import java.awt.Color;
|
|||
import javax.swing.JTabbedPane;
|
||||
|
||||
import org.apache.jmeter.samplers.SampleResult;
|
||||
import org.apache.jorphan.reflect.JMeterService;
|
||||
|
||||
|
||||
/**
|
||||
* Interface to results render
|
||||
*/
|
||||
@JMeterService
|
||||
public interface ResultRenderer {
|
||||
|
||||
void clearData();
|
||||
|
|
|
@ -25,7 +25,6 @@ import java.awt.event.ActionEvent;
|
|||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -36,6 +35,7 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -73,6 +73,7 @@ import org.apache.jmeter.samplers.SampleResult;
|
|||
import org.apache.jmeter.util.JMeterUtils;
|
||||
import org.apache.jmeter.visualizers.gui.AbstractVisualizer;
|
||||
import org.apache.jorphan.gui.JMeterUIDefaults;
|
||||
import org.apache.jorphan.reflect.LogAndIgnoreServiceLoadExceptionHandler;
|
||||
import org.apache.jorphan.util.StringWrap;
|
||||
import org.apiguardian.api.API;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -454,38 +455,24 @@ implements ActionListener, TreeSelectionListener, Clearable, ItemListener {
|
|||
selectRenderPanel.addActionListener(this);
|
||||
|
||||
// if no results render in jmeter.properties, load Standard (default)
|
||||
List<String> classesToAdd = Collections.<String>emptyList();
|
||||
try {
|
||||
classesToAdd = JMeterUtils.findClassesThatExtend(ResultRenderer.class);
|
||||
} catch (IOException e1) {
|
||||
// ignored
|
||||
}
|
||||
String defaultRenderer = expandToClassname(".RenderAsText"); // $NON-NLS-1$
|
||||
if (VIEWERS_ORDER.length() > 0) {
|
||||
defaultRenderer = expandToClassname(VIEWERS_ORDER.split(",", 2)[0]);
|
||||
}
|
||||
Object defaultObject = null;
|
||||
Map<String, ResultRenderer> map = new HashMap<>(classesToAdd.size());
|
||||
for (String clazz : classesToAdd) {
|
||||
try {
|
||||
// Instantiate render classes
|
||||
final ResultRenderer renderer = Class.forName(clazz)
|
||||
.asSubclass(ResultRenderer.class)
|
||||
.getDeclaredConstructor().newInstance();
|
||||
if (defaultRenderer.equals(clazz)) {
|
||||
defaultObject=renderer;
|
||||
}
|
||||
renderer.setBackgroundColor(getBackground());
|
||||
map.put(renderer.getClass().getName(), renderer);
|
||||
} catch (NoClassDefFoundError e) { // NOSONAR See bug 60583
|
||||
if (e.getMessage() != null && e.getMessage().contains("javafx")) {
|
||||
log.info("Add JavaFX to your Java installation if you want to use renderer: {}", clazz);
|
||||
} else {
|
||||
log.warn("Error loading result renderer: {}", clazz, e);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("Error loading result renderer: {}", clazz, e);
|
||||
ResultRenderer defaultObject = null;
|
||||
Map<String, ResultRenderer> map = new HashMap<>();
|
||||
for (ResultRenderer renderer : JMeterUtils.loadServicesAndScanJars(
|
||||
ResultRenderer.class,
|
||||
ServiceLoader.load(ResultRenderer.class),
|
||||
Thread.currentThread().getContextClassLoader(),
|
||||
new LogAndIgnoreServiceLoadExceptionHandler(log)
|
||||
)) {
|
||||
// Instantiate render classes
|
||||
if (defaultRenderer.equals(renderer.getClass().getName())) {
|
||||
defaultObject = renderer;
|
||||
}
|
||||
renderer.setBackgroundColor(getBackground());
|
||||
map.put(renderer.getClass().getName(), renderer);
|
||||
}
|
||||
if (VIEWERS_ORDER.length() > 0) {
|
||||
Arrays.stream(VIEWERS_ORDER.split(","))
|
||||
|
|
|
@ -24,6 +24,8 @@ import org.apache.jmeter.config.Arguments;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* An abstract implementation of the BackendListenerClient interface. This
|
||||
* implementation provides default implementations of most of the methods in the
|
||||
|
@ -49,6 +51,7 @@ import org.slf4j.LoggerFactory;
|
|||
* @see BackendListener#sampleOccurred(org.apache.jmeter.samplers.SampleEvent)
|
||||
* @since 2.13
|
||||
*/
|
||||
@AutoService(BackendListenerClient.class)
|
||||
public abstract class AbstractBackendListenerClient implements BackendListenerClient {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(AbstractBackendListenerClient.class);
|
||||
|
|
|
@ -21,6 +21,7 @@ import java.util.List;
|
|||
|
||||
import org.apache.jmeter.config.Arguments;
|
||||
import org.apache.jmeter.samplers.SampleResult;
|
||||
import org.apache.jorphan.reflect.JMeterService;
|
||||
|
||||
/**
|
||||
* This interface defines the interactions between the {@link BackendListener}
|
||||
|
@ -63,6 +64,7 @@ import org.apache.jmeter.samplers.SampleResult;
|
|||
*
|
||||
* @since 2.13
|
||||
*/
|
||||
@JMeterService
|
||||
public interface BackendListenerClient {
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,11 +20,10 @@ package org.apache.jmeter.visualizers.backend;
|
|||
import java.awt.BorderLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.ComboBoxModel;
|
||||
|
@ -33,7 +32,6 @@ import javax.swing.JLabel;
|
|||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.jmeter.config.Argument;
|
||||
import org.apache.jmeter.config.Arguments;
|
||||
|
@ -45,7 +43,7 @@ import org.apache.jmeter.testelement.TestElement;
|
|||
import org.apache.jmeter.testelement.property.JMeterProperty;
|
||||
import org.apache.jmeter.util.JMeterUtils;
|
||||
import org.apache.jmeter.visualizers.gui.AbstractListenerGui;
|
||||
import org.apache.jorphan.reflect.ClassFinder;
|
||||
import org.apache.jorphan.reflect.LogAndIgnoreServiceLoadExceptionHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -77,7 +75,6 @@ public class BackendListenerGui extends AbstractListenerGui implements ActionLis
|
|||
/** The current className of the Backend listener **/
|
||||
private String className;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new BackendListenerGui as a standalone component.
|
||||
*/
|
||||
|
@ -117,25 +114,18 @@ public class BackendListenerGui extends AbstractListenerGui implements ActionLis
|
|||
* @return a panel containing the relevant components
|
||||
*/
|
||||
private JPanel createClassnamePanel() {
|
||||
List<String> possibleClasses = new ArrayList<>();
|
||||
|
||||
try {
|
||||
// Find all the classes which implement the BackendListenerClient
|
||||
// interface.
|
||||
possibleClasses = ClassFinder.findClassesThatExtend(JMeterUtils.getSearchPaths(),
|
||||
new Class[] { BackendListenerClient.class });
|
||||
|
||||
// Remove the BackendListener class from the list since it only
|
||||
// implements the interface for error conditions.
|
||||
|
||||
possibleClasses.remove(BackendListener.class.getName() + "$ErrorBackendListenerClient");
|
||||
} catch (Exception e) {
|
||||
log.debug("Exception getting interfaces.", e);
|
||||
}
|
||||
|
||||
JLabel label = new JLabel(JMeterUtils.getResString("backend_listener_classname")); // $NON-NLS-1$
|
||||
|
||||
classnameCombo = new JComboBox<>(possibleClasses.toArray(ArrayUtils.EMPTY_STRING_ARRAY));
|
||||
String[] listenerClasses = JMeterUtils.loadServicesAndScanJars(
|
||||
BackendListenerClient.class,
|
||||
ServiceLoader.load(BackendListenerClient.class),
|
||||
Thread.currentThread().getContextClassLoader(),
|
||||
new LogAndIgnoreServiceLoadExceptionHandler(log)
|
||||
).stream()
|
||||
.map(s -> s.getClass().getName())
|
||||
.sorted()
|
||||
.toArray(String[]::new);
|
||||
classnameCombo = new JComboBox<>(listenerClasses);
|
||||
classnameCombo.addActionListener(this);
|
||||
classnameCombo.setEditable(false);
|
||||
label.setLabelFor(classnameCombo);
|
||||
|
|
|
@ -37,17 +37,21 @@ import org.apache.jmeter.config.Arguments;
|
|||
import org.apache.jmeter.samplers.SampleResult;
|
||||
import org.apache.jmeter.util.JMeterUtils;
|
||||
import org.apache.jmeter.visualizers.backend.AbstractBackendListenerClient;
|
||||
import org.apache.jmeter.visualizers.backend.BackendListenerClient;
|
||||
import org.apache.jmeter.visualizers.backend.BackendListenerContext;
|
||||
import org.apache.jmeter.visualizers.backend.SamplerMetric;
|
||||
import org.apache.jmeter.visualizers.backend.UserMetric;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Graphite based Listener using Pickle Protocol
|
||||
* @see <a href="http://graphite.readthedocs.org/en/latest/overview.html">Graphite Overview</a>
|
||||
* @since 2.13
|
||||
*/
|
||||
@AutoService(BackendListenerClient.class)
|
||||
public class GraphiteBackendListenerClient extends AbstractBackendListenerClient implements Runnable {
|
||||
|
||||
//+ Argument names
|
||||
|
|
|
@ -29,6 +29,8 @@ import org.apache.jmeter.visualizers.backend.BackendListenerContext;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Implementation of {@link BackendListenerClient} to write the response times
|
||||
* of every sample to InfluxDB. If more "raw" information is required in InfluxDB
|
||||
|
@ -38,6 +40,7 @@ import org.slf4j.LoggerFactory;
|
|||
*
|
||||
* @since 5.3
|
||||
*/
|
||||
@AutoService(BackendListenerClient.class)
|
||||
public class InfluxDBRawBackendListenerClient implements BackendListenerClient {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(InfluxDBRawBackendListenerClient.class);
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.apache.jmeter.config.Arguments;
|
|||
import org.apache.jmeter.samplers.SampleResult;
|
||||
import org.apache.jmeter.util.JMeterUtils;
|
||||
import org.apache.jmeter.visualizers.backend.AbstractBackendListenerClient;
|
||||
import org.apache.jmeter.visualizers.backend.BackendListenerClient;
|
||||
import org.apache.jmeter.visualizers.backend.BackendListenerContext;
|
||||
import org.apache.jmeter.visualizers.backend.ErrorMetric;
|
||||
import org.apache.jmeter.visualizers.backend.SamplerMetric;
|
||||
|
@ -43,12 +44,15 @@ import org.apache.jmeter.visualizers.backend.UserMetric;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Implementation of {@link AbstractBackendListenerClient} to write to InfluxDB
|
||||
* using a custom schema; since JMeter 5.2, this also support the InfluxDB v2.
|
||||
*
|
||||
* @since 3.2
|
||||
*/
|
||||
@AutoService(BackendListenerClient.class)
|
||||
public class InfluxdbBackendListenerClient extends AbstractBackendListenerClient implements Runnable {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(InfluxdbBackendListenerClient.class);
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.util.Collection;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
import org.apache.jmeter.functions.Function;
|
||||
import org.apache.jmeter.functions.InvalidVariableException;
|
||||
|
@ -30,7 +31,7 @@ import org.apache.jmeter.samplers.Sampler;
|
|||
import org.apache.jmeter.threads.JMeterContext;
|
||||
import org.apache.jmeter.threads.JMeterContextService;
|
||||
import org.apache.jmeter.util.JMeterUtils;
|
||||
import org.apache.jorphan.reflect.ClassFinder;
|
||||
import org.apache.jorphan.reflect.LogAndIgnoreServiceLoadExceptionHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -69,15 +70,15 @@ public class CompoundVariable implements Function {
|
|||
log.info("Note: Function class names must not contain the string: '{}'", notContain);
|
||||
}
|
||||
|
||||
List<String> classes = ClassFinder.findClassesThatExtend(JMeterUtils.getSearchPaths(),
|
||||
new Class[] { Function.class }, true, contain, notContain);
|
||||
for (String clazzName : classes) {
|
||||
Function tempFunc = Class.forName(clazzName)
|
||||
.asSubclass(Function.class)
|
||||
.getDeclaredConstructor().newInstance();
|
||||
String referenceKey = tempFunc.getReferenceKey();
|
||||
for (Function function : JMeterUtils.loadServicesAndScanJars(
|
||||
Function.class,
|
||||
ServiceLoader.load(Function.class),
|
||||
Thread.currentThread().getContextClassLoader(),
|
||||
new LogAndIgnoreServiceLoadExceptionHandler(log)
|
||||
)) {
|
||||
String referenceKey = function.getReferenceKey();
|
||||
if (referenceKey.length() > 0) { // ignore self
|
||||
functions.put(referenceKey, tempFunc.getClass());
|
||||
functions.put(referenceKey, function.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,18 +23,20 @@ import java.util.List;
|
|||
import org.apache.jmeter.engine.util.CompoundVariable;
|
||||
import org.apache.jmeter.samplers.SampleResult;
|
||||
import org.apache.jmeter.samplers.Sampler;
|
||||
import org.apache.jorphan.reflect.JMeterService;
|
||||
|
||||
/**
|
||||
* Methods that a function must implement
|
||||
*/
|
||||
@JMeterService
|
||||
public interface Function {
|
||||
/**
|
||||
* Given the previous SampleResult and the current Sampler, return a string
|
||||
* to use as a replacement value for the function call. Assume
|
||||
* "setParameter" was previously called.
|
||||
*
|
||||
* This method must be threadsafe - multiple threads will be using the same
|
||||
* object.
|
||||
* <p>This method must be thread-safe - multiple threads will be using the same
|
||||
* object.</p>
|
||||
* @param previousResult The previous {@link SampleResult}
|
||||
* @param currentSampler The current {@link Sampler}
|
||||
* @return The replacement value, which was generated by the function
|
||||
|
|
|
@ -30,9 +30,16 @@ import org.apache.jmeter.exceptions.IllegalUserActionException;
|
|||
import org.apache.jmeter.gui.action.AbstractAction;
|
||||
import org.apache.jmeter.gui.action.ActionNames;
|
||||
import org.apache.jmeter.gui.action.ActionRouter;
|
||||
import org.apache.jmeter.gui.action.Command;
|
||||
import org.apache.jmeter.gui.plugin.MenuCreator;
|
||||
import org.apache.jmeter.util.JMeterUtils;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
@AutoService({
|
||||
Command.class,
|
||||
MenuCreator.class
|
||||
})
|
||||
public class HtmlReportAction extends AbstractAction implements MenuCreator {
|
||||
private static final Set<String> commands = new HashSet<>();
|
||||
private HtmlReportUI htmlReportPanel;
|
||||
|
|
|
@ -42,10 +42,13 @@ import org.apache.jmeter.gui.GuiPackage;
|
|||
import org.apache.jmeter.gui.util.EscapeDialog;
|
||||
import org.apache.jmeter.util.JMeterUtils;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* About Command. It may be extended in the future to add a list of installed
|
||||
* protocols, config options, etc.
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class AboutCommand extends AbstractAction {
|
||||
private static final Set<String> commandSet;
|
||||
|
||||
|
|
|
@ -309,6 +309,7 @@ public final class ActionRouter implements ActionListener {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private static List<String> findClassesThatExtend(String className, String excluding, String[] searchPath) throws IOException, ClassNotFoundException {
|
||||
|
||||
return ClassFinder.findClassesThatExtend(
|
||||
|
|
|
@ -28,9 +28,12 @@ import org.apache.jmeter.testelement.TestElement;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Implements the Add Parent menu command
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class AddParent extends AbstractAction {
|
||||
private static final Logger log = LoggerFactory.getLogger(AddParent.class);
|
||||
|
||||
|
|
|
@ -33,10 +33,13 @@ import org.apache.jmeter.util.JMeterUtils;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Add ThinkTime (TestAction + UniformRandomTimer)
|
||||
* @since 3.2
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class AddThinkTimeBetweenEachStep extends AbstractAction {
|
||||
private static final Logger log = LoggerFactory.getLogger(AddThinkTimeBetweenEachStep.class);
|
||||
|
||||
|
|
|
@ -32,6 +32,9 @@ import org.apache.jmeter.util.JMeterUtils;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
@AutoService(Command.class)
|
||||
public class AddToTree extends AbstractAction {
|
||||
private static final Logger log = LoggerFactory.getLogger(AddToTree.class);
|
||||
|
||||
|
|
|
@ -32,10 +32,13 @@ import org.apache.jmeter.util.JMeterUtils;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Allows to apply naming convention on nodes
|
||||
* @since 3.2
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class ApplyNamingConvention extends AbstractAction {
|
||||
private static final Logger log = LoggerFactory.getLogger(ApplyNamingConvention.class);
|
||||
|
||||
|
|
|
@ -28,9 +28,12 @@ import org.apache.jorphan.util.JMeterError;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Change language
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class ChangeLanguage extends AbstractActionWithNoRunningTest {
|
||||
private static final Set<String> commands = new HashSet<>();
|
||||
|
||||
|
|
|
@ -38,9 +38,12 @@ import org.apache.jmeter.util.JMeterUtils;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Allows to change Controller implementation
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class ChangeParent extends AbstractAction {
|
||||
private static final Logger log = LoggerFactory.getLogger(ChangeParent.class);
|
||||
|
||||
|
|
|
@ -33,10 +33,13 @@ import org.apache.jorphan.collections.ListedHashTree;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Check if the TestPlan has been changed since it was last saved
|
||||
*
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class CheckDirty extends AbstractAction implements HashTreeTraverser, ActionListener {
|
||||
private static final Logger log = LoggerFactory.getLogger(CheckDirty.class);
|
||||
|
||||
|
|
|
@ -28,12 +28,15 @@ import org.apache.jmeter.samplers.Clearable;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Handles the following actions:
|
||||
* - Clear (Data)
|
||||
* - Clear All (Data)
|
||||
* - Reset (Clear GUI)
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class Clear extends AbstractAction {
|
||||
private static final Logger log = LoggerFactory.getLogger(Clear.class);
|
||||
|
||||
|
|
|
@ -29,11 +29,14 @@ import org.apache.jmeter.gui.util.FocusRequester;
|
|||
import org.apache.jmeter.services.FileServer;
|
||||
import org.apache.jmeter.util.JMeterUtils;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* This command clears the existing test plan, allowing the creation of a New
|
||||
* test plan.
|
||||
*
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class Close extends AbstractActionWithNoRunningTest {
|
||||
|
||||
private static final Set<String> commands = new HashSet<>();
|
||||
|
|
|
@ -25,10 +25,13 @@ import javax.swing.JTree;
|
|||
|
||||
import org.apache.jmeter.gui.GuiPackage;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Processes the Collapse All and Expand All options.
|
||||
*
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class CollapseExpand extends AbstractAction {
|
||||
|
||||
private static final Set<String> commands = new HashSet<>();
|
||||
|
|
|
@ -30,9 +30,12 @@ import org.apache.jmeter.gui.GuiPackage;
|
|||
import org.apache.jmeter.gui.tree.JMeterTreeListener;
|
||||
import org.apache.jmeter.gui.tree.JMeterTreeNode;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Processes the collapse and expand of a tree branch
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class CollapseExpandTreeBranch extends AbstractAction {
|
||||
private static final Set<String> commands = new HashSet<>();
|
||||
|
||||
|
|
|
@ -38,10 +38,16 @@ import org.apache.jorphan.collections.HashTreeTraverser;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Compile JSR223 Test Element that use Compilable script language
|
||||
* @since 5.1
|
||||
*/
|
||||
@AutoService({
|
||||
Command.class,
|
||||
MenuCreator.class
|
||||
})
|
||||
public class CompileJSR223TestElements extends AbstractAction implements MenuCreator {
|
||||
private static final Logger log = LoggerFactory.getLogger(CompileJSR223TestElements.class);
|
||||
|
||||
|
|
|
@ -37,9 +37,12 @@ import org.apache.jmeter.util.JMeterUtils;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Implements the Copy menu command
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class Copy extends AbstractAction {
|
||||
private static final Logger log = LoggerFactory.getLogger(Copy.class);
|
||||
|
||||
|
|
|
@ -23,6 +23,9 @@ import java.util.Set;
|
|||
|
||||
import org.apache.jmeter.functions.gui.FunctionHelper;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
@AutoService(Command.class)
|
||||
public class CreateFunctionDialog extends AbstractAction {
|
||||
|
||||
private static final Set<String> commands;
|
||||
|
|
|
@ -24,9 +24,12 @@ import java.util.Set;
|
|||
import org.apache.jmeter.gui.GuiPackage;
|
||||
import org.apache.jmeter.gui.tree.JMeterTreeNode;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Implements the Cut menu item command
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class Cut extends AbstractAction {
|
||||
private static final Set<String> commands = new HashSet<>();
|
||||
|
||||
|
|
|
@ -26,9 +26,12 @@ import org.apache.jmeter.gui.tree.JMeterTreeListener;
|
|||
import org.apache.jmeter.gui.tree.JMeterTreeModel;
|
||||
import org.apache.jmeter.gui.tree.JMeterTreeNode;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Implements the Duplicate menu command
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class Duplicate extends AbstractAction {
|
||||
|
||||
private static final HashSet<String> commands = new HashSet<>();
|
||||
|
|
|
@ -25,9 +25,12 @@ import org.apache.jmeter.gui.GuiPackage;
|
|||
import org.apache.jmeter.gui.JMeterGUIComponent;
|
||||
import org.apache.jorphan.gui.ui.TextComponentUI;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Implements the Edit menu item.
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class EditCommand extends AbstractAction {
|
||||
private static final Set<String> commands = new HashSet<>();
|
||||
|
||||
|
|
|
@ -26,9 +26,12 @@ import org.apache.jmeter.gui.tree.JMeterTreeNode;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Implements the Enable menu item.
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class EnableComponent extends AbstractAction {
|
||||
private static final Logger log = LoggerFactory.getLogger(EnableComponent.class);
|
||||
|
||||
|
|
|
@ -26,6 +26,9 @@ import javax.swing.JOptionPane;
|
|||
import org.apache.jmeter.gui.GuiPackage;
|
||||
import org.apache.jmeter.util.JMeterUtils;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
@AutoService(Command.class)
|
||||
public class ExitCommand extends AbstractActionWithNoRunningTest {
|
||||
|
||||
private static final Set<String> commands = new HashSet<>();
|
||||
|
|
|
@ -35,9 +35,12 @@ import org.apache.jorphan.gui.ComponentUtil;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Implements the Help menu item.
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class Help extends AbstractAction {
|
||||
private static final Logger log = LoggerFactory.getLogger(Help.class);
|
||||
private static final boolean USE_LOCAL_HELP =
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.apache.jorphan.collections.HashTree;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.thoughtworks.xstream.converters.ConversionException;
|
||||
import com.thoughtworks.xstream.io.StreamException;
|
||||
|
||||
|
@ -49,6 +50,7 @@ import com.thoughtworks.xstream.io.StreamException;
|
|||
* Handles the Open (load a new file) and Merge commands.
|
||||
*
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class Load extends AbstractActionWithNoRunningTest {
|
||||
private static final Logger log = LoggerFactory.getLogger(Load.class);
|
||||
|
||||
|
|
|
@ -34,10 +34,13 @@ import java.util.stream.IntStream;
|
|||
import javax.swing.JComponent;
|
||||
import javax.swing.JMenuItem;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Handles the loading of recent files, and also the content and
|
||||
* visibility of menu items for loading the recent files
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class LoadRecentProject extends Load {
|
||||
/** Prefix for the user preference key */
|
||||
private static final String USER_PREFS_KEY = "recent_file_"; //$NON-NLS-1$
|
||||
|
|
|
@ -29,10 +29,13 @@ import org.apiguardian.api.API;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Implements log level setting menu item.
|
||||
* @since 3.2
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class LogLevelCommand extends AbstractAction {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(LogLevelCommand.class);
|
||||
|
|
|
@ -26,10 +26,13 @@ import javax.swing.UIManager;
|
|||
|
||||
import org.apache.jmeter.gui.GuiPackage;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Hide / unhide LoggerPanel.
|
||||
*
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class LoggerPanelEnableDisable extends AbstractAction {
|
||||
|
||||
private static final Set<String> commands = new HashSet<>();
|
||||
|
|
|
@ -40,10 +40,12 @@ import org.apache.jorphan.gui.JFactory;
|
|||
import com.github.weisj.darklaf.LafManager;
|
||||
import com.github.weisj.darklaf.theme.DarculaTheme;
|
||||
import com.github.weisj.darklaf.theme.Theme;
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Implements the Look and Feel menu item.
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class LookAndFeelCommand extends AbstractAction {
|
||||
private static final String JMETER_LAF = "jmeter.laf"; // $NON-NLS-1$
|
||||
|
||||
|
|
|
@ -33,10 +33,13 @@ import org.apache.jmeter.gui.util.MenuFactory;
|
|||
import org.apache.jmeter.testelement.TestElement;
|
||||
import org.apache.jmeter.testelement.TestPlan;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Move a node up/down/left/right
|
||||
*
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class Move extends AbstractAction {
|
||||
private static final Set<String> commands = new HashSet<>();
|
||||
|
||||
|
|
|
@ -29,6 +29,9 @@ import javax.swing.JOptionPane;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
@AutoService(Command.class)
|
||||
public class OpenLinkAction extends AbstractAction {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(OpenLinkAction.class);
|
||||
|
|
|
@ -33,9 +33,12 @@ import org.apache.jmeter.util.JMeterUtils;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Places a copied JMeterTreeNode under the selected node.
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class Paste extends AbstractAction {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(Paste.class);
|
||||
|
|
|
@ -33,6 +33,9 @@ import org.apache.jmeter.threads.RemoteThreadsListenerTestElement;
|
|||
import org.apache.jmeter.util.JMeterUtils;
|
||||
import org.apache.jorphan.collections.HashTree;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
@AutoService(Command.class)
|
||||
public class RemoteStart extends AbstractAction {
|
||||
|
||||
private static final String LOCAL_HOST = "127.0.0.1"; // NOSONAR $NON-NLS-1$
|
||||
|
|
|
@ -29,9 +29,12 @@ import org.apache.jmeter.gui.tree.JMeterTreeNode;
|
|||
import org.apache.jmeter.testelement.TestElement;
|
||||
import org.apache.jmeter.util.JMeterUtils;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Implements the Remove menu item.
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class Remove extends AbstractAction {
|
||||
|
||||
private static final Set<String> commands = new HashSet<>();
|
||||
|
|
|
@ -26,9 +26,12 @@ import org.apache.jmeter.gui.GuiPackage;
|
|||
import org.apache.jmeter.gui.Searchable;
|
||||
import org.apache.jmeter.gui.tree.JMeterTreeNode;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Reset Search
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class ResetSearchCommand extends AbstractAction {
|
||||
|
||||
private static final Set<String> commands = new HashSet<>();
|
||||
|
|
|
@ -39,11 +39,17 @@ import org.apache.jmeter.util.JMeterUtils;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Restart JMeter
|
||||
* Based on https://dzone.com/articles/programmatically-restart-java
|
||||
* @since 5.0
|
||||
*/
|
||||
@AutoService({
|
||||
Command.class,
|
||||
MenuCreator.class
|
||||
})
|
||||
public class Restart extends AbstractActionWithNoRunningTest implements MenuCreator {
|
||||
private static final Logger log = LoggerFactory.getLogger(Restart.class);
|
||||
|
||||
|
|
|
@ -27,10 +27,13 @@ import javax.swing.JOptionPane;
|
|||
import org.apache.jmeter.gui.GuiPackage;
|
||||
import org.apache.jmeter.util.JMeterUtils;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Handles the Revert Project command.
|
||||
*
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class RevertProject extends AbstractActionWithNoRunningTest {
|
||||
private static final Set<String> commands = new HashSet<>();
|
||||
|
||||
|
|
|
@ -32,6 +32,8 @@ import org.apache.jmeter.gui.GuiPackage;
|
|||
import org.apache.jmeter.util.JMeterUtils;
|
||||
import org.apache.jmeter.util.SSLManager;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
//
|
||||
/**
|
||||
* SSL Manager Command. The SSL Manager provides a mechanism to change your
|
||||
|
@ -52,6 +54,7 @@ import org.apache.jmeter.util.SSLManager;
|
|||
* already defined via the property.
|
||||
*
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class SSLManagerCommand extends AbstractAction {
|
||||
private static final Set<String> commandSet;
|
||||
static {
|
||||
|
|
|
@ -56,12 +56,15 @@ import org.apache.jorphan.collections.ListedHashTree;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Save the current test plan; implements:
|
||||
* Save
|
||||
* Save TestPlan As
|
||||
* Save (Selection) As
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class Save extends AbstractAction {
|
||||
private static final Logger log = LoggerFactory.getLogger(Save.class);
|
||||
|
||||
|
|
|
@ -23,11 +23,14 @@ import java.util.Set;
|
|||
|
||||
import org.apache.jmeter.gui.GuiPackage;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Save Before Run Action To save test plan before GUI execution
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class SaveBeforeRun extends AbstractAction {
|
||||
private static final Set<String> commands = new HashSet<>();
|
||||
|
||||
|
|
|
@ -34,6 +34,8 @@ import org.apache.jmeter.save.SaveGraphicsService;
|
|||
import org.apache.jmeter.util.JMeterUtils;
|
||||
import org.apache.jmeter.visualizers.Printable;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* SaveGraphics action is meant to be a generic reusable Action. The class will
|
||||
* use GUIPackage to get the current gui. Once it does, it checks to see if the
|
||||
|
@ -42,6 +44,7 @@ import org.apache.jmeter.visualizers.Printable;
|
|||
* file if no extension is provided. If either .png or .tif is in the filename,
|
||||
* it will call SaveGraphicsService to save in the format.
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class SaveGraphics extends AbstractAction {
|
||||
|
||||
private static final Set<String> commands = new HashSet<>();
|
||||
|
|
|
@ -47,10 +47,16 @@ import org.apache.jorphan.collections.HashTree;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Schematic view of Test Plan
|
||||
* @since 5.1
|
||||
*/
|
||||
@AutoService({
|
||||
Command.class,
|
||||
MenuCreator.class
|
||||
})
|
||||
public class SchematicView extends AbstractAction implements MenuCreator {
|
||||
private static final Logger log = LoggerFactory.getLogger(SchematicView.class);
|
||||
private static final String DEFAULT_XSL_FILE =
|
||||
|
|
|
@ -23,10 +23,13 @@ import java.util.Set;
|
|||
|
||||
import javax.swing.JFrame;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Search nodes for a text
|
||||
* TODO Enhance search dialog to select kind of nodes ....
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class SearchTreeCommand extends AbstractAction {
|
||||
|
||||
private static final Set<String> commands = new HashSet<>();
|
||||
|
|
|
@ -45,6 +45,8 @@ import org.apache.jorphan.collections.ListedHashTree;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Set of Actions to:
|
||||
* <ul>
|
||||
|
@ -57,6 +59,7 @@ import org.slf4j.LoggerFactory;
|
|||
* <li>Validate a set of Thread Groups with/without sleeping on the timers depending on jmeter properties</li>
|
||||
* </ul>
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class Start extends AbstractAction {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(Start.class);
|
||||
|
|
|
@ -26,10 +26,13 @@ import java.util.Set;
|
|||
import org.apache.jmeter.gui.GuiPackage;
|
||||
import org.apache.jmeter.gui.Stoppable;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Stops stopables (Proxy, Mirror)
|
||||
* @since 2.5.1
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class StopStoppables extends AbstractAction implements ActionListener {
|
||||
private static final Set<String> commands = new HashSet<>();
|
||||
|
||||
|
|
|
@ -21,10 +21,13 @@ import java.awt.event.ActionEvent;
|
|||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Open Templates
|
||||
* @since 2.10
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class TemplatesCommand extends AbstractActionWithNoRunningTest {
|
||||
|
||||
private static final Set<String> commands = new HashSet<>();
|
||||
|
|
|
@ -26,10 +26,13 @@ import org.apache.jmeter.exceptions.IllegalUserActionException;
|
|||
import org.apache.jmeter.gui.GuiPackage;
|
||||
import org.apache.jorphan.collections.HashTree;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Menu command to serve Undo/Redo
|
||||
* @since 2.12
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class UndoCommand extends AbstractAction {
|
||||
|
||||
private static final Set<String> commands = new HashSet<>();
|
||||
|
|
|
@ -35,6 +35,8 @@ import org.apache.logging.log4j.core.config.Configurator;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
*
|
||||
* Debug class to show details of the currently selected object
|
||||
|
@ -43,6 +45,7 @@ import org.slf4j.LoggerFactory;
|
|||
* Also enables/disables debug for the test element.
|
||||
*
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class What extends AbstractAction {
|
||||
private static final Logger log = LoggerFactory.getLogger(What.class);
|
||||
|
||||
|
|
|
@ -24,10 +24,13 @@ import java.util.Set;
|
|||
import org.apache.jmeter.util.JMeterUtils;
|
||||
import org.apache.jorphan.gui.JMeterUIDefaults;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* Zoom IN/OUT
|
||||
* @since 3.2
|
||||
*/
|
||||
@AutoService(Command.class)
|
||||
public class ZoomInOut extends AbstractAction {
|
||||
private static final Set<String> commands = new HashSet<>();
|
||||
|
||||
|
|
|
@ -21,9 +21,12 @@ import javax.swing.JMenu;
|
|||
import javax.swing.JMenuItem;
|
||||
import javax.swing.MenuElement;
|
||||
|
||||
import org.apache.jorphan.reflect.JMeterService;
|
||||
|
||||
/**
|
||||
* @since 2.10
|
||||
*/
|
||||
@JMeterService
|
||||
public interface MenuCreator {
|
||||
enum MENU_LOCATION {
|
||||
FILE,
|
||||
|
|
|
@ -19,14 +19,13 @@ package org.apache.jmeter.gui.util;
|
|||
|
||||
import java.awt.Component;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.JCheckBoxMenuItem;
|
||||
|
@ -54,7 +53,7 @@ import org.apache.jmeter.util.JMeterUtils;
|
|||
import org.apache.jmeter.util.LocaleChangeEvent;
|
||||
import org.apache.jmeter.util.LocaleChangeListener;
|
||||
import org.apache.jmeter.util.SSLManager;
|
||||
import org.apache.jorphan.reflect.ClassFinder;
|
||||
import org.apache.jorphan.reflect.LogAndIgnoreServiceLoadExceptionHandler;
|
||||
import org.apache.jorphan.util.JOrphanUtils;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -92,7 +91,13 @@ public class JMeterMenuBar extends JMenuBar implements LocaleChangeListener {
|
|||
private JMenu remoteExit;
|
||||
private final Collection<JMenuItem> remoteEngineExit;
|
||||
private JMenu searchMenu;
|
||||
private List<MenuCreator> menuCreators;
|
||||
private final Collection<MenuCreator> menuCreators =
|
||||
JMeterUtils.loadServicesAndScanJars(
|
||||
MenuCreator.class,
|
||||
ServiceLoader.load(MenuCreator.class),
|
||||
Thread.currentThread().getContextClassLoader(),
|
||||
new LogAndIgnoreServiceLoadExceptionHandler(log)
|
||||
);
|
||||
|
||||
public static final String SYSTEM_LAF = "System"; // $NON-NLS-1$
|
||||
public static final String CROSS_PLATFORM_LAF = "CrossPlatform"; // $NON-NLS-1$
|
||||
|
@ -192,9 +197,6 @@ public class JMeterMenuBar extends JMenuBar implements LocaleChangeListener {
|
|||
* should be defined in a file somewhere, but that is for later.
|
||||
*/
|
||||
public void createMenuBar() {
|
||||
|
||||
this.menuCreators = findMenuCreators();
|
||||
|
||||
makeFileMenu();
|
||||
makeEditMenu();
|
||||
makeRunMenu();
|
||||
|
@ -217,35 +219,6 @@ public class JMeterMenuBar extends JMenuBar implements LocaleChangeListener {
|
|||
this.add(helpMenu);
|
||||
}
|
||||
|
||||
private static List<MenuCreator> findMenuCreators() {
|
||||
List<MenuCreator> creators = new ArrayList<>();
|
||||
try {
|
||||
List<String> listClasses = ClassFinder.findClassesThatExtend(
|
||||
JMeterUtils.getSearchPaths(),
|
||||
new Class[] {MenuCreator.class });
|
||||
for (String strClassName : listClasses) {
|
||||
try {
|
||||
log.debug("Loading menu creator class: {}", strClassName);
|
||||
Class<?> commandClass = Class.forName(strClassName);
|
||||
if (!Modifier.isAbstract(commandClass.getModifiers())) {
|
||||
log.debug("Instantiating: {}", commandClass);
|
||||
MenuCreator creator = (MenuCreator) commandClass.getDeclaredConstructor().newInstance();
|
||||
creators.add(creator);
|
||||
}
|
||||
} catch (NoClassDefFoundError e) {
|
||||
log.error("Exception registering implementation: [{}] of interface: [{}], a dependency used by the plugin class is missing",
|
||||
strClassName, MenuCreator.class, e);
|
||||
} catch (Exception e) {
|
||||
log.error("Exception registering implementation: [{}] of interface: [{}], a jar is probably missing",
|
||||
strClassName, MenuCreator.class, e);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("Exception finding implementations of {}", MenuCreator.class, e);
|
||||
}
|
||||
return creators;
|
||||
}
|
||||
|
||||
private void makeHelpMenu() {
|
||||
helpMenu = makeMenuRes("help",'H'); //$NON-NLS-1$
|
||||
|
||||
|
@ -590,7 +563,7 @@ public class JMeterMenuBar extends JMenuBar implements LocaleChangeListener {
|
|||
* @param menuCreators
|
||||
* @param location
|
||||
*/
|
||||
private static void addPluginsMenuItems(JMenu menu, List<MenuCreator> menuCreators, MENU_LOCATION location) {
|
||||
private static void addPluginsMenuItems(JMenu menu, Collection<MenuCreator> menuCreators, MENU_LOCATION location) {
|
||||
for (MenuCreator menuCreator : menuCreators) {
|
||||
JMenuItem[] menuItems = menuCreator.getMenuItemsAtLocation(location);
|
||||
if (menuItems.length != 0) {
|
||||
|
|
|
@ -124,6 +124,8 @@ public final class MenuFactory {
|
|||
private static void initializeMenus(
|
||||
Map<String, List<MenuInfo>> menus, Set<String> elementsToSkip) {
|
||||
try {
|
||||
// TODO: migrate to ServiceLoader or something else
|
||||
@SuppressWarnings("deprecation")
|
||||
List<String> guiClasses = ClassFinder
|
||||
.findClassesThatExtend(
|
||||
JMeterUtils.getSearchPaths(),
|
||||
|
|
|
@ -17,10 +17,13 @@
|
|||
|
||||
package org.apache.jmeter.threads;
|
||||
|
||||
import org.apache.jorphan.reflect.JMeterService;
|
||||
|
||||
/**
|
||||
* Interface notified when number of active threads changes
|
||||
* @since 2.10
|
||||
*/
|
||||
@JMeterService
|
||||
public interface RemoteThreadsLifeCycleListener {
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,18 +17,16 @@
|
|||
|
||||
package org.apache.jmeter.threads;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.rmi.RemoteException;
|
||||
import java.rmi.server.UnicastRemoteObject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
import org.apache.jmeter.gui.GuiPackage;
|
||||
import org.apache.jmeter.rmi.RmiUtils;
|
||||
import org.apache.jmeter.testelement.ThreadListener;
|
||||
import org.apache.jmeter.util.JMeterUtils;
|
||||
import org.apache.jorphan.reflect.ClassFinder;
|
||||
import org.apache.jorphan.reflect.LogAndIgnoreServiceLoadExceptionHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -39,7 +37,14 @@ import org.slf4j.LoggerFactory;
|
|||
public class RemoteThreadsListenerImpl extends UnicastRemoteObject implements
|
||||
RemoteThreadsListener, ThreadListener {
|
||||
private static final Logger log = LoggerFactory.getLogger(RemoteThreadsListenerImpl.class);
|
||||
private final List<RemoteThreadsLifeCycleListener> listeners = new ArrayList<>();
|
||||
|
||||
private final Collection<RemoteThreadsLifeCycleListener> listeners =
|
||||
JMeterUtils.loadServicesAndScanJars(
|
||||
RemoteThreadsLifeCycleListener.class,
|
||||
ServiceLoader.load(RemoteThreadsLifeCycleListener.class),
|
||||
Thread.currentThread().getContextClassLoader(),
|
||||
new LogAndIgnoreServiceLoadExceptionHandler(log)
|
||||
);
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -56,27 +61,6 @@ public class RemoteThreadsListenerImpl extends UnicastRemoteObject implements
|
|||
*/
|
||||
public RemoteThreadsListenerImpl() throws RemoteException {
|
||||
super(DEFAULT_LOCAL_PORT, RmiUtils.createClientSocketFactory(), RmiUtils.createServerSocketFactory());
|
||||
try {
|
||||
List<String> listClasses = ClassFinder.findClassesThatExtend(
|
||||
JMeterUtils.getSearchPaths(),
|
||||
new Class[] {RemoteThreadsLifeCycleListener.class });
|
||||
for (String strClassName : listClasses) {
|
||||
try {
|
||||
log.debug("Loading class: {}", strClassName);
|
||||
Class<?> commandClass = Class.forName(strClassName);
|
||||
if (!Modifier.isAbstract(commandClass.getModifiers())) {
|
||||
log.debug("Instantiating: {}", commandClass);
|
||||
RemoteThreadsLifeCycleListener listener = (RemoteThreadsLifeCycleListener) commandClass.getDeclaredConstructor().newInstance();
|
||||
listeners.add(listener);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Exception registering {} with implementation: {}", RemoteThreadsLifeCycleListener.class,
|
||||
strClassName, e);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("Exception finding implementations of {}", RemoteThreadsLifeCycleListener.class, e);
|
||||
}
|
||||
}
|
||||
|
||||
private static int addOffset(int port, int offset) {
|
||||
|
|
|
@ -27,19 +27,25 @@ import java.io.InputStream;
|
|||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URL;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.Properties;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -59,6 +65,7 @@ import org.apache.jmeter.threads.JMeterContextService;
|
|||
import org.apache.jorphan.gui.JFactory;
|
||||
import org.apache.jorphan.gui.JMeterUIDefaults;
|
||||
import org.apache.jorphan.reflect.ClassFinder;
|
||||
import org.apache.jorphan.reflect.ServiceLoadExceptionHandler;
|
||||
import org.apache.jorphan.test.UnitTestManager;
|
||||
import org.apache.jorphan.util.JMeterError;
|
||||
import org.apache.jorphan.util.JOrphanUtils;
|
||||
|
@ -316,6 +323,71 @@ public class JMeterUtils implements UnitTestManager {
|
|||
getProperties(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads services implementing a given interface and scans JMeter search path for the implementations.
|
||||
* This is a transition replacement for {@link ClassFinder}, and JMeter would migrate to {@link ServiceLoader}-only
|
||||
* lookup in the future.
|
||||
* <p>Note: it is not always safe to cache the result as {@code search_paths} property might change over time</p>
|
||||
*
|
||||
* @param service interface that services should extend.
|
||||
* @param serviceLoader ServiceLoader to fetch services.
|
||||
* @param classLoader classLoader to use when searching for classes on the search path.
|
||||
* @param exceptionHandler exception handler to use for services that fail to load.
|
||||
* @return collection of services that load successfully
|
||||
* @param <S> type of service (class or interface)
|
||||
*/
|
||||
@API(status = API.Status.DEPRECATED, since = "5.6")
|
||||
public static <S> Collection<S> loadServicesAndScanJars(
|
||||
@SuppressWarnings("BoundedWildcard") Class<S> service,
|
||||
ServiceLoader<S> serviceLoader,
|
||||
ClassLoader classLoader,
|
||||
ServiceLoadExceptionHandler<? super S> exceptionHandler
|
||||
) {
|
||||
Collection<S> services = ClassFinder.loadServices(service, serviceLoader, exceptionHandler);
|
||||
|
||||
List<String> classesFromJars;
|
||||
try (ClassFinder.Closeable ignored = ClassFinder.skipJarsWithJmeterSkipClassScanningAttribute()) {
|
||||
classesFromJars = findClassesThatExtend(service);
|
||||
} catch (IOException e) {
|
||||
log.warn("Unable to lookup {} with ClassFinder.findClassesThatExtend. " +
|
||||
"Will use only results from ServiceLoader ({} items found)", service, services.size(), e);
|
||||
return services;
|
||||
}
|
||||
|
||||
if (classesFromJars.isEmpty()) {
|
||||
return services;
|
||||
}
|
||||
|
||||
Set<String> loadedClasses = new HashSet<>((int) (services.size() / 0.75f) + 1);
|
||||
for (S s : services) {
|
||||
loadedClasses.add(s.getClass().getName());
|
||||
}
|
||||
|
||||
List<S> result = new ArrayList<>(services.size() + classesFromJars.size());
|
||||
result.addAll(services);
|
||||
for (String className : classesFromJars) {
|
||||
// Ignore classes that we loaded previously (e.g. with a ServiceLoader)
|
||||
if (!loadedClasses.add(className)) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
Class<? extends S> klass = Class.forName(className, false, classLoader)
|
||||
.asSubclass(service);
|
||||
if (!Modifier.isAbstract(klass.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
result.add(klass.getDeclaredConstructor().newInstance());
|
||||
} catch (Throwable e) {
|
||||
if (e instanceof InvocationTargetException) {
|
||||
//noinspection AssignmentToCatchBlockParameter
|
||||
e = e.getCause();
|
||||
}
|
||||
exceptionHandler.handle(service, className, e);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for
|
||||
* {@link ClassFinder#findClassesThatExtend(String[], Class[], boolean)}
|
||||
|
@ -325,7 +397,10 @@ public class JMeterUtils implements UnitTestManager {
|
|||
* @param superClass - single class to search for
|
||||
* @return List of Strings containing discovered class names.
|
||||
* @throws IOException when the used {@link ClassFinder} throws one while searching for the class
|
||||
* @deprecated use {@link #loadServicesAndScanJars(Class, ServiceLoader, ClassLoader, ServiceLoadExceptionHandler)} instead
|
||||
*/
|
||||
@API(status = API.Status.DEPRECATED, since = "5.6")
|
||||
@Deprecated
|
||||
public static List<String> findClassesThatExtend(Class<?> superClass)
|
||||
throws IOException {
|
||||
return ClassFinder.findClassesThatExtend(getSearchPaths(), new Class[]{superClass}, false);
|
||||
|
|
|
@ -321,8 +321,10 @@ public final class AllTests {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private static List<String> findJMeterJUnitTests(String searchPathString) throws IOException {
|
||||
final String[] searchPaths = JOrphanUtils.split(searchPathString, ",");
|
||||
// TODO: do we really need class searching here?
|
||||
return ClassFinder.findClasses(searchPaths, new JunitTestFilter());
|
||||
}
|
||||
|
||||
|
|
|
@ -440,6 +440,7 @@ public class JMeterTest extends JMeterTestCaseJUnit implements Describable {
|
|||
|
||||
public static Collection<Object> getObjects(Class<?> extendsClass) throws Throwable {
|
||||
String exName = extendsClass.getName();
|
||||
@SuppressWarnings("deprecation")
|
||||
Iterator<String> classes = ClassFinder
|
||||
.findClassesThatExtend(JMeterUtils.getSearchPaths(), new Class[] { extendsClass }).iterator();
|
||||
List<Object> objects = new ArrayList<>();
|
||||
|
|
|
@ -171,6 +171,7 @@ public final class PackageTest extends JMeterTestCaseJUnit implements Describabl
|
|||
public static Test suite() throws Exception {
|
||||
TestSuite suite = new TestSuite("Bean Resource Test Suite");
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
List<String> testBeanClassNames = ClassFinder.findClassesThatExtend(JMeterUtils.getSearchPaths(), new Class[] { TestBean.class });
|
||||
|
||||
boolean errorDetected = false;
|
||||
|
|
|
@ -48,6 +48,7 @@ public class TestClassFinder {
|
|||
|
||||
@Test
|
||||
public void testFindClassesThatExtendStringArrayClassOfQArray() throws IOException {
|
||||
@SuppressWarnings("deprecation")
|
||||
List<String> findClassesThatExtend = ClassFinder.findClassesThatExtend(
|
||||
libDirs,
|
||||
new Class<?>[] { Exception.class });
|
||||
|
@ -56,6 +57,7 @@ public class TestClassFinder {
|
|||
|
||||
@Test
|
||||
public void testFindClassesThatExtendStringArrayClassOfQArrayTrue() throws Exception {
|
||||
@SuppressWarnings("deprecation")
|
||||
List<String> findClassesThatExtend = ClassFinder.findClassesThatExtend(
|
||||
libDirs,
|
||||
new Class<?>[] { Object.class },
|
||||
|
@ -66,6 +68,7 @@ public class TestClassFinder {
|
|||
|
||||
@Test
|
||||
public void testFindClassesThatExtendStringArrayClassOfQArrayFalse() throws Exception {
|
||||
@SuppressWarnings("deprecation")
|
||||
List<String> findClassesThatExtend = ClassFinder.findClassesThatExtend(
|
||||
libDirs,
|
||||
new Class<?>[] { Exception.class },
|
||||
|
@ -77,6 +80,7 @@ public class TestClassFinder {
|
|||
|
||||
@Test
|
||||
public void testFindClassesThatExtendStringArrayClassOfQArrayBooleanStringString() throws Exception {
|
||||
@SuppressWarnings("deprecation")
|
||||
List<String> findClassesThatExtend = ClassFinder.findClassesThatExtend(
|
||||
libDirs,
|
||||
new Class<?>[] { Exception.class },
|
||||
|
@ -90,6 +94,7 @@ public class TestClassFinder {
|
|||
|
||||
@Test
|
||||
public void testFindClassesThatExtendStringArrayClassOfQArrayBooleanStringStringTrue() throws Exception {
|
||||
@SuppressWarnings("deprecation")
|
||||
List<String> annotatedClasses = ClassFinder.findClassesThatExtend(
|
||||
libDirs,
|
||||
new Class<?>[] { java.beans.Transient.class },
|
||||
|
@ -102,7 +107,7 @@ public class TestClassFinder {
|
|||
|
||||
@Test
|
||||
public void testFindAnnotatedClasses() throws Exception {
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({"deprecation", "unchecked"})
|
||||
List<String> annotatedClasses = ClassFinder.findAnnotatedClasses(
|
||||
libDirs,
|
||||
new Class[] { java.beans.Transient.class});
|
||||
|
@ -111,7 +116,7 @@ public class TestClassFinder {
|
|||
|
||||
@Test
|
||||
public void testFindAnnotatedInnerClasses() throws Exception {
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({"deprecation", "unchecked"})
|
||||
List<String> annotatedClasses = ClassFinder.findAnnotatedClasses(libDirs,
|
||||
new Class[] { java.lang.Deprecated.class}, true);
|
||||
Assert.assertTrue(annotatedClasses.stream().anyMatch(s->s.contains("$")));
|
||||
|
@ -119,12 +124,16 @@ public class TestClassFinder {
|
|||
|
||||
@Test
|
||||
public void testFindClasses() throws IOException {
|
||||
Assert.assertFalse(ClassFinder.findClasses(libDirs, className -> true).isEmpty());
|
||||
@SuppressWarnings("deprecation")
|
||||
List<String> classes = ClassFinder.findClasses(libDirs, className -> true);
|
||||
Assert.assertFalse(classes.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindClassesNone() throws IOException {
|
||||
Assert.assertTrue(ClassFinder.findClasses(libDirs, className -> false).isEmpty());
|
||||
@SuppressWarnings("deprecation")
|
||||
List<String> classes = ClassFinder.findClasses(libDirs, className -> false);
|
||||
Assert.assertTrue(classes.isEmpty());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,10 +32,13 @@ import org.apache.jmeter.util.JMeterUtils;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
/**
|
||||
* A function which understands BeanShell
|
||||
* @since 1.X
|
||||
*/
|
||||
@AutoService(Function.class)
|
||||
public class BeanShell extends AbstractFunction {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(BeanShell.class);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue