| /* |
| * 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. |
| */ |
| |
| package org.apache.jmeter.protocol.http.gui.action; |
| |
| import java.awt.BorderLayout; |
| import java.awt.Color; |
| import java.awt.Container; |
| import java.awt.Dimension; |
| import java.awt.event.ActionEvent; |
| import java.awt.event.ActionListener; |
| import java.awt.event.KeyEvent; |
| import java.io.File; |
| import java.io.IOException; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.nio.charset.StandardCharsets; |
| import java.text.MessageFormat; |
| import java.time.LocalDateTime; |
| import java.time.format.DateTimeFormatter; |
| import java.util.ArrayList; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import javax.swing.JButton; |
| import javax.swing.JCheckBox; |
| import javax.swing.JLabel; |
| import javax.swing.JMenu; |
| import javax.swing.JMenuItem; |
| import javax.swing.JPanel; |
| import javax.swing.MenuElement; |
| import javax.swing.SwingUtilities; |
| import javax.swing.UIManager; |
| import javax.swing.tree.TreePath; |
| |
| import org.apache.commons.io.FileUtils; |
| import org.apache.commons.lang3.StringUtils; |
| import org.apache.commons.lang3.tuple.Pair; |
| import org.apache.jmeter.config.Arguments; |
| import org.apache.jmeter.config.KeystoreConfig; |
| import org.apache.jmeter.control.Controller; |
| import org.apache.jmeter.control.LoopController; |
| import org.apache.jmeter.control.ReplaceableController; |
| import org.apache.jmeter.control.gui.TestPlanGui; |
| import org.apache.jmeter.exceptions.IllegalUserActionException; |
| import org.apache.jmeter.gui.GuiPackage; |
| 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.gui.tree.JMeterTreeModel; |
| import org.apache.jmeter.gui.tree.JMeterTreeNode; |
| import org.apache.jmeter.gui.util.EscapeDialog; |
| import org.apache.jmeter.gui.util.FilePanel; |
| import org.apache.jmeter.gui.util.JSyntaxTextArea; |
| import org.apache.jmeter.gui.util.JTextScrollPane; |
| import org.apache.jmeter.protocol.http.control.AuthManager; |
| import org.apache.jmeter.protocol.http.control.Authorization; |
| import org.apache.jmeter.protocol.http.control.Cookie; |
| import org.apache.jmeter.protocol.http.control.CookieManager; |
| import org.apache.jmeter.protocol.http.control.DNSCacheManager; |
| import org.apache.jmeter.protocol.http.control.Header; |
| import org.apache.jmeter.protocol.http.control.HeaderManager; |
| import org.apache.jmeter.protocol.http.control.StaticHost; |
| import org.apache.jmeter.protocol.http.control.gui.HttpTestSampleGui; |
| import org.apache.jmeter.protocol.http.curl.ArgumentHolder; |
| import org.apache.jmeter.protocol.http.curl.BasicCurlParser; |
| import org.apache.jmeter.protocol.http.curl.BasicCurlParser.Request; |
| import org.apache.jmeter.protocol.http.curl.FileArgumentHolder; |
| import org.apache.jmeter.protocol.http.gui.AuthPanel; |
| import org.apache.jmeter.protocol.http.gui.CookiePanel; |
| import org.apache.jmeter.protocol.http.gui.DNSCachePanel; |
| import org.apache.jmeter.protocol.http.gui.HeaderPanel; |
| import org.apache.jmeter.protocol.http.sampler.HTTPSamplerFactory; |
| import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy; |
| import org.apache.jmeter.protocol.http.util.HTTPFileArg; |
| import org.apache.jmeter.reporters.ResultCollector; |
| import org.apache.jmeter.services.FileServer; |
| import org.apache.jmeter.testbeans.gui.TestBeanGUI; |
| import org.apache.jmeter.testelement.TestElement; |
| import org.apache.jmeter.testelement.TestPlan; |
| import org.apache.jmeter.threads.AbstractThreadGroup; |
| import org.apache.jmeter.threads.AbstractThreadGroupSchema; |
| import org.apache.jmeter.threads.ThreadGroup; |
| import org.apache.jmeter.threads.gui.ThreadGroupGui; |
| import org.apache.jmeter.util.JMeterUtils; |
| import org.apache.jmeter.visualizers.ViewResultsFullVisualizer; |
| import org.apache.jorphan.collections.HashTree; |
| import org.apache.jorphan.gui.ComponentUtil; |
| import org.apache.jorphan.gui.JMeterUIDefaults; |
| import org.apache.tika.Tika; |
| import org.apache.tika.config.TikaConfig; |
| import org.apache.tika.exception.TikaException; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| import org.xml.sax.SAXException; |
| |
| import com.google.auto.service.AutoService; |
| |
| /** |
| * Opens a popup where user can enter a cURL command line and create a test plan |
| * from it |
| * |
| * @since 5.1 |
| */ |
| @AutoService({ |
| Command.class, |
| MenuCreator.class |
| }) |
| public class ParseCurlCommandAction extends AbstractAction implements MenuCreator, ActionListener { // NOSONAR |
| private static final Logger LOGGER = LoggerFactory.getLogger(ParseCurlCommandAction.class); |
| private static final String ACCEPT_ENCODING = "Accept-Encoding"; |
| private static final Set<String> commands = new HashSet<>(); |
| public static final String IMPORT_CURL = "import_curl"; |
| private static final String CREATE_REQUEST = "CREATE_REQUEST"; |
| private static final String CERT = "cert"; |
| /** A panel allowing results to be saved. */ |
| private FilePanel filePanel = null; |
| static { |
| commands.add(IMPORT_CURL); |
| } |
| private JSyntaxTextArea cURLCommandTA; |
| private JLabel statusText; |
| private JCheckBox uploadCookiesCheckBox; |
| private final Tika tika = createTika(); |
| |
| private Tika createTika() { |
| try { |
| return new Tika(new TikaConfig(this.getClass().getClassLoader() |
| .getResourceAsStream("org/apache/jmeter/protocol/http/gui/action/tika-config.xml"))); |
| } catch (TikaException | IOException | SAXException e) { |
| return new Tika(); |
| } |
| } |
| |
| public ParseCurlCommandAction() { |
| super(); |
| } |
| |
| @Override |
| public void doAction(ActionEvent e) { |
| showInputDialog(e); |
| } |
| |
| /** |
| * Show popup where user can import cURL command |
| * |
| * @param event {@link ActionEvent} |
| */ |
| private void showInputDialog(ActionEvent event) { |
| EscapeDialog messageDialog = new EscapeDialog( |
| getParentFrame(event), |
| JMeterUtils.getResString("curl_import"), //$NON-NLS-1$ |
| false); |
| Container contentPane = messageDialog.getContentPane(); |
| contentPane.setLayout(new BorderLayout()); |
| statusText = new JLabel("",JLabel.CENTER); |
| statusText.setForeground(UIManager.getColor(JMeterUIDefaults.LABEL_ERROR_FOREGROUND)); |
| contentPane.add(statusText, BorderLayout.NORTH); |
| cURLCommandTA = JSyntaxTextArea.getInstance(20, 80, false); |
| cURLCommandTA.setCaretPosition(0); |
| contentPane.add(JTextScrollPane.getInstance(cURLCommandTA), BorderLayout.CENTER); |
| JPanel optionPanel = new JPanel(new BorderLayout(3, 1)); |
| filePanel = new FilePanel(JMeterUtils.getResString("curl_import_from_file")); // $NON-NLS-1$ |
| optionPanel.add(filePanel,BorderLayout.CENTER); |
| uploadCookiesCheckBox = new JCheckBox(JMeterUtils.getResString("curl_add_cookie_header_to_cookiemanager"), false); |
| optionPanel.add(uploadCookiesCheckBox,BorderLayout.NORTH); |
| JButton button = new JButton(JMeterUtils.getResString("curl_create_request")); |
| button.setActionCommand(CREATE_REQUEST); |
| button.addActionListener(this); |
| button.setPreferredSize(new Dimension(50, 50)); |
| optionPanel.add(button,BorderLayout.SOUTH); |
| contentPane.add(optionPanel, BorderLayout.SOUTH); |
| messageDialog.pack(); |
| ComponentUtil.centerComponentInComponent(GuiPackage.getInstance().getMainFrame(), messageDialog); |
| SwingUtilities.invokeLater(() -> messageDialog.setVisible(true)); |
| } |
| |
| /** |
| * Finds the first enabled node of a given type in the tree. |
| * |
| * @param type class of the node to be found |
| * @return the first node of the given type in the test component tree, or |
| * <code>null</code> if none was found. |
| */ |
| private static JMeterTreeNode findFirstNodeOfType(Class<?> type) { |
| JMeterTreeModel treeModel = GuiPackage.getInstance().getTreeModel(); |
| return treeModel.getNodesOfType(type).stream().filter(JMeterTreeNode::isEnabled).findFirst().orElse(null); |
| } |
| |
| private static DNSCacheManager findNodeOfTypeDnsCacheManagerByType(boolean isCustom) { |
| JMeterTreeModel treeModel = GuiPackage.getInstance().getTreeModel(); |
| List<JMeterTreeNode> res = treeModel.getNodesOfType(DNSCacheManager.class); |
| for (JMeterTreeNode jm : res) { |
| DNSCacheManager dnsCacheManager = (DNSCacheManager) jm.getTestElement(); |
| if (dnsCacheManager.isCustomResolver() == isCustom) { |
| return dnsCacheManager; |
| } |
| } |
| return null; |
| } |
| |
| private void createTestPlan(ActionEvent e, Request request, String statusText) |
| throws MalformedURLException, IllegalUserActionException { |
| ActionRouter.getInstance().doActionNow(new ActionEvent(e.getSource(), e.getID(), ActionNames.CLOSE)); |
| GuiPackage guiPackage = GuiPackage.getInstance(); |
| guiPackage.clearTestPlan(); |
| FileServer.getFileServer().setScriptName(null); |
| ThreadGroup threadGroup = new ThreadGroup(); |
| threadGroup.setProperty(TestElement.GUI_CLASS, ThreadGroupGui.class.getName()); |
| threadGroup.setProperty(TestElement.NAME, "Thread Group"); |
| threadGroup.set(AbstractThreadGroupSchema.INSTANCE.getNumThreads(), "${__P(threads,10)}"); |
| threadGroup.setProperty(ThreadGroup.RAMP_TIME,"${__P(rampup,30)}"); |
| threadGroup.setScheduler(true); |
| threadGroup.setProperty(ThreadGroup.DURATION,"${__P(duration,3600)}"); |
| threadGroup.setDelay(5); |
| LoopController loopCtrl = new LoopController(); |
| loopCtrl.setLoops("${__P(iterations,-1)}"); |
| loopCtrl.setContinueForever(false); |
| threadGroup.setSamplerController(loopCtrl); |
| TestPlan testPlan = new TestPlan(); |
| testPlan.setProperty(TestElement.NAME, "Test Plan"); |
| testPlan.setProperty(TestElement.GUI_CLASS, TestPlanGui.class.getName()); |
| testPlan.setComment("You can run me using: jmeter -Jthreads=<Number of threads> -Jrampup=<rampup in seconds> -Jduration=<duration in seconds> " |
| + "-Jiterations=<Number of iterations, -1 means infinite> -e -o <report output folder>"); |
| HashTree tree = new HashTree(); |
| HashTree testPlanHT = tree.add(testPlan); |
| HashTree threadGroupHT = testPlanHT.add(threadGroup); |
| createHttpRequest(request, threadGroupHT,statusText); |
| if (!request.getAuthorization().getUser().isEmpty()) { |
| AuthManager authManager = new AuthManager(); |
| createAuthManager(request, authManager); |
| threadGroupHT.add(authManager); |
| } |
| if (!request.getDnsServers().isEmpty()) { |
| DNSCacheManager dnsCacheManager = new DNSCacheManager(); |
| createDnsServer(request, dnsCacheManager); |
| threadGroupHT.add(dnsCacheManager); |
| } |
| if (request.getDnsResolver()!=null) { |
| DNSCacheManager dnsCacheManager = new DNSCacheManager(); |
| createDnsResolver(request, dnsCacheManager); |
| threadGroupHT.add(dnsCacheManager); |
| } |
| CookieManager cookieManager = new CookieManager(); |
| createCookieManager(cookieManager, request); |
| threadGroupHT.add(cookieManager); |
| ResultCollector resultCollector = new ResultCollector(); |
| resultCollector.setProperty(TestElement.NAME, "View Results Tree"); |
| resultCollector.setProperty(TestElement.GUI_CLASS, ViewResultsFullVisualizer.class.getName()); |
| tree.add(tree.getArray()[0], resultCollector); |
| final HashTree newTree = guiPackage.addSubTree(tree); |
| guiPackage.updateCurrentGui(); |
| guiPackage.getMainFrame().getTree() |
| .setSelectionPath(new TreePath(((JMeterTreeNode) newTree.getArray()[0]).getPath())); |
| final HashTree subTree = guiPackage.getCurrentSubTree(); |
| // Send different event whether we are merging a test plan into another test |
| // plan, |
| // or loading a testplan from scratch |
| ActionEvent actionEvent = new ActionEvent(subTree.get(subTree.getArray()[subTree.size() - 1]), e.getID(), |
| ActionNames.SUB_TREE_LOADED); |
| ActionRouter.getInstance().actionPerformed(actionEvent); |
| ActionRouter.getInstance().doActionNow(new ActionEvent(e.getSource(), e.getID(), ActionNames.EXPAND_ALL)); |
| } |
| |
| private HTTPSamplerProxy createHttpRequest(Request request, HashTree parentHT, String commentText) throws MalformedURLException { |
| HTTPSamplerProxy httpSampler = createSampler(request,commentText); |
| HashTree samplerHT = parentHT.add(httpSampler); |
| samplerHT.add(httpSampler.getHeaderManager()); |
| if (CERT.equals(request.getCaCert())) { |
| samplerHT.add(httpSampler.getKeystoreConfig()); |
| } |
| return httpSampler; |
| } |
| |
| /** |
| * @param request {@link Request} |
| * @param commentText |
| * @return {@link HTTPSamplerProxy} |
| * @throws MalformedURLException |
| */ |
| private HTTPSamplerProxy createSampler(Request request, String commentText) throws MalformedURLException { |
| HTTPSamplerProxy httpSampler = (HTTPSamplerProxy) HTTPSamplerFactory |
| .newInstance(HTTPSamplerFactory.DEFAULT_CLASSNAME); |
| httpSampler.setProperty(TestElement.GUI_CLASS, HttpTestSampleGui.class.getName()); |
| httpSampler.setProperty(TestElement.NAME, "HTTP Request"); |
| if (!commentText.isEmpty()) { |
| httpSampler.setProperty(TestElement.COMMENTS,commentText); // NOSONAR |
| } else { |
| httpSampler.setProperty(TestElement.COMMENTS, getDefaultComment()); |
| } // NOSONAR |
| URL url = new URL(request.getUrl()); |
| httpSampler.setProtocol(url.getProtocol()); |
| if (url.getPort() != -1) { |
| httpSampler.setPort(url.getPort()); |
| } |
| String path = url.getPath(); |
| if (StringUtils.isNotEmpty(url.getQuery())) { |
| path += "?" + url.getQuery(); |
| } |
| // setMethod must be before setPath as setPath uses method to determine if parameters should be parsed or not |
| httpSampler.setMethod(request.getMethod()); |
| httpSampler.setPath(path); |
| httpSampler.setDomain(url.getHost()); |
| httpSampler.setUseKeepAlive(request.isKeepAlive()); |
| httpSampler.setFollowRedirects(true); |
| HeaderManager headerManager = createHeaderManager(request); |
| httpSampler.addTestElement(headerManager); |
| configureTimeout(request, httpSampler); |
| createProxyServer(request, httpSampler); |
| if (request.getInterfaceName() != null) { |
| httpSampler.setIpSourceType(1); |
| httpSampler.setIpSource(request.getInterfaceName()); |
| } |
| if (!"GET".equals(request.getMethod()) && request.getPostData() != null) { |
| Arguments arguments = new Arguments(); |
| httpSampler.setArguments(arguments); |
| httpSampler.addNonEncodedArgument("", request.getPostData(), ""); |
| } |
| if (!request.getFormData().isEmpty() || !request.getFormStringData().isEmpty()) { |
| setFormData(request, httpSampler); |
| httpSampler.setDoMultipart(true); |
| } |
| if (CERT.equals(request.getCaCert())) { |
| KeystoreConfig keystoreConfig = createKeystoreConfiguration(); |
| httpSampler.addTestElement(keystoreConfig); |
| } |
| return httpSampler; |
| } |
| |
| private static void configureTimeout(Request request, HTTPSamplerProxy httpSampler) { |
| double connectTimeout = request.getConnectTimeout(); |
| double maxTime = request.getMaxTime(); |
| if (connectTimeout >= 0) { |
| httpSampler.setConnectTimeout(String.valueOf((int) request.getConnectTimeout())); |
| if (maxTime >= 0) { |
| maxTime = maxTime - connectTimeout; |
| } |
| } |
| if (maxTime >= 0) { |
| httpSampler.setResponseTimeout(String.valueOf((int) maxTime)); |
| } |
| } |
| |
| /** |
| * |
| * @param request {@link Request} |
| * @return {@link HeaderManager} element |
| */ |
| private static HeaderManager createHeaderManager(Request request) { |
| HeaderManager headerManager = new HeaderManager(); |
| headerManager.setProperty(TestElement.GUI_CLASS, HeaderPanel.class.getName()); |
| headerManager.setProperty(TestElement.NAME, "HTTP HeaderManager"); |
| headerManager.setProperty(TestElement.COMMENTS, getDefaultComment()); |
| boolean hasAcceptEncoding = false; |
| for (Pair<String, String> header : request.getHeaders()) { |
| String key = header.getKey(); |
| hasAcceptEncoding = hasAcceptEncoding || key.equalsIgnoreCase(ACCEPT_ENCODING); |
| headerManager.getHeaders().addItem(new Header(key, header.getValue())); |
| } |
| if (!hasAcceptEncoding && request.isCompressed()) { |
| headerManager.getHeaders().addItem(new Header(ACCEPT_ENCODING, "gzip, deflate")); |
| } |
| return headerManager; |
| } |
| |
| /** |
| * Configures a given Cookie Manager. |
| * |
| * @param cookieManager the manager to configure |
| * @param request to copy information about cookies from |
| */ |
| private void createCookieManager(CookieManager cookieManager, Request request) { |
| cookieManager.setProperty(TestElement.GUI_CLASS, CookiePanel.class.getName()); |
| cookieManager.setProperty(TestElement.NAME, "HTTP CookieManager"); |
| cookieManager.setProperty(TestElement.COMMENTS, getDefaultComment()); |
| if (!request.getCookies(request.getUrl()).isEmpty()) { |
| for (Cookie c : request.getCookies(request.getUrl())) { |
| cookieManager.getCookies().addItem(c); |
| } |
| } |
| if (!request.getCookieInHeaders(request.getUrl()).isEmpty() && uploadCookiesCheckBox.isSelected()) { |
| for (Cookie c : request.getCookieInHeaders(request.getUrl())) { |
| cookieManager.getCookies().addItem(c); |
| } |
| } |
| if (!request.getFilepathCookie().isEmpty()) { |
| String pathfileCookie=request.getFilepathCookie(); |
| File file = new File(pathfileCookie); |
| if (file.isFile() && file.exists()) { |
| try { |
| cookieManager.addFile(pathfileCookie); |
| } catch (IOException e) { |
| LOGGER.error("Failed to read from File {}", pathfileCookie, e); |
| throw new IllegalArgumentException("Failed to read from File " + pathfileCookie); |
| } |
| } else { |
| LOGGER.error("File {} doesn't exist", pathfileCookie); |
| throw new IllegalArgumentException("File " + pathfileCookie + " doesn't exist"); |
| } |
| } |
| } |
| |
| private static KeystoreConfig createKeystoreConfiguration() { |
| KeystoreConfig keystoreConfig = new KeystoreConfig(); |
| keystoreConfig.setProperty(TestElement.GUI_CLASS, TestBeanGUI.class.getName()); |
| keystoreConfig.setProperty(TestElement.NAME, "Keystore Configuration"); |
| keystoreConfig.setProperty(TestElement.COMMENTS, getDefaultComment()); |
| return keystoreConfig; |
| } |
| |
| /** |
| * Create Authorization manager |
| * |
| * @param request {@link Request} |
| */ |
| private static void createAuthManager(Request request, AuthManager authManager) { |
| Authorization auth = request.getAuthorization(); |
| authManager.setProperty(TestElement.GUI_CLASS, AuthPanel.class.getName()); |
| authManager.setProperty(TestElement.NAME, "HTTP AuthorizationManager"); |
| authManager.setProperty(TestElement.COMMENTS, getDefaultComment()); |
| authManager.getAuthObjects().addItem(auth); |
| } |
| |
| /** |
| * Whether to update Authorization Manager in http request |
| * |
| * @param request {@link Request} |
| * @param authManager {@link AuthManager} element |
| * @return whether to update Authorization Manager in http request |
| */ |
| private static boolean canAddAuthManagerInHttpRequest(Request request, AuthManager authManager) { |
| Authorization auth = request.getAuthorization(); |
| for (int i = 0; i < authManager.getAuthObjects().size(); i++) { |
| if (!authManager.getAuthObjectAt(i).getUser().equals(auth.getUser()) |
| || !authManager.getAuthObjectAt(i).getPass().equals(auth.getPass()) |
| || authManager.getAuthObjectAt(i).getMechanism() != auth.getMechanism()) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Whether to update Authorization Manager in Thread Group |
| * |
| * @param request {@link Request} |
| * @param authManager {@link AuthManager} element |
| * @return whether to update Authorization Manager in Thread Group |
| */ |
| private static boolean canUpdateAuthManagerInThreadGroup(Request request, AuthManager authManager) { |
| Authorization auth = request.getAuthorization(); |
| for (int i = 0; i < authManager.getAuthObjects().size(); i++) { |
| if (auth.getURL().equals(authManager.getAuthObjectAt(i).getURL())) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| private static void createDnsServer(Request request, DNSCacheManager dnsCacheManager) { |
| Set<String> dnsServers = request.getDnsServers(); |
| dnsCacheManager.setProperty(TestElement.GUI_CLASS, DNSCachePanel.class.getName()); |
| dnsCacheManager.setProperty(TestElement.NAME, "DNS Cache Manager"); |
| dnsCacheManager.setProperty(TestElement.COMMENTS, getDefaultComment()); |
| dnsCacheManager.getServers().clear(); |
| for (String dnsServer : dnsServers) { |
| dnsCacheManager.addServer(dnsServer); |
| } |
| } |
| |
| private static boolean canAddDnsServerInHttpRequest(Request request, DNSCacheManager dnsCacheManager) { |
| Set<String> currentDnsServers =new HashSet<>(); |
| Set<String> newDnsServers = request.getDnsServers(); |
| for (int i = 0; i < dnsCacheManager.getServers().size(); i++) { |
| currentDnsServers.add(dnsCacheManager.getServers().get(i).getStringValue()); |
| } |
| return !(newDnsServers.size() == currentDnsServers.size() && newDnsServers.containsAll(currentDnsServers)); |
| } |
| |
| private static void createDnsResolver(Request request, DNSCacheManager dnsCacheManager) { |
| dnsCacheManager.setProperty(TestElement.GUI_CLASS, DNSCachePanel.class.getName()); |
| dnsCacheManager.setProperty(TestElement.NAME, "DNS Cache Manager"); |
| dnsCacheManager.setCustomResolver(true); |
| dnsCacheManager.getHosts().clear(); |
| String[]resolveParameters=request.getDnsResolver().split(":"); |
| String port=resolveParameters[1]; |
| if (!"443".equals(port) |
| && !"80".equals(port) |
| && !"*".equals(port)) { |
| dnsCacheManager.setProperty(TestElement.COMMENTS, |
| "Custom DNS resolver doesn't support port "+port); |
| } |
| else { |
| dnsCacheManager.setProperty(TestElement.COMMENTS, getDefaultComment()); |
| } |
| dnsCacheManager.addHost(resolveParameters[0], resolveParameters[2]); |
| } |
| |
| @SuppressWarnings("JavaTimeDefaultTimeZone") |
| private static String getDefaultComment() { |
| return "Created from cURL on " + LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME); |
| } |
| |
| private static boolean canAddDnsResolverInHttpRequest(Request request, DNSCacheManager dnsCacheManager) { |
| if (dnsCacheManager.getHosts().size() != 1) { |
| return true; |
| } else { |
| String[] resolveParameters = request.getDnsResolver().split(":"); |
| String host = resolveParameters[0]; |
| String address = resolveParameters[2]; |
| StaticHost statichost = (StaticHost) dnsCacheManager.getHosts().get(0).getObjectValue(); |
| if (statichost.getAddress().equals(address) && statichost.getName().equals(host)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| private void setFormData(Request request, HTTPSamplerProxy httpSampler) { |
| if (request.getPostData() != null) { |
| throw new IllegalArgumentException("--form and --data can't appear in the same command"); |
| } |
| List<HTTPFileArg> httpFileArgs = new ArrayList<>(); |
| for (Pair<String, String> entry : request.getFormStringData()) { |
| String formName = entry.getKey(); |
| String formValue = entry.getValue(); |
| httpSampler.addNonEncodedArgument(formName, formValue, ""); |
| } |
| for (Pair<String, ArgumentHolder> entry : request.getFormData()) { |
| String formName = entry.getKey(); |
| ArgumentHolder formValueObject = entry.getValue(); |
| String formValue = formValueObject.getName(); |
| if (formValueObject instanceof FileArgumentHolder) { |
| String contentType; |
| if (formValueObject.hasContenType()) { |
| contentType = formValueObject.getContentType(); |
| } else { |
| try { |
| final File contentFile = new File(formValue); |
| if (contentFile.canRead()) { |
| contentType = tika.detect(contentFile); |
| } else { |
| LOGGER.info("Can not read file {}, so guessing contentType by extension.", formValue); |
| contentType = tika.detect(formValue); |
| } |
| } catch (IOException e) { |
| LOGGER.info( |
| "Could not detect contentType for file {} by content, so falling back to detection by filename", |
| formValue); |
| contentType = tika.detect(formValue); |
| } |
| } |
| httpFileArgs.add(new HTTPFileArg(formValue, formName, contentType)); |
| } else { |
| if (formValueObject.hasContenType()) { |
| httpSampler.addNonEncodedArgument(formName, formValue, "", formValueObject.getContentType()); |
| } else { |
| httpSampler.addNonEncodedArgument(formName, formValue, ""); |
| } |
| } |
| } |
| if (!httpFileArgs.isEmpty()) { |
| httpSampler.setHTTPFiles(httpFileArgs.toArray(new HTTPFileArg[httpFileArgs.size()])); |
| } |
| } |
| |
| private static void createProxyServer(Request request, HTTPSamplerProxy httpSampler) { |
| Map<String, String> proxyServer = request.getProxyServer(); |
| for (Map.Entry<String, String> proxyPara : proxyServer.entrySet()) { |
| String key = proxyPara.getKey(); |
| switch (key) { |
| case "servername": |
| httpSampler.setProxyHost(proxyPara.getValue()); |
| break; |
| case "port": |
| httpSampler.setProxyPortInt(proxyPara.getValue()); |
| break; |
| case "scheme": |
| httpSampler.setProxyScheme(proxyPara.getValue()); |
| break; |
| case "username": |
| httpSampler.setProxyUser(proxyPara.getValue()); |
| break; |
| case "password": |
| httpSampler.setProxyPass(proxyPara.getValue()); |
| break; |
| default: |
| break; |
| } |
| } |
| } |
| |
| @Override |
| public JMenuItem[] getMenuItemsAtLocation(MENU_LOCATION location) { |
| if (location == MENU_LOCATION.TOOLS) { |
| // Use the action name as resource key because the action name is used by JMeterMenuBar too when changing languages. |
| JMenuItem menuItemIC = new JMenuItem(JMeterUtils.getResString(IMPORT_CURL), KeyEvent.VK_UNDEFINED); |
| menuItemIC.setName(IMPORT_CURL); |
| menuItemIC.setActionCommand(IMPORT_CURL); |
| menuItemIC.setAccelerator(null); |
| menuItemIC.addActionListener(ActionRouter.getInstance()); |
| return new JMenuItem[] { menuItemIC }; |
| } |
| return new JMenuItem[0]; |
| } |
| |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| statusText.setText(""); |
| statusText.setForeground(Color.GREEN); |
| boolean isReadFromFile = false; |
| if (e.getActionCommand().equals(CREATE_REQUEST)) { |
| List<String> commandsList = null; |
| try { |
| if (!filePanel.getFilename().trim().isEmpty() && cURLCommandTA.getText().trim().isEmpty()) { |
| commandsList = readFromFile(filePanel.getFilename().trim()); |
| isReadFromFile = true; |
| } else if (filePanel.getFilename().trim().isEmpty() && !cURLCommandTA.getText().trim().isEmpty()) { |
| commandsList = readFromTextPanel(cURLCommandTA.getText().trim()); |
| } else { |
| throw new IllegalArgumentException( |
| "Error creating tast plan ,Please select one between reading file and directly fill in the panel"); |
| } |
| List<Request> requests = parseCommands(isReadFromFile, commandsList); |
| for (int i=0;i<requests.size();i++) { |
| BasicCurlParser.Request request = requests.get(i); |
| try { |
| String commentText = createCommentText(request); |
| GuiPackage guiPackage = GuiPackage.getInstance(); |
| guiPackage.updateCurrentNode(); |
| JMeterTreeNode treeNode = findFirstNodeOfType(AbstractThreadGroup.class); |
| if (treeNode == null) { |
| LOGGER.info("No AbstractThreadGroup found, potentially empty plan, creating a new plan"); |
| createTestPlan(e, request, commentText); |
| } else { |
| JMeterTreeNode currentNode = guiPackage.getCurrentNode(); |
| Object userObject = currentNode.getUserObject(); |
| if (userObject instanceof Controller && !(userObject instanceof ReplaceableController)) { |
| LOGGER.info("Newly created element will be placed under current selected node {}", |
| currentNode.getName()); |
| addToTestPlan(currentNode, request, commentText); |
| } else { |
| LOGGER.info( |
| "Newly created element will be placed under first AbstractThreadGroup node {}", |
| treeNode.getName()); |
| addToTestPlan(treeNode, request, commentText); |
| } |
| } |
| statusText.setText(JMeterUtils.getResString("curl_create_success")); |
| } |
| catch (Exception ex) { |
| LOGGER.error("Error creating test plan from cURL command:{}, error:{}", commandsList.get(i), |
| ex.getMessage(), ex); |
| statusText.setText( |
| MessageFormat.format(JMeterUtils.getResString("curl_create_failure"), ex.getMessage())); |
| statusText.setForeground(UIManager.getColor(JMeterUIDefaults.LABEL_ERROR_FOREGROUND)); |
| break; |
| } |
| } |
| } catch (Exception ex) { |
| LOGGER.error("Error creating test plan from cURL command list:{}", commandsList, ex); |
| statusText.setText( |
| MessageFormat.format(JMeterUtils.getResString("curl_create_failure"), ex.getMessage())); |
| statusText.setForeground(UIManager.getColor(JMeterUIDefaults.LABEL_ERROR_FOREGROUND)); |
| } |
| } |
| } |
| |
| |
| public List<Request> parseCommands(boolean isReadFromFile, List<String> commandsList) { |
| List<Request> requests = new ArrayList<>(); |
| BasicCurlParser basicCurlParser = new BasicCurlParser(); |
| for (int i = 0; i < commandsList.size(); i++) { |
| try { |
| BasicCurlParser.Request q = basicCurlParser.parse(commandsList.get(i)); |
| requests.add(q); |
| LOGGER.info("Parsed CURL command {} into {}", commandsList.get(i), q); |
| } catch (IllegalArgumentException ie) { |
| if (isReadFromFile) { |
| int line = i + 1; |
| LOGGER.error("Error creating test plan from line {} of file, command:{}, error:{}", line, |
| commandsList.get(i), ie.getMessage(), ie); |
| throw new IllegalArgumentException( |
| "Error creating tast plan from file in line " + line + ", see log file"); |
| } else { |
| LOGGER.error("Error creating test plan from cURL command:{}, error:{}", commandsList.get(i), |
| ie.getMessage(), ie); |
| throw ie; |
| } |
| } |
| } |
| return requests; |
| } |
| |
| private void addToTestPlan(final JMeterTreeNode currentNode, Request request,String statusText) throws MalformedURLException { |
| final HTTPSamplerProxy sampler = createSampler(request,statusText); |
| JMeterTreeModel treeModel = GuiPackage.getInstance().getTreeModel(); |
| JMeterUtils.runSafe(true, () -> { |
| try { |
| boolean canAddAuthManagerInHttpRequest = false; |
| boolean canAddDnsServer=false; |
| boolean canAddDnsResolver=false; |
| if (!request.getAuthorization().getUser().isEmpty()) { |
| JMeterTreeNode jMeterTreeNodeAuth = findFirstNodeOfType(AuthManager.class); |
| if (jMeterTreeNodeAuth == null) { |
| AuthManager authManager = new AuthManager(); |
| createAuthManager(request, authManager); |
| treeModel.addComponent(authManager, currentNode); |
| } else { |
| AuthManager authManager = (AuthManager) jMeterTreeNodeAuth.getTestElement(); |
| if (canUpdateAuthManagerInThreadGroup(request, authManager)) { |
| createAuthManager(request, authManager); |
| } else { |
| canAddAuthManagerInHttpRequest = canAddAuthManagerInHttpRequest(request, authManager); |
| } |
| } |
| } |
| if (!request.getDnsServers().isEmpty()) { |
| DNSCacheManager dnsCacheManager = findNodeOfTypeDnsCacheManagerByType(false); |
| if ( dnsCacheManager == null) { |
| dnsCacheManager=new DNSCacheManager(); |
| createDnsServer(request, dnsCacheManager); |
| treeModel.addComponent(dnsCacheManager, currentNode); |
| } else { |
| canAddDnsServer=canAddDnsServerInHttpRequest(request, dnsCacheManager); |
| } |
| } |
| if (request.getDnsResolver()!=null) { |
| DNSCacheManager dnsCacheManager = findNodeOfTypeDnsCacheManagerByType(true); |
| if (dnsCacheManager == null) { |
| dnsCacheManager=new DNSCacheManager(); |
| createDnsResolver(request, dnsCacheManager); |
| treeModel.addComponent(dnsCacheManager, currentNode); |
| } else { |
| canAddDnsResolver=canAddDnsResolverInHttpRequest(request, dnsCacheManager); |
| } |
| } |
| if (!request.getCookies(request.getUrl()).isEmpty() || !request.getFilepathCookie().isEmpty() |
| || (!request.getCookieInHeaders(request.getUrl()).isEmpty()&&uploadCookiesCheckBox.isSelected())) { |
| JMeterTreeNode jMeterTreeNodeCookie = findFirstNodeOfType(CookieManager.class); |
| if (jMeterTreeNodeCookie == null) { |
| CookieManager cookieManager = new CookieManager(); |
| createCookieManager(cookieManager, request); |
| treeModel.addComponent(cookieManager, currentNode); |
| } else { |
| CookieManager cookieManager = (CookieManager) jMeterTreeNodeCookie.getTestElement(); |
| createCookieManager(cookieManager, request); |
| } |
| } |
| HeaderManager headerManager = sampler.getHeaderManager(); |
| KeystoreConfig keystoreConfig = sampler.getKeystoreConfig(); |
| final JMeterTreeNode newNode = treeModel.addComponent(sampler, currentNode); |
| treeModel.addComponent(headerManager, newNode); |
| if (CERT.equals(request.getCaCert())) { |
| treeModel.addComponent(keystoreConfig, newNode); |
| } |
| if (canAddAuthManagerInHttpRequest) { |
| AuthManager authManager = new AuthManager(); |
| createAuthManager(request, authManager); |
| treeModel.addComponent(authManager, newNode); |
| } |
| if (canAddDnsServer) { |
| DNSCacheManager dnsCacheManager=new DNSCacheManager(); |
| createDnsServer(request, dnsCacheManager); |
| treeModel.addComponent(dnsCacheManager, newNode); |
| } |
| if (canAddDnsResolver) { |
| DNSCacheManager dnsCacheManager=new DNSCacheManager(); |
| createDnsResolver(request, dnsCacheManager); |
| treeModel.addComponent(dnsCacheManager, newNode); |
| } |
| } catch (IllegalUserActionException ex) { |
| LOGGER.error("Error placing sampler", ex); |
| JMeterUtils.reportErrorToUser(ex.getMessage()); |
| } |
| }); |
| } |
| |
| @Override |
| public Set<String> getActionNames() { |
| return commands; |
| } |
| |
| @Override |
| public JMenu[] getTopLevelMenus() { |
| return new JMenu[0]; |
| } |
| |
| @Override |
| public boolean localeChanged(MenuElement menu) { |
| return false; |
| } |
| |
| @Override |
| public void localeChanged() { |
| // NOOP |
| } |
| |
| public List<String> readFromFile(String pathname) throws IOException { |
| String encoding = StandardCharsets.UTF_8.name(); |
| File file = new File(pathname); |
| return FileUtils.readLines(file, encoding); |
| } |
| |
| public List<String> readFromTextPanel(String commands) { |
| String[] cs = commands.split("curl"); |
| List<String> s = new ArrayList<>(); |
| for (int i = 1; i < cs.length; i++) { |
| s.add("curl " + cs[i].trim()); |
| } |
| return s; |
| } |
| |
| public String createCommentText(Request request) { |
| StringBuilder commentText = new StringBuilder(); |
| if (!request.getOptionsIgnored().isEmpty()) { |
| for (String s : request.getOptionsIgnored()) { |
| commentText.append("--"+s + " "); |
| } |
| commentText.append("ignoring; "); |
| } |
| if (!request.getOptionsInProperties().isEmpty()) { |
| for (String s : request.getOptionsInProperties()) { |
| commentText.append(s + " "); |
| } |
| commentText.append("configure in jmeter.properties "); |
| } |
| if (request.getLimitRate() != 0) { |
| commentText.append( |
| "Please configure the limit rate in 'httpclient.socket.http.cps' of 'jmeter.properties(374 line), the value is " |
| + request.getLimitRate() + ";"); |
| } |
| if (!request.getOptionsNoSupport().isEmpty()) { |
| for (String s : request.getOptionsNoSupport()) { |
| commentText.append("--"+s + " "); |
| } |
| commentText.append("not supported; "); |
| } |
| if (request.getNoproxy()!=null) { |
| commentText.append("Please configure noproxy list in terminal and restart JMeter. "); |
| commentText.append("Look: https://jmeter.apache.org/usermanual/get-started.html#proxy_server"); |
| } |
| if (!request.getCaCert().isEmpty()) { |
| commentText.append("Please configure the SSL file with CA certificates in 'SSL configuration' of 'system.properties(49 line)'. "); |
| commentText.append("Look: https://jmeter.apache.org/usermanual/properties_reference.html#ssl_config"); |
| } |
| return commentText.toString(); |
| } |
| } |