├── doc ├── har_convertor_tool_logo.png └── images │ ├── browser_create_har.png │ ├── har_convertor_tool_gui.png │ ├── jmeter_record_template_begin.png │ ├── jmeter_script_record_created.png │ ├── jmeter_record_template_tree_view.png │ ├── browsers_har_convertor_script_record.png │ ├── har_convertor_tool_gui_check_ws_plugin.png │ ├── jmeter_menu_tools_with_har_convertor.png │ ├── jmeter_websocket_script_and_xml_record.png │ ├── browserup-proxy_har_convertor_script_record.png │ ├── browsermob-proxy_har_convertor_script_record.png │ ├── browers_har_external_csv_convertor_script_record.png │ └── lrwr_chrome_extension_har_convertor_script_record.png ├── src └── main │ ├── resources │ └── io │ │ └── github │ │ └── vdaburon │ │ └── jmeterplugins │ │ └── har │ │ ├── har-convertor-to-jmeter.sh │ │ └── har-convertor-to-jmeter.cmd │ └── java │ └── io │ └── github │ └── vdaburon │ └── jmeterplugins │ └── har │ ├── HarConvertorInstaller.java │ └── gui │ └── HarConvertorGui.java ├── pom.xml └── README.md /doc/har_convertor_tool_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdaburon/har-convertor-jmeter-plugin/HEAD/doc/har_convertor_tool_logo.png -------------------------------------------------------------------------------- /doc/images/browser_create_har.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdaburon/har-convertor-jmeter-plugin/HEAD/doc/images/browser_create_har.png -------------------------------------------------------------------------------- /doc/images/har_convertor_tool_gui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdaburon/har-convertor-jmeter-plugin/HEAD/doc/images/har_convertor_tool_gui.png -------------------------------------------------------------------------------- /doc/images/jmeter_record_template_begin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdaburon/har-convertor-jmeter-plugin/HEAD/doc/images/jmeter_record_template_begin.png -------------------------------------------------------------------------------- /doc/images/jmeter_script_record_created.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdaburon/har-convertor-jmeter-plugin/HEAD/doc/images/jmeter_script_record_created.png -------------------------------------------------------------------------------- /doc/images/jmeter_record_template_tree_view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdaburon/har-convertor-jmeter-plugin/HEAD/doc/images/jmeter_record_template_tree_view.png -------------------------------------------------------------------------------- /doc/images/browsers_har_convertor_script_record.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdaburon/har-convertor-jmeter-plugin/HEAD/doc/images/browsers_har_convertor_script_record.png -------------------------------------------------------------------------------- /doc/images/har_convertor_tool_gui_check_ws_plugin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdaburon/har-convertor-jmeter-plugin/HEAD/doc/images/har_convertor_tool_gui_check_ws_plugin.png -------------------------------------------------------------------------------- /doc/images/jmeter_menu_tools_with_har_convertor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdaburon/har-convertor-jmeter-plugin/HEAD/doc/images/jmeter_menu_tools_with_har_convertor.png -------------------------------------------------------------------------------- /doc/images/jmeter_websocket_script_and_xml_record.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdaburon/har-convertor-jmeter-plugin/HEAD/doc/images/jmeter_websocket_script_and_xml_record.png -------------------------------------------------------------------------------- /doc/images/browserup-proxy_har_convertor_script_record.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdaburon/har-convertor-jmeter-plugin/HEAD/doc/images/browserup-proxy_har_convertor_script_record.png -------------------------------------------------------------------------------- /doc/images/browsermob-proxy_har_convertor_script_record.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdaburon/har-convertor-jmeter-plugin/HEAD/doc/images/browsermob-proxy_har_convertor_script_record.png -------------------------------------------------------------------------------- /doc/images/browers_har_external_csv_convertor_script_record.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdaburon/har-convertor-jmeter-plugin/HEAD/doc/images/browers_har_external_csv_convertor_script_record.png -------------------------------------------------------------------------------- /doc/images/lrwr_chrome_extension_har_convertor_script_record.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdaburon/har-convertor-jmeter-plugin/HEAD/doc/images/lrwr_chrome_extension_har_convertor_script_record.png -------------------------------------------------------------------------------- /src/main/resources/io/github/vdaburon/jmeterplugins/har/har-convertor-to-jmeter.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ## Licensed to the Apache Software Foundation (ASF) under one or more 4 | ## contributor license agreements. See the NOTICE file distributed with 5 | ## this work for additional information regarding copyright ownership. 6 | ## The ASF licenses this file to You under the Apache License, Version 2.0 7 | ## (the "License"); you may not use this file except in compliance with 8 | ## the License. You may obtain a copy of the License at 9 | ## 10 | ## http://www.apache.org/licenses/LICENSE-2.0 11 | ## 12 | ## Unless required by applicable law or agreed to in writing, software 13 | ## distributed under the License is distributed on an "AS IS" BASIS, 14 | ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | ## See the License for the specific language governing permissions and 16 | ## limitations under the License. 17 | 18 | ## Run HAR Convert tool in CLI 19 | 20 | ## run script shell with parameters : /bin/har-convertor-to-jmeter.sh -har_in "myhar.har" -jmx_out "script_out.jmx" -record_out "record.xml" -add_pause true -new_tc_pause 5000 21 | ## run script shell with parameters : /bin/har-convertor-to-jmeter.sh -har_in "myhar.har" -jmx_out "script_out.jmx" -filter_include "https://mysite.com/.*" -filter_exclude "https://notmysite.com/.*" - 22 | 23 | cd `dirname $0` 24 | 25 | CP=../lib/ext/har-convertor-jmeter-plugin-${version}-jar-with-dependencies.jar 26 | CP=${CP}:../lib/* 27 | 28 | java -cp $CP io.github.vdaburon.jmeter.har.HarForJMeter $* 29 | -------------------------------------------------------------------------------- /src/main/resources/io/github/vdaburon/jmeterplugins/har/har-convertor-to-jmeter.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem Licensed to the Apache Software Foundation (ASF) under one or more 4 | rem contributor license agreements. See the NOTICE file distributed with 5 | rem this work for additional information regarding copyright ownership. 6 | rem The ASF licenses this file to You under the Apache License, Version 2.0 7 | rem (the "License"); you may not use this file except in compliance with 8 | rem the License. You may obtain a copy of the License at 9 | rem 10 | rem http://www.apache.org/licenses/LICENSE-2.0 11 | rem 12 | rem Unless required by applicable law or agreed to in writing, software 13 | rem distributed under the License is distributed on an "AS IS" BASIS, 14 | rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | rem See the License for the specific language governing permissions and 16 | rem limitations under the License. 17 | 18 | rem Run HAR Convert tool in CLI 19 | 20 | rem run script shell with parameters : \bin\har-convertor-to-jmeter.cmd -har_in "myhar.har" -jmx_out "script_out.jmx" -record_out "record.xml" -add_pause true -new_tc_pause 5000 21 | rem run script shell with parameters : \bin\har-convertor-to-jmeter.cmd -har_in "myhar.har" -jmx_out "script_out.jmx" -filter_include "https://mysite.com/.*" -filter_exclude "https://notmysite.com/.*" - 22 | 23 | setlocal 24 | 25 | cd /D %~dp0 26 | 27 | set CP=..\lib\ext\har-convertor-jmeter-plugin-${version}-jar-with-dependencies.jar 28 | set CP=%CP%;..\lib\* 29 | 30 | java -cp %CP% io.github.vdaburon.jmeter.har.HarForJMeter %* 31 | -------------------------------------------------------------------------------- /src/main/java/io/github/vdaburon/jmeterplugins/har/HarConvertorInstaller.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Vincent DABURON 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | * 15 | */ 16 | 17 | 18 | package io.github.vdaburon.jmeterplugins.har; 19 | 20 | import java.io.File; 21 | import java.io.IOException; 22 | import java.io.InputStream; 23 | import java.nio.file.Files; 24 | import java.nio.file.StandardCopyOption; 25 | 26 | public class HarConvertorInstaller { 27 | public static void main(String[] argv) throws IOException { 28 | writeOut("har-convertor-to-jmeter.cmd", false); 29 | writeOut("har-convertor-to-jmeter.sh", true); 30 | } 31 | 32 | private static void writeOut(String resName, boolean executable) throws IOException { 33 | resName = "/io/github/vdaburon/jmeterplugins/har/" + resName; 34 | File self = new File(HarConvertorInstaller.class.getProtectionDomain().getCodeSource().getLocation().getFile()); 35 | File src = new File(resName); 36 | String home = self.getParentFile().getParentFile().getParent(); 37 | File dest = new File(home + File.separator + "bin" + File.separator + src.getName()); 38 | 39 | InputStream is = HarConvertorInstaller.class.getResourceAsStream(resName); 40 | Files.copy(is, dest.toPath(), StandardCopyOption.REPLACE_EXISTING); 41 | dest.setExecutable(executable); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | io.github.vdaburon 8 | har-convertor-jmeter-plugin 9 | 8.0 10 | jar 11 | 12 | Apache JMeter Plugin to convert a HAR file to a JMeter script and Record XML 13 | Apache JMeter Plugin to convert a HAR file to a JMeter script and Record XML 14 | https://github.com/vdaburon/har-convertor-jmeter-plugin 15 | 2024 16 | 17 | 18 | Apache License, Version 2.0 19 | https://www.apache.org/licenses/LICENSE-2.0.txt 20 | A business-friendly OSS license 21 | 22 | 23 | 24 | 25 | 26 | vdaburon 27 | Vincent DABURON 28 | vdaburon at gmail dot com 29 | 30 | architect 31 | developer 32 | 33 | 34 | 35 | 36 | 37 | jmeter-plugins-google-group 38 | https://groups.google.com/g/jmeter-plugins 39 | 40 | 41 | 42 | https://github.com/vdaburon/har-convertor-jmeter-plugin.git 43 | https://github.com/vdaburon/har-convertor-jmeter-plugin.git 44 | https://github.com/vdaburon/har-convertor-jmeter-plugin 45 | HEAD 46 | 47 | 48 | 49 | ossrh 50 | https://s01.oss.sonatype.org/content/repositories/snapshots 51 | 52 | 53 | ossrh 54 | https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/ 55 | 56 | 57 | 58 | 59 | 8 60 | 8 61 | UTF-8 62 | false 63 | 64 | 65 | 66 | 67 | 68 | org.apache.jmeter 69 | ApacheJMeter_core 70 | 5.5 71 | provided 72 | 73 | 74 | 75 | org.slf4j 76 | slf4j-api 77 | 1.7.36 78 | provided 79 | 80 | 81 | 82 | 83 | io.github.vdaburon 84 | har-to-jmeter-convertor 85 | 8.0 86 | 87 | 88 | 89 | 90 | 91 | 92 | org.apache.maven.plugins 93 | maven-compiler-plugin 94 | 3.13.0 95 | 96 | ${maven.compiler.source} 97 | ${maven.compiler.target} 98 | ${project.build.sourceEncoding} 99 | 100 | 101 | 102 | org.apache.maven.plugins 103 | maven-javadoc-plugin 104 | 2.9.1 105 | 106 | 107 | attach-javadocs 108 | 109 | jar 110 | 111 | 112 | 113 | 114 | 115 | org.apache.maven.plugins 116 | maven-source-plugin 117 | 3.3.1 118 | 119 | 120 | attach-sources 121 | 122 | jar 123 | 124 | 125 | 126 | 127 | 128 | 129 | org.apache.maven.plugins 130 | maven-assembly-plugin 131 | 3.7.1 132 | 133 | 134 | package 135 | 136 | single 137 | 138 | 139 | 140 | 141 | 142 | io.github.vdaburon.jmeterplugins.har.HarConvertorIntegrateGui 143 | 144 | 145 | 146 | 147 | jar-with-dependencies 148 | 149 | 150 | 151 | 152 | 153 | 154 | org.apache.maven.plugins 155 | maven-gpg-plugin 156 | 3.1.0 157 | 158 | 159 | sign-artifacts 160 | verify 161 | 162 | sign 163 | 164 | 165 | 166 | 167 | 168 | 172 | org.sonatype.central 173 | central-publishing-maven-plugin 174 | 0.9.0 175 | true 176 | 177 | central_publishing 178 | https://central.sonatype.com 179 | published 180 | ${mavenCentralAutoReleaseAfterClose} 181 | 182 | 183 | 184 | 185 | 186 | 187 | src/main/resources 188 | 189 | true 190 | 191 | 192 | 193 | 194 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | har convertor jmeter plugin logo 3 |

Convert a HAR file to a JMeter script and a Record XML file.

4 |

Link to github project har-convertor-jmeter-plugin

5 |

6 | 7 | # Convert a HAR (Http ARchive) file to a JMeter script and a Record XML file. 8 | [![Maven Central](https://img.shields.io/maven-central/v/io.github.vdaburon/har-convertor-jmeter-plugin)](https://central.sonatype.com/artifact/io.github.vdaburon/har-convertor-jmeter-plugin) 9 | [![Apache License](http://img.shields.io/badge/license-Apache-green.svg)](https://github.com/vdaburon/CreateHtmlForFilesInDirectory/blob/main/LICENSE) 10 | ![Free](https://img.shields.io/badge/free-open--source-green.svg) 11 | [![Apache JMeter](https://img.shields.io/badge/Apache%20JMeter-green)](https://jmeter.apache.org/) 12 | 13 | An article about motivations to create this tool: https://dzone.com/articles/convert-a-har-file-to-jmeter-script 14 | 15 | Since version 7.0, **Websocket** is manage with samplers from the plugin "WebSocket Samplers by Peter Doornbosch". 16 | 17 | ## GUI interface in the JMeter Tools Menu 18 | This tool is present in the Menu Tools > vdn@github - HAR Convertor Tool 19 | 20 | ![Menu Tools](doc/images/jmeter_menu_tools_with_har_convertor.png) 21 | 22 | When you click and the menu line "vdn@github - HAR Convertor Tool", the tool GUI is display 23 | 24 | ![Menu Tools](doc/images/har_convertor_tool_gui.png) 25 | 26 | ### Parameters 27 | Parameters are : 28 | * har_in the HAR file to read (exported HAR from Web Browser : Chrome, Firefox, Edge ...) 29 | * jmx_out the file JMeter script generated, if the text field is empty then the jmx_out is the file name of har_in without the extension with suffix ".jmx"
30 | e.g. har_in = myhar1.har, jmx_out is empty then file_out will be myhar1.jmx 31 | * record_out create the record xml file from the har file (could be open with the Listener View Results Tree)
32 | e.g. record_out = record.xml 33 | * add_result_tree_record, add a View Result Tree to view the Recording XML File Generated (default true), the record_out must be not empty 34 | * ws_with_pdoornbosch, create WebSocket Sampler if HAR contains WebSocket Connection (ws or wss) and WebSocket Exchange message (default false). Need this JMeter plugin "WebSocket Samplers by Peter Doornbosch" to open generated JMeter script. 35 | * external_file_infos, external csv file contains information about Timestamp, Transaction Name, date start or end.
36 | e.g. external_file_infos = myappli_transactions.csv 37 | * new_tc_pause time between 2 urls to create a new page (Transaction Controller) (default 5000 = jmeter property value : proxy.pause=5000)
38 | * e.g. 5000 for 5 sec between 2 urls 39 | * page_start_number, set the start page number for partial recording (default 1, must be an integer > 0)
40 | * sampler_start_number, set the start sampler number for partial recording (default 1, must be an integer > 0)
41 | * filter_include, the regular expression matches the URL to Include (first filter)
42 | * default all = empty (no filter) 43 | * e.g. filter_include=https://mysite.com/.* 44 | * filter_exclude, the regular expression matches the URL to Exclude (second filter)
45 | * default all = empty (no filter) 46 | * e.g. filter_exclude=https://notmysite.com/.* 47 | * or filter statics, filter_exclude=(?i).*\\.(bmp|css|js|gif|ico|jpe?g|png|swf|eot|otf|ttf|mp4|woff|woff2|svg) 48 | * remove_headers, remove a list of http headers (comma separator, case insensitive), e.g: -remove_headers "User-Agent,Pragma,X-TOKEN" 49 | * add_pause checkbox, add Flow Control Action Pause, parameter new_tc_pause must be > 0 (default true)
50 | * remove_cookie checkbox , remove header with cookie because add a Cookie Manager in the script (default true)
51 | * remove_cache_request checkbox, remove cache request header because add a Cache Manager in the script (default true)
52 | * har created with lrwr, the har file has been generated with LoadRunner Web Recorder Chrome extension and contains Transaction Name, expected values : true or false (default false = unchecked)
53 | 54 | 55 | Status, the status line contains the tool status or the tool result. 56 | 57 | e.g. : Status Results **OK** 58 | * Tool HAR Convertor Finished OK, fileJmxOut=C:\Temp\script1.jmx 59 | * Tool HAR Convertor Finished OK, fileJmxOut=C:\Temp\script1.jmx AND recordXmlOut=C:\Temp\record.xml 60 | 61 | e.g. : Status Results **KO** 62 | * Tool HAR Convertor Finished KO, CAN'T READ HAR fileHarIn = C:\Temp\harzzzz.har 63 | * Tool HAR Convertor Finished KO, exception = java.util.regex.PatternSyntaxException: Unmatched closing ')' near index 2 (.)) 64 | * Tool HAR Convertor Finished KO, exception = net.sf.saxon.trans.XPathException: Failed to create output file file:/c:/toto.jmx 65 | 66 | ### Action buttons 67 | * "CONVERT AND LOAD GENERATED SCRIPT", generates the JMeter script and record.xml file if set, next if no error LOAD the generated script in the current JMeter. 68 | * "CONVERT", generates the JMeter script and record.xml file if set. 69 | 70 | ## Creating a har file and run the tool har-to-jmx-convertor to simulate recording from the JMeter recording template 71 | This tool har-to-jmx-convertor try to **simulate** a script JMeter and a record xml file recording from the **JMeter Recording Template**. 72 | 73 | ### JMeter Recording Template and HTTP(S) Test Script Recorder - The standard way to record 74 | The JMeter Recording Template :
75 | ![JMeter recording template start](doc/images/jmeter_record_template_begin.png) 76 | 77 | The result of recording with JMeter "HTTP(S) Test Script Recorder" :
78 | ![JMeter script and record](doc/images/jmeter_record_template_tree_view.png) 79 | 80 | ### HAR created on a Browser (e.g. Firefox) - The new way with the convertor tool 81 | Record the navigation in the web application with Developer tool : **Network** and **save** exchanges in **HAR** file format :
82 | ![Browser save HAR file](doc/images/browser_create_har.png) 83 | 84 | Launch the "Convertor tool" :
85 | ![Step to create script and record from HAR file](doc/images/browsers_har_convertor_script_record.png) 86 | 87 | Tool results : Open the script created and the record.xml in a View Results Tree
88 | ![Open the script created](doc/images/jmeter_script_record_created.png) 89 | 90 | ### Standard HAR file created with Firefox, Chrome, Edge with external csv file for transaction information 91 | You could add an external file that contains information about transaction name start and end. 92 | 93 | ![Step to create script and record from HAR file and external csv file](doc/images/browers_har_external_csv_convertor_script_record.png) 94 | 95 | The format is : 96 | - Timestamp iso format GMT;TRANSACTION;transaction name;start for starting a new transaction 97 | - Timestamp iso format GMT;TRANSACTION;transaction name;stop for ending transaction the precedent transaction 98 | - Separator ";" 99 | - Charset UTF-8 100 | 101 | E.g : 102 |
103 | 2024-05-06T12:39:58.711Z;TRANSACTION;login;start
104 | 2024-05-06T12:40:08.643Z;TRANSACTION;login;stop
105 | 2024-05-06T12:40:20.880Z;TRANSACTION;home;start
106 | 2024-05-06T12:40:37.634Z;TRANSACTION;home;stop
107 | 
108 | 109 | A simple tool named "create-external-file-for-har" create easily this csv file. https://github.com/vdaburon/create-external-file-for-har 110 | 111 | You need to select the csv file in the text field : "(Optional) External csv file with transaction info (to read) " 112 | 113 | ### HAR created with BrowserUp Proxy 114 | This tool is compatible with Har file generated with BrowserUp Proxy. 115 | 116 | The BrowserUp Proxy create a har and could filter url or content (no binary). 117 | 118 | The proxy client could be a browser or a client http in an application. 119 | 120 | BrowserUp Proxy could be embedded in a java application or in Selenium java code application. 121 | 122 | ![Step to create script and record from HAR file from BrowserUp](doc/images/browserup-proxy_har_convertor_script_record.png) 123 | 124 | The BrowserUp Proxy **active** project is available at this url :
125 | [Goto the BrowserUp Proxy active project](https://github.com/valfirst/browserup-proxy) 126 | 127 | Note : The BrowserMod Proxy tool is no more active (since september 2017) and it's recommended to migrate to BrowerUp proxy https://github.com/valfirst/browserup-proxy the "valfirst" GitHub username is important. 128 | 129 | ### HAR created in Chrome Browser with the OpenText Professional Performance Engineering (LoadRunner) Web Recorder Chrome Extension 130 | This tool is compatible with Har file generated with the LoadRunner Web Recorder Chrome Extension. 131 | 132 | The main advantage is to declare **Transaction Names when recording** and navigate to the web site. This transactions will be Page Names (Transaction Controllers names) in the JMeter script. 133 | 134 | ![Step to create script and record from HAR file from LoadRunner Web Recorder](doc/images/lrwr_chrome_extension_har_convertor_script_record.png) 135 | 136 | The OpenText Professional Performance Engineering (LoadRunner) Web Recorder Chrome Extension is available at this url :
137 | [Download the Recorder extension for Chrome : "HarGeneratorChrome"](https://marketplace.opentext.com/appdelivery/content/recorder-extension-for-chrome) 138 | 139 | You need to check to checkbox "HAR was generated with LoadRunner Web Recorder and Transaction Names" to indicate that is a HAR file generated with LoadRunner Web Recorder (lrwr), default false (unchecked). 140 | 141 | ## Websocket use the plugin "WebSocket Samplers by Peter Doornbosch" 142 | If your Har file contains WebSocket Connection and Messages, check the checkbox ws_with_pdoornbosch (set true), this tool will try to create Websocket Samplers in the JMeter script generated and the exchanges in the Recording XML file if you set the record xml file name. 143 | 144 | Documentation at : https://bitbucket.org/pjtr/jmeter-websocket-samplers/src/master/ 145 | 146 | The HAR is record from **Chrome** Browser not Firefox Browser and not Egde Browser (research in har file the attribute : '_webSocketMessages'). 147 | 148 | Currently limitation to only one websocket connection and multi text messages (send or receive) in this websocket connection (binary message is not tested). 149 | 150 | Text message could be on "STOMP" format (https://en.wikipedia.org/wiki/Streaming_Text_Oriented_Messaging_Protocol) or no "STOMP" (simple text). 151 | 152 | Need the plugin "WebSocket Samplers by Peter Doornbosch" to open the generated script that contain Websocket Samplers. 153 | 154 | This demonstration use the web site : https://websocket.org/tools/websocket-echo-server/ 155 | 156 | ![Script generated with Websocket samplers and xml record messages](doc/images/jmeter_websocket_script_and_xml_record.png) 157 | 158 | If you click on the checkbox "Create WebSocket Sampler if HAR contains WebSocket Connection" but the JMeter **have not the plugin** "WebSocket Samplers by Peter Doornbosch" a warning message is display and the button "CONVERT AND LOAD GENERATED SCRIPT" is disable. 159 | 160 | ![Warning if the plugin "WebSocket Samplers by Peter Doornbosch" is not present](doc/images/har_convertor_tool_gui_check_ws_plugin.png) 161 | 162 | 163 | ## More documentation from har-to-jmeter-convertor CLI Tool 164 | This plugin use a **library** from the Command Line Interface tool (har-to-jmeter-convertor)
165 | For more documentation look at README from [har-to-jmeter-convertor](https://github.com/vdaburon/har-to-jmeter-convertor) 166 | 167 | ## Command line tool (CLI) 168 | This tool could be use with script shell Windows or Linux. 169 | 170 | Scripts shell are in <JMETER_HOME>\bin 171 | * har-convertor-to-jmeter.cmd for Windows OS 172 | * har-convertor-to-jmeter.sh for Linux/Mac OS 173 | 174 | Help to see all parameters : 175 | 176 |
177 | C:\apache-jmeter\bin>har-convertor-to-jmeter.cmd -help
178 | 
179 | usage: io.github.vdaburon.jmeter.har.HarForJMeter [-add_pause <add_pause>] [-add_result_tree_record
180 |        <add_result_tree_record>] [-external_file_infos <external_file_infos>] [-filter_exclude <filter_exclude>]
181 |        [-filter_include <filter_include>] -har_in <har_in> [-help] -jmx_out <jmx_out> [-new_tc_pause <new_tc_pause>]
182 |        [-page_start_number <page_start_number>] [-record_out <record_out>] [-remove_cache_request
183 |        <remove_cache_request>] [-remove_cookie <remove_cookie>] [-remove_headers <remove_headers>]
184 |        [-sampler_start_number <sampler_start_number>] [-use_lrwr_infos <use_lrwr_infos>] [-ws_with_pdoornbosch
185 |        <ws_with_pdoornbosch>]
186 | io.github.vdaburon.jmeter.har.HarForJMeter
187 |  -add_pause <add_pause>                             Optional boolean, add Flow Control Action Pause after Transaction
188 |                                                     Controller (default true)
189 |  -add_result_tree_record <add_result_tree_record>   Optional boolean, add 'View Result Tree' to view the record.xml file
190 |                                                     created (default true), record_out must be not empty
191 |  -external_file_infos <external_file_infos>         Optional, csv file contains external infos : timestamp transaction
192 |                                                     name and start or end
193 |  -filter_exclude <filter_exclude>                   Optional, regular expression to exclude url
194 |  -filter_include <filter_include>                   Optional, regular expression to include url
195 |  -har_in <har_in>                                   Har file to read (e.g : my_file.har)
196 |  -help                                              Help and show parameters
197 |  -jmx_out <jmx_out>                                 JMeter file created to write (e.g : script.jmx)
198 |  -new_tc_pause <new_tc_pause>                       Optional, create new Transaction Controller after request ms, same
199 |                                                     as jmeter property : proxy.pause, need to be > 0 if set. Usefully
200 |                                                     for Har created by Firefox or Single Page Application (Angular,
201 |                                                     ReactJS, VuesJS ...)
202 |  -page_start_number <page_start_number>             Optional, the start page number for partial recording (default 1)
203 |  -record_out <record_out>                           Optional, file xml contains exchanges likes recorded by JMeter
204 |  -remove_cache_request <remove_cache_request>       Optional boolean, remove cache header in the http request (default
205 |                                                     true because add a Cache Manager)
206 |  -remove_cookie <remove_cookie>                     Optional boolean, remove cookie in http header (default true because
207 |                                                     add a Cookie Manager)
208 |  -remove_headers <remove_headers>                   Remove a list of headers (comma separator, case insensitive),
209 |                                                     e.g:User-Agent,Pragma,X-TOKEN
210 |  -sampler_start_number <sampler_start_number>       Optional, the start sampler number for partial recording (default 1)
211 |  -use_lrwr_infos <use_lrwr_infos>                   Optional, the har file has been generated with LoadRunner Web
212 |                                                     Recorder and contains Transaction Name, expected value :
213 |                                                     'transaction_name' or don't add this parameter
214 |  -ws_with_pdoornbosch <ws_with_pdoornbosch>         Optional boolean, Manage websocket messages with the JMeter plugin
215 |                                                     from Peter DOORNBOSH (default false), if true need the plugin from
216 |                                                     Peter DOORNBOSH to open the generated script
217 | E.g : java -jar har-for-jmeter-<version>-jar-with-dependencies.jar -har_in myhar.har -jmx_out scriptout.jmx -record_out
218 | recording.xml -add_result_tree_record true -new_tc_pause 5000 -add_pause true -filter_include "https://mysite/.*"
219 | -filter_exclude "https://notmysite/*" -page_start_number 50 -sampler_start_number 250 -ws_with_pdoornbosch false
220 | -remove_headers "User-Agent,Pragma"
221 | 
222 | 
223 | 224 |
225 | C:\apache-jmeter\bin>har-convertor-to-jmeter.cmd -har_in "myhar.har" -jmx_out "script_out.jmx" -filter_include "https://mysite.com/.*" -filter_exclude "https://notmysite.com/.*" -add_pause true -new_tc_pause 5000
226 | 
227 | 228 |
229 | /var/opt/apache-jmeter/bin>./har-convertor-to-jmeter.sh -har_in "myhar.har" -jmx_out "script_out.jmx" -record_out "record.xml" -add_pause true -new_tc_pause 5000
230 | 
231 | 232 | ## Tool installed with jmeter-plugins-manager 233 | This tool could be installed with the jmeter-plugins-manager from jmeter.plugins.org.
234 | The tool name is : "vdn@github - har-convertor-jmeter-tool" 235 | 236 | ## Usage Maven 237 | The maven groupId, artifactId and version, this plugin is in the **Maven Central Repository** [![Maven Central](https://img.shields.io/maven-central/v/io.github.vdaburon/har-convertor-jmeter-plugin)](https://central.sonatype.com/artifact/io.github.vdaburon/har-convertor-jmeter-plugin) 238 | 239 | ```xml 240 | io.github.vdaburon 241 | har-convertor-jmeter-plugin 242 | 8.0 243 | ``` 244 | 245 | ## License 246 | Licensed under the Apache License, Version 2.0 247 | 248 | ## Versions 249 | Version 8.0 date 2025-11-22, Use new library har-to-jmeter-convertor 8.0 add new parameter -remove_headers remove a list of http headers (comma separator, case insensitive), e.g: -remove_headers "User-Agent,Pragma,X-TOKEN" 250 | 251 | Version 7.1 date 2025-03-27, Use new library har-to-jmeter-convertor 7.1 remove request headers from HTTP/2, these headers start with ':' likes ":authority", ":method", ":path" or ":scheme" correct Issue #2. Don't create HttpSampler for url "data:". 252 | 253 | Version 7.0 date 2025-02-27, Use new library har-to-jmeter-convertor 7.0 add manage the websocket messages with 'WebSocket Samplers by Peter Doornbosch', add checkbox for boolean parameter 'ws_with_pdoornbosch' (default unchecked == false). 254 | 255 | Version 6.1 date 2025-01-28, Use new library har-to-jmeter-convertor 6.1 to correct a NullPointerException when creating the Recording XML file. 256 | 257 | Version 6.0 date 2024-09-19, Use new library har-to-jmeter-convertor 6.0 for adding 'HTTP(S) Test Script Recorder' and 'View Results Tree' to view the Record.xml file created. Correct save file no url encoded name. 258 | 259 | Version 5.3 date 2024-09-13, Use new library har-to-jmeter-convertor 5.3 that correct PUT with no parameter, no content and mime-type == null 260 | 261 | Version 5.2 date 2024-06-20, Use new library har-to-jmeter-convertor 5.2 that correct extract parameters for mime type "form-urlencoded" ended with charset likes "application/x-www-form-urlencoded; charset=xxx" 262 | 263 | Version 5.1 date 2024-05-17, Compatible with har generated by browsermob-proxy tool and csv file contains transaction infos. Use library har-to-jmeter-convertor 5.1. 264 | 265 | Version 5.0 date 2024-05-10, Add an external csv file with transaction information for JMeter Transaction Controller Name. New parameter : -external_file_infos transaction_info.csv. Correct Filter Include first filter and Filter Exclude second filter. 266 | 267 | Version 4.0 date 2024-05-06, Add compatibility with HAR generated with LoadRunner Web Recorder Chrome Extension. New checkbox "(Optional) HAR was generated with LoadRunner Web Recorder and Transaction Names" 268 | 269 | Version 3.2 date 2024-03-30, Use library har-to-jmeter-convertor-2.2.jar, this version encode value for x-www-form-urlencoded when value contains space ' ' or equal '=' or slash '/' or plus '+' characters. Correct add the content for body data for POST, PUT or PATCH if not x-www-form-urlencoded in the Record.xml file. 270 | 271 | Version 3.1 date 2024-03-29, Use library har-to-jmeter-convertor-2.2.jar, this version remove the header 'Content-length' because the length is computed by JMeter when the request is created. POST or PUT could have query string and body with content so add query string to the path. Set Content Encoding to UFT-8 for POST or PUT method and request Content-Type : application/json. Add body data content in record.xml for PUT and PATCH methods. 272 | 273 | Version 3.0 date 2024-03-18, Add Load generated script if no error. File Chooser select only file and no directory. 274 | 275 | Version 2.0 date 2024-03-12, for POST multipart/form-data don't put the content of the file in the Record.xml file because binary content could be large and not XML compatible. Add parameters : page_start_number and sampler_start_number to facilitate partial recording of website navigation. 276 | 277 | Version 1.0 date 2024-03-11, First Release. 278 | 279 | -------------------------------------------------------------------------------- /src/main/java/io/github/vdaburon/jmeterplugins/har/gui/HarConvertorGui.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Vincent DABURON 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | * 15 | */ 16 | 17 | 18 | package io.github.vdaburon.jmeterplugins.har.gui; 19 | 20 | import io.github.vdaburon.jmeter.har.HarForJMeter; 21 | 22 | import org.apache.jmeter.exceptions.IllegalUserActionException; 23 | import org.apache.jmeter.gui.GuiPackage; 24 | import org.apache.jmeter.gui.JMeterFileFilter; 25 | import org.apache.jmeter.gui.UnsharedComponent; 26 | import org.apache.jmeter.gui.action.AbstractAction; 27 | import org.apache.jmeter.gui.plugin.MenuCreator; 28 | import org.apache.jmeter.gui.util.EscapeDialog; 29 | import org.apache.jmeter.gui.util.VerticalPanel; 30 | import org.apache.jmeter.save.SaveService; 31 | import org.apache.jorphan.collections.HashTree; 32 | import org.apache.jorphan.gui.ComponentUtil; 33 | 34 | import org.slf4j.Logger; 35 | import org.slf4j.LoggerFactory; 36 | 37 | import javax.swing.*; 38 | 39 | import java.awt.*; 40 | import java.awt.event.ActionEvent; 41 | import java.awt.event.ActionListener; 42 | import java.io.File; 43 | import java.io.Serializable; 44 | import java.util.HashSet; 45 | import java.util.Set; 46 | 47 | public class HarConvertorGui extends AbstractAction implements 48 | ActionListener, UnsharedComponent, MenuCreator, Serializable { 49 | 50 | private static Set commands = new HashSet<>(); 51 | 52 | @SuppressWarnings("unused") 53 | private static final long serialVersionUID = 2433L; 54 | 55 | private static final Logger log = LoggerFactory.getLogger(HarConvertorGui.class); 56 | private static final String BROWSE_HAR_IN = "BROWSE_HAR_IN"; 57 | private static final String BROWSE_JMX_OUT = "BROWSE_JMX_OUT"; 58 | private static final String BROWSE_RECORD_OUT = "BROWSE_RECORD_OUT"; 59 | private static final String BROWSE_EXTERNAL_FILE_IN = "BROWSE_EXTERNAL_FILE_IN"; 60 | private static final String ACTION_CONVERT = "ACTION_CONVERT"; 61 | private static final String ACTION_CONVERT_AND_LOAD_SCRIPT = "ACTION_CONVERT_LOAD"; 62 | private static final String ACTION_MENU_TOOL = "ACTION_MENU_TOOL"; 63 | private static final String ACTION_CHECKBOX_WEBSOCKET = "ACTION_CHECKBOX_WEBSOCKET"; 64 | 65 | private EscapeDialog messageDialog; 66 | 67 | private JTextField fileHarInTextField; 68 | private JTextField fileJmxOutTextField; 69 | private JTextField fileRecordOutTextField; 70 | private JTextField externalFileInfoInField; 71 | private JTextField pauseBetweenUrlTextField; 72 | private JTextField pageStartNumberTextField; 73 | private JTextField samplerStartNumberTextField; 74 | private JButton fileHarInFileButton; 75 | private JTextField regexFilterIncludeField; 76 | private JTextField regexFilterExcludeField; 77 | private JTextField removeHeadersField; 78 | private JButton fileJmxOutFileButton; 79 | private JButton fileRecordOutFileButton; 80 | private JButton externalFileInfoInButton; 81 | private JCheckBox isAddPauseCheckbox; 82 | private JCheckBox isRemoveCookieCheckbox; 83 | private JCheckBox isRemoveCacheRequestHeaderCheckbox; 84 | private JCheckBox isUseLrwrTransactionNameCheckbox; 85 | private JCheckBox isAddResultTreeRecordCheckbox; 86 | private JCheckBox isWebSocketPDoornboschCheckbox; 87 | 88 | private JButton btConvert; 89 | private JButton btConvertAndLoad; 90 | private String lastJFCDirectory; 91 | private JTextField labelStatus; 92 | 93 | static { 94 | commands.add(ACTION_MENU_TOOL); 95 | } 96 | public HarConvertorGui() { 97 | super(); 98 | log.debug("Creating HarConvertorGui"); 99 | } 100 | 101 | 102 | public String getLabelResource() { 103 | return this.getClass().getSimpleName(); 104 | } 105 | 106 | public void doAction(ActionEvent e) throws IllegalUserActionException { 107 | HarConvertorGui harConvertorGui = new HarConvertorGui(); 108 | JFrame jfMainFrame = GuiPackage.getInstance().getMainFrame(); 109 | harConvertorGui.showInputDialog(jfMainFrame); 110 | } 111 | 112 | public void showInputDialog(JFrame parent) { 113 | setupInputDialog(parent); 114 | launchInputDialog(); 115 | } 116 | 117 | private void launchInputDialog() { 118 | messageDialog.pack(); 119 | ComponentUtil.centerComponentInWindow(messageDialog); 120 | messageDialog.setVisible(true); 121 | } 122 | 123 | public void setupInputDialog(JFrame parent) { 124 | messageDialog = new EscapeDialog(parent, "vdn@github - HAR CONVERTOR TOOL", false); 125 | setupContentPane(); 126 | } 127 | 128 | private void setupContentPane() { 129 | Container contentPane = messageDialog.getContentPane(); 130 | contentPane.setLayout(new BorderLayout(0,5)); 131 | 132 | JPanel mainPanel = new JPanel(new BorderLayout()); 133 | VerticalPanel vertPanel = new VerticalPanel(); 134 | vertPanel.setBorder(BorderFactory.createTitledBorder( 135 | BorderFactory.createEtchedBorder(), "HAR Convertor Configuration")); 136 | 137 | vertPanel.add(setupFileChooserPanel()); 138 | vertPanel.add(createFilterAndPausePanel()); 139 | vertPanel.add(createCheckbox()); 140 | vertPanel.add(createControls()); 141 | 142 | labelStatus = new JTextField("Waiting configuration ... "); 143 | labelStatus.setEditable(false); 144 | vertPanel.add(labelStatus); 145 | 146 | mainPanel.add(vertPanel); 147 | contentPane.add(mainPanel); 148 | 149 | } 150 | 151 | 152 | @Override 153 | public void actionPerformed(ActionEvent action) { 154 | String command = action.getActionCommand(); 155 | Exception except = null; 156 | 157 | // log.info("command=" + command); 158 | if (command.equals(ACTION_MENU_TOOL)) { 159 | try { 160 | doAction(action); 161 | } catch (IllegalUserActionException e) { 162 | e.printStackTrace(); 163 | } 164 | } 165 | 166 | if (command.equals(ACTION_CONVERT) || command.equals(ACTION_CONVERT_AND_LOAD_SCRIPT)) { 167 | String fileHarIn= fileHarInTextField.getText(); 168 | 169 | File fFileIn = new File(fileHarIn); 170 | if (!fFileIn.canRead()) { 171 | labelStatus.setText("Tool HAR Convertor Finished KO, CAN'T READ HAR fileHarIn = " + fileHarIn); 172 | labelStatus.setForeground(java.awt.Color.RED); 173 | return; 174 | } 175 | 176 | String externalFileInfoIn= externalFileInfoInField.getText(); 177 | if (!externalFileInfoIn.isEmpty()) { 178 | File fExternalFileInfoIn = new File(externalFileInfoIn); 179 | if (!fExternalFileInfoIn.canRead()) { 180 | labelStatus.setText("Tool HAR Convertor Finished KO, CAN'T READ CSV externalFileInfoIn = " + externalFileInfoIn); 181 | labelStatus.setForeground(java.awt.Color.RED); 182 | return; 183 | } 184 | } 185 | 186 | String fileJmxOut= fileJmxOutTextField.getText(); 187 | String recordXmlOut= fileRecordOutTextField.getText(); 188 | String regexFilterInclude= regexFilterIncludeField.getText(); 189 | String regexFilterExclude= regexFilterExcludeField.getText(); 190 | String removeHeaders = removeHeadersField.getText(); 191 | 192 | if (fileJmxOut.trim().isEmpty()) { 193 | fileJmxOut = fileHarIn.substring(0,fileHarIn.lastIndexOf(".")) + ".jmx"; 194 | } 195 | if (regexFilterInclude.trim().isEmpty()) { 196 | regexFilterInclude = ""; 197 | } 198 | 199 | boolean isAddPause = isAddPauseCheckbox.isSelected(); 200 | 201 | String timeWaitBetweenUrls = pauseBetweenUrlTextField.getText(); 202 | long createNewTransactionAfterRequestMs = 0; 203 | if (!timeWaitBetweenUrls.isEmpty()) { 204 | try { 205 | createNewTransactionAfterRequestMs = Integer.parseInt(timeWaitBetweenUrls); 206 | if (isAddPause && createNewTransactionAfterRequestMs > 0) { 207 | isAddPause = true; 208 | } 209 | } catch (Exception ex) { 210 | log.warn("Error parsing long parameter " + ", value = " + timeWaitBetweenUrls + ", set to 0"); 211 | createNewTransactionAfterRequestMs = 0; 212 | } 213 | } 214 | 215 | String sPageStartNumber = pageStartNumberTextField.getText(); 216 | int pageStartNumber = 1; 217 | if (!sPageStartNumber.isEmpty()) { 218 | try { 219 | pageStartNumber = Integer.parseInt(sPageStartNumber); 220 | } catch (Exception ex) { 221 | log.warn("Error parsing int parameter " + ", value = " + sPageStartNumber + ", set to 1"); 222 | pageStartNumber = 1; 223 | } 224 | } 225 | if (pageStartNumber <= 0) { 226 | pageStartNumber = 1; 227 | } 228 | 229 | String sSamplerStartNumber = samplerStartNumberTextField.getText(); 230 | int samplerStartNumber = 1; 231 | if (!sSamplerStartNumber.isEmpty()) { 232 | try { 233 | samplerStartNumber = Integer.parseInt(sSamplerStartNumber); 234 | } catch (Exception ex) { 235 | log.warn("Error parsing int parameter " + ", value = " + sSamplerStartNumber + ", set to 1"); 236 | samplerStartNumber = 1; 237 | } 238 | } 239 | if (samplerStartNumber <= 0) { 240 | samplerStartNumber = 1; 241 | } 242 | 243 | boolean isRemoveCookieHeader = isRemoveCookieCheckbox.isSelected(); 244 | boolean isRemoveCacheRequestHeader = isRemoveCacheRequestHeaderCheckbox.isSelected(); 245 | boolean isAddResultTreeRecord = isAddResultTreeRecordCheckbox.isSelected(); 246 | boolean isUseLrwrTransactionName = isUseLrwrTransactionNameCheckbox.isSelected(); 247 | boolean isWebSocketPDoornbosch = isWebSocketPDoornboschCheckbox.isSelected(); 248 | 249 | 250 | String lrwr_info = ""; 251 | if (isUseLrwrTransactionName) { 252 | lrwr_info = HarForJMeter.K_LRWR_USE_TRANSACTION_NAME; 253 | } 254 | 255 | try { 256 | btConvert.setEnabled(false); 257 | labelStatus.setText("Tool HAR Convert Running"); 258 | log.info("Before HarForJMeter.generateJmxAndRecord"); 259 | log.info("************* PARAMETERS ***************"); 260 | log.info("fileHarIn=<"+ fileHarIn + ">"); 261 | log.info("fileJmxOut=<" + fileJmxOut + ">"); 262 | log.info("recordXmlOut=<" + recordXmlOut + ">"); 263 | log.info("isAddResultTreeRecord=<" + isAddResultTreeRecord + ">"); 264 | log.info("isWebSocketPDoornbosch=<" + isWebSocketPDoornbosch + ">"); 265 | log.info("createNewTransactionAfterRequestMs=<" + createNewTransactionAfterRequestMs + ">"); 266 | log.info("isAddPause=<" + isAddPause + ">"); 267 | log.info("regexFilterInclude=<" + regexFilterInclude + ">"); 268 | log.info("regexFilterExclude=<" + regexFilterExclude + ">"); 269 | log.info("removeHeaders=<" + removeHeaders + ">"); 270 | log.info("isRemoveCookieHeader=<" + isRemoveCookieHeader + ">"); 271 | log.info("samplerStartNumber=<" + samplerStartNumber + ">"); 272 | log.info("samplerStartNumber=<" + samplerStartNumber + ">"); 273 | log.info("lrwr_info=<" + lrwr_info + ">"); 274 | log.info("externalFileInfoIn=<" + externalFileInfoIn + ">"); 275 | log.info("****************************************"); 276 | 277 | HarForJMeter.generateJmxAndRecord(fileHarIn, fileJmxOut,createNewTransactionAfterRequestMs,isAddPause, isRemoveCookieHeader, isRemoveCacheRequestHeader, 278 | regexFilterInclude, regexFilterExclude, recordXmlOut, pageStartNumber, samplerStartNumber, lrwr_info, externalFileInfoIn, 279 | isAddResultTreeRecord, isWebSocketPDoornbosch,removeHeaders); 280 | 281 | log.info("After HarForJMeter.generateJmxAndRecord"); 282 | btConvert.setEnabled(true); 283 | if (!recordXmlOut.isEmpty()) { 284 | labelStatus.setText("Tool HAR Convertor Finished OK, fileJmxOut=" + fileJmxOut + " AND recordXmlOut=" + recordXmlOut); 285 | } else { 286 | labelStatus.setText("Tool HAR Convertor Finished OK, fileJmxOut=" + fileJmxOut); 287 | } 288 | labelStatus.setForeground(java.awt.Color.BLACK); 289 | 290 | if (command.equals(ACTION_CONVERT_AND_LOAD_SCRIPT)) { 291 | // open the script generated in current JMeter 292 | final HashTree tree = SaveService.loadTree(new File(fileJmxOut)); 293 | org.apache.jmeter.gui.action.Load.insertLoadedTree(1,tree); 294 | } 295 | } catch (Exception e) { 296 | e.printStackTrace(); 297 | except = e; 298 | btConvert.setEnabled(true); 299 | btConvertAndLoad.setEnabled(true); 300 | labelStatus.setText("Tool HAR Convertor Finished KO, exception = " + e); 301 | labelStatus.setForeground(java.awt.Color.RED); 302 | } 303 | 304 | if (null == except) { 305 | btConvert.setEnabled(true); 306 | } 307 | } 308 | 309 | if (command.equals(BROWSE_HAR_IN)) { 310 | fileHarInTextField.setText(showFileChooser(fileHarInTextField.getParent(), 311 | fileHarInTextField, false, new String[] { ".har" })); 312 | labelStatus.setText("Waiting configuration ... "); 313 | labelStatus.setForeground(java.awt.Color.BLACK); 314 | } 315 | 316 | if (command.equals(BROWSE_JMX_OUT)) { 317 | fileJmxOutTextField.setText(showFileChooser(fileJmxOutTextField.getParent(), 318 | fileJmxOutTextField, false, new String[] { ".jmx" })); 319 | labelStatus.setText("Waiting configuration ... "); 320 | labelStatus.setForeground(java.awt.Color.BLACK); 321 | } 322 | 323 | if (command.equals(BROWSE_RECORD_OUT)) { 324 | fileRecordOutTextField.setText(showFileChooser(fileRecordOutTextField.getParent(), 325 | fileRecordOutTextField, false, new String[] { ".xml" })); 326 | labelStatus.setText("Waiting configuration ... "); 327 | labelStatus.setForeground(java.awt.Color.BLACK); 328 | } 329 | 330 | if (command.equals(BROWSE_EXTERNAL_FILE_IN)) { 331 | externalFileInfoInField.setText(showFileChooser(externalFileInfoInField.getParent(), 332 | externalFileInfoInField, false, new String[] { ".csv" })); 333 | labelStatus.setText("Waiting configuration ... "); 334 | labelStatus.setForeground(java.awt.Color.BLACK); 335 | } 336 | 337 | if (command.equals(ACTION_CHECKBOX_WEBSOCKET)) { 338 | boolean isWSChecked = isWebSocketPDoornboschCheckbox.isSelected(); 339 | if (isWSChecked) { 340 | try { 341 | // check if plugin "WebSocket Samplers by Peter Doornbosch" is present 342 | Class.forName("eu.luminis.jmeter.wssampler.WebsocketGeneralSampler"); 343 | log.info("plugin \"WebSocket Samplers by Peter Doornbosch\" is present"); 344 | } catch (ClassNotFoundException ex) { 345 | labelStatus.setText("You must install the plugin 'WebSocket Samplers by Peter Doornbosch' to open the JMeter generated script file"); 346 | labelStatus.setForeground(java.awt.Color.RED); 347 | btConvertAndLoad.setEnabled(false); 348 | } 349 | } else { 350 | labelStatus.setText("Waiting configuration ... "); 351 | labelStatus.setForeground(java.awt.Color.BLACK); 352 | btConvertAndLoad.setEnabled(true); 353 | } 354 | } 355 | } 356 | 357 | private JPanel createControls() { 358 | btConvert = new JButton("CONVERT"); 359 | btConvert.addActionListener(this); 360 | btConvert.setActionCommand(ACTION_CONVERT); 361 | btConvert.setEnabled(true); 362 | 363 | btConvertAndLoad = new JButton("CONVERT AND LOAD GENERATED SCRIPT"); 364 | btConvertAndLoad.addActionListener(this); 365 | btConvertAndLoad.setActionCommand(ACTION_CONVERT_AND_LOAD_SCRIPT); 366 | btConvertAndLoad.setEnabled(true); 367 | 368 | JPanel panel = new JPanel(); 369 | panel.add(btConvertAndLoad); 370 | panel.add(btConvert); 371 | return panel; 372 | } 373 | 374 | 375 | private JPanel createFilterAndPausePanel() { 376 | JPanel panel = new JPanel(new GridLayout(0, 2)); 377 | JLabel regexFilterIncludeLabel = new JLabel("(Optional) Regular expression matches for filter Include URL"); 378 | regexFilterIncludeField = new JTextField("", 80); 379 | 380 | JLabel regexFilterExcludeLabel = new JLabel("(Optional) Regular expression matches for filter Exclude URL"); 381 | regexFilterExcludeField = new JTextField("", 80); 382 | 383 | JLabel removeHeadersFieldLabel = new JLabel("(Optional) Remove Headers (comma separator case insensitive)"); 384 | removeHeadersField = new JTextField("", 80); 385 | 386 | JLabel pauseBetweenUrlLabel = new JLabel("(Optional) Time (ms) between 2 URLs to create a new page (Transaction Controller)"); 387 | pauseBetweenUrlTextField = new JTextField("5000", 80); 388 | 389 | JLabel pageStartNumberLabel = new JLabel("(Optional) Page start number usually for partial recording (default 1)"); 390 | pageStartNumberTextField = new JTextField("", 80); 391 | 392 | JLabel samplerStartNumberLabel = new JLabel("(Optional) Sampler start number usually for partial recording (default 1)"); 393 | samplerStartNumberTextField = new JTextField("", 80); 394 | 395 | panel.add(pauseBetweenUrlLabel); 396 | panel.add(pauseBetweenUrlTextField); 397 | 398 | panel.add(pageStartNumberLabel); 399 | panel.add(pageStartNumberTextField); 400 | 401 | panel.add(samplerStartNumberLabel); 402 | panel.add(samplerStartNumberTextField); 403 | 404 | panel.add(regexFilterIncludeLabel); 405 | panel.add(regexFilterIncludeField); 406 | 407 | panel.add(regexFilterExcludeLabel); 408 | panel.add(regexFilterExcludeField); 409 | 410 | panel.add(removeHeadersFieldLabel); 411 | panel.add(removeHeadersField); 412 | 413 | return panel; 414 | } 415 | 416 | private JPanel createCheckbox() { 417 | JPanel panel = new JPanel(new GridLayout(0, 2)); 418 | 419 | JLabel isWebSocketPDoornboschLabel = new JLabel("(Optional) Create WebSocket Sampler if HAR contains WebSocket Connection (default false)"); 420 | isWebSocketPDoornboschCheckbox= new JCheckBox("",false); 421 | isWebSocketPDoornboschCheckbox.addActionListener(this); 422 | isWebSocketPDoornboschCheckbox.setActionCommand(ACTION_CHECKBOX_WEBSOCKET); 423 | isWebSocketPDoornboschCheckbox.setEnabled(true); 424 | 425 | JLabel isAddPauseLabel = new JLabel("(Optional) Add a pause between Transaction Controller (default true), time between 2 URLs must be > 0"); 426 | isAddPauseCheckbox= new JCheckBox("",true); 427 | 428 | JLabel isRemoveCookieLabel = new JLabel("(Optional) Remove cookie in http header (default true because add a Cookie Manager)"); 429 | isRemoveCookieCheckbox= new JCheckBox("",true); 430 | 431 | JLabel isRemoveCacheHeaderLabel = new JLabel("(Optional) Remove cache header in the http request (default true because add a Cache Manager)"); 432 | isRemoveCacheRequestHeaderCheckbox= new JCheckBox("",true); 433 | 434 | JLabel isAddResultTreeRecordLabel = new JLabel("(Optional) Add 'View Result Tree' to view the recording xml file created (default true)"); 435 | isAddResultTreeRecordCheckbox= new JCheckBox("",true); 436 | 437 | JLabel isUseLrwrTransactionNameLabel = new JLabel("(Optional) HAR was generated with LoadRunner Web Recorder and Transaction Names (default false)"); 438 | isUseLrwrTransactionNameCheckbox= new JCheckBox("",false); 439 | 440 | panel.add(isWebSocketPDoornboschLabel); 441 | panel.add(isWebSocketPDoornboschCheckbox); 442 | 443 | panel.add(isAddPauseLabel); 444 | panel.add(isAddPauseCheckbox); 445 | 446 | panel.add(isRemoveCookieLabel); 447 | panel.add(isRemoveCookieCheckbox); 448 | 449 | panel.add(isRemoveCacheHeaderLabel); 450 | panel.add(isRemoveCacheRequestHeaderCheckbox); 451 | 452 | panel.add(isAddResultTreeRecordLabel); 453 | panel.add(isAddResultTreeRecordCheckbox); 454 | 455 | panel.add(isUseLrwrTransactionNameLabel); 456 | panel.add(isUseLrwrTransactionNameCheckbox); 457 | 458 | return panel; 459 | } 460 | 461 | private JPanel setupFileChooserPanel() { 462 | JPanel fileChooserPanel = new JPanel(new GridLayout(0, 3)); 463 | fileChooserPanel.add(new JLabel("HAR file in (to read) : ")); 464 | 465 | fileHarInTextField = new JTextField(); 466 | fileChooserPanel.add(fileHarInTextField); 467 | 468 | this.fileHarInFileButton = new JButton("Browse ..."); 469 | fileHarInFileButton.setActionCommand(BROWSE_HAR_IN); 470 | fileHarInFileButton.addActionListener(this); 471 | fileChooserPanel.add(fileHarInFileButton); 472 | 473 | fileChooserPanel.add(new JLabel("JMeter script out (to write) (if empty default .jmx) : ")); 474 | 475 | fileJmxOutTextField = new JTextField(); 476 | fileChooserPanel.add(fileJmxOutTextField); 477 | 478 | this.fileJmxOutFileButton = new JButton("Browse ..."); 479 | fileJmxOutFileButton.setActionCommand(BROWSE_JMX_OUT); 480 | fileJmxOutFileButton.addActionListener(this); 481 | fileChooserPanel.add(fileJmxOutFileButton); 482 | 483 | 484 | fileChooserPanel.add(new JLabel("(Optional) Record XML out (to write) : ")); 485 | fileRecordOutTextField = new JTextField(); 486 | fileChooserPanel.add(fileRecordOutTextField); 487 | 488 | this.fileRecordOutFileButton = new JButton("Browse ..."); 489 | fileRecordOutFileButton.setActionCommand(BROWSE_RECORD_OUT); 490 | fileRecordOutFileButton.addActionListener(this); 491 | fileChooserPanel.add(fileRecordOutFileButton); 492 | 493 | fileChooserPanel.add(new JLabel("(Optional) External csv file with transaction info (to read) : ")); 494 | externalFileInfoInField= new JTextField(); 495 | fileChooserPanel.add(externalFileInfoInField); 496 | 497 | this.externalFileInfoInButton = new JButton("Browse ..."); 498 | externalFileInfoInButton.setActionCommand(BROWSE_EXTERNAL_FILE_IN); 499 | externalFileInfoInButton.addActionListener(this); 500 | fileChooserPanel.add(externalFileInfoInButton); 501 | 502 | return fileChooserPanel; 503 | } 504 | 505 | /** 506 | * Show a file chooser to the user 507 | * 508 | * @param locationTextField 509 | * the textField that will receive the path 510 | * @param onlyDirectory 511 | * whether or not the file chooser will only display directories or Files only 512 | * @param extensions File extensions to filter 513 | * @return the path the user selected or, if the user cancelled the file 514 | * chooser, the previous path 515 | */ 516 | private String showFileChooser(Component component, JTextField locationTextField, boolean onlyDirectory, String[] extensions) { 517 | JFileChooser jfc = new JFileChooser(); 518 | if (onlyDirectory) { 519 | jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); 520 | } else { 521 | jfc.setFileSelectionMode(JFileChooser.FILES_ONLY); 522 | } 523 | if(extensions != null && extensions.length > 0) { 524 | JMeterFileFilter currentFilter = new JMeterFileFilter(extensions); 525 | jfc.addChoosableFileFilter(currentFilter); 526 | jfc.setAcceptAllFileFilterUsed(true); 527 | jfc.setFileFilter(currentFilter); 528 | } 529 | if (lastJFCDirectory != null) { 530 | jfc.setCurrentDirectory(new File(lastJFCDirectory)); 531 | } else { 532 | String start = System.getProperty("user.dir", ""); //$NON-NLS-1$//$NON-NLS-2$ 533 | if (!start.isEmpty()) { 534 | jfc.setCurrentDirectory(new File(start)); 535 | } 536 | } 537 | int retVal = jfc.showOpenDialog(component); 538 | if (retVal == JFileChooser.APPROVE_OPTION) { 539 | lastJFCDirectory = jfc.getCurrentDirectory().getAbsolutePath(); 540 | return jfc.getSelectedFile().getPath(); 541 | } else { 542 | return locationTextField.getText(); 543 | } 544 | } 545 | 546 | @Override 547 | public JMenuItem[] getMenuItemsAtLocation(MENU_LOCATION location) { 548 | if (location != MENU_LOCATION.TOOLS) { 549 | return new JMenuItem[0]; 550 | } 551 | 552 | JMenuItem menuItem = new JMenuItem("vdn@github - HAR Convertor Tool", null); 553 | menuItem.setName("HAR Convertor Tool"); 554 | menuItem.setActionCommand(ACTION_MENU_TOOL); 555 | menuItem.setAccelerator(null); 556 | menuItem.addActionListener(this); 557 | return new JMenuItem[] { menuItem }; 558 | } 559 | 560 | @Override 561 | public JMenu[] getTopLevelMenus() { 562 | return new JMenu[0]; 563 | } 564 | 565 | @Override 566 | public void localeChanged() { 567 | // NOOP 568 | 569 | } 570 | 571 | @Override 572 | public boolean localeChanged(MenuElement arg0) { 573 | return false; 574 | } 575 | 576 | 577 | @Override 578 | public Set getActionNames() { 579 | return commands; 580 | } 581 | } 582 | --------------------------------------------------------------------------------