├── .gitignore ├── DEBUG.md ├── LICENSE ├── LICENSES.md ├── MANUAL.md ├── PRE_REQUISITES.md ├── README.md ├── RELEASE-NOTES.md ├── SETUP.md ├── TROUBLESHOOTING.md ├── checkstyle.xml ├── citrix-client-win ├── .gitignore ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── blazemeter │ └── jmeter │ └── citrix │ └── client │ └── windows │ ├── KeyEvent.java │ ├── MouseEvent.java │ ├── WinCitrixClient.java │ ├── WinCitrixClientFactory.java │ ├── com4j │ ├── ClassFactory.java │ ├── ICAColorDepth.java │ ├── ICAEvent.java │ ├── ICAScalingMode.java │ ├── ICASessionCounter.java │ ├── ICASessionEndAction.java │ ├── ICASessionString.java │ ├── ICASoundQuality.java │ ├── ICAVCDataType.java │ ├── ICAWindowType.java │ ├── IICAClient.java │ ├── IKeyboard.java │ ├── IMouse.java │ ├── IScreenShot.java │ ├── ISession.java │ ├── IWindow.java │ ├── IWindows.java │ ├── KeyModifier.java │ ├── MouseButton.java │ ├── OutputMode.java │ ├── WindowExStyle.java │ ├── WindowStyle.java │ ├── events │ │ ├── _IICAClientEvents.java │ │ ├── _IKeyboardEvents.java │ │ ├── _IMouseEvents.java │ │ ├── _IScreenShotEvents.java │ │ ├── _ISessionEvents.java │ │ └── _IWindowEvents.java │ └── package.html │ └── events │ ├── ICAClientAdapter.java │ ├── KeyboardAdapter.java │ ├── MouseAdapter.java │ ├── SessionAdapter.java │ └── WindowAdapter.java ├── citrix-common ├── .gitignore ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── blazemeter │ └── jmeter │ └── citrix │ └── client │ ├── AbstractCitrixClient.java │ ├── CitrixClient.java │ ├── CitrixClientException.java │ ├── Win32Utils.java │ ├── WindowInfo.java │ ├── events │ ├── ClientEvent.java │ ├── EventHelper.java │ ├── EventInfo.java │ ├── InteractionEvent.java │ ├── Modifier.java │ ├── MouseButton.java │ ├── SessionEvent.java │ └── WindowEvent.java │ ├── factory │ ├── AbstractCitrixClientFactory.java │ └── CitrixClientFactory.java │ └── handler │ ├── CitrixClientAdapter.java │ ├── CitrixClientHandler.java │ └── CitrixClientHandlerException.java ├── citrix-jmeter ├── .gitignore ├── plugin-metadata │ ├── descriptor-test.json │ ├── descriptor.json │ └── presentationScreenshot.png ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── blazemeter │ │ │ └── jmeter │ │ │ └── citrix │ │ │ ├── assertion │ │ │ ├── CitrixAssertion.java │ │ │ ├── CitrixSessionAssertion.java │ │ │ └── gui │ │ │ │ ├── CitrixAssertionGUI.java │ │ │ │ └── CitrixSessionAssertionGui.java │ │ │ ├── clause │ │ │ ├── CheckResult.java │ │ │ ├── CheckType.java │ │ │ ├── Clause.java │ │ │ ├── ClauseComputationException.java │ │ │ ├── ClauseHelper.java │ │ │ ├── SessionState.java │ │ │ ├── gui │ │ │ │ ├── ClauseBuilderPanel.java │ │ │ │ └── ClausePanel.java │ │ │ └── strategy │ │ │ │ ├── check │ │ │ │ ├── AbstractScreenChecker.java │ │ │ │ ├── CheckStrategy.java │ │ │ │ ├── ClientChecker.java │ │ │ │ ├── DiffChecker.java │ │ │ │ ├── DirectChecker.java │ │ │ │ ├── ListeningStrategy.java │ │ │ │ ├── PollingContext.java │ │ │ │ ├── PollingStrategy.java │ │ │ │ ├── ScreenshotAssessor.java │ │ │ │ └── SnapshotChecker.java │ │ │ │ └── format │ │ │ │ ├── AssessmentFormatter.java │ │ │ │ ├── DiffResultFormatter.java │ │ │ │ ├── RegularAssessmentFormatter.java │ │ │ │ ├── RegularResultFormatter.java │ │ │ │ ├── ResultFormatter.java │ │ │ │ ├── WindowEventAssessmentFormatter.java │ │ │ │ └── WindowEventResultFormatter.java │ │ │ ├── client │ │ │ ├── CitrixClientFactoryException.java │ │ │ ├── CitrixClientFactoryHelper.java │ │ │ └── SessionErrorLogger.java │ │ │ ├── extractor │ │ │ ├── AssessmentExtractor.java │ │ │ ├── OCRExtractor.java │ │ │ └── gui │ │ │ │ ├── AssessmentExtractorGUI.java │ │ │ │ └── OCRExtractorGUI.java │ │ │ ├── gui │ │ │ ├── AreaChangedEvent.java │ │ │ ├── BlazeMeterLabsLogo.java │ │ │ ├── CitrixResultRenderer.java │ │ │ ├── DimensionPanel.java │ │ │ ├── GuiHelper.java │ │ │ ├── ImagePanel.java │ │ │ ├── PositionPanel.java │ │ │ ├── SelectionChangedListener.java │ │ │ ├── SelectionChangedManager.java │ │ │ ├── SelectionChangedSubject.java │ │ │ └── SelectionPanel.java │ │ │ ├── installer │ │ │ ├── CitrixInstaller.java │ │ │ ├── StreamGobbler.java │ │ │ └── WinRegistry.java │ │ │ ├── listener │ │ │ ├── CitrixIcaFileSaver.java │ │ │ └── gui │ │ │ │ └── CitrixIcaFileSaverGui.java │ │ │ ├── ocr │ │ │ ├── OcrException.java │ │ │ ├── OcrManager.java │ │ │ └── OcrManagerHolder.java │ │ │ ├── recorder │ │ │ ├── Capture.java │ │ │ ├── CaptureItem.java │ │ │ ├── CaptureLimitException.java │ │ │ ├── CitrixRecorder.java │ │ │ ├── RecordingCitrixIcaFileSaver.java │ │ │ ├── RecordingHandler.java │ │ │ ├── TreeClonerForICADownloading.java │ │ │ └── gui │ │ │ │ ├── ActionItem.java │ │ │ │ ├── ActionItemRenderer.java │ │ │ │ ├── BasePanel.java │ │ │ │ ├── BoundsPopupMenuListener.java │ │ │ │ ├── BrowseFile.java │ │ │ │ ├── CapturePanel.java │ │ │ │ ├── CitrixRecorderGUI.java │ │ │ │ ├── ConfigurationPanel.java │ │ │ │ ├── DownloadingControllerCellRenderer.java │ │ │ │ ├── DownloadingControllerTreeSelectionModel.java │ │ │ │ ├── PageViewer.java │ │ │ │ ├── RecorderDialog.java │ │ │ │ ├── ResultNodeRenderer.java │ │ │ │ ├── TemplateUpdater.java │ │ │ │ └── workers │ │ │ │ ├── DownloadIcaWorker.java │ │ │ │ ├── MonitorRecordingWorker.java │ │ │ │ ├── StartRecordingWorker.java │ │ │ │ ├── StopRecordingWorker.java │ │ │ │ └── WaitCaptureWorker.java │ │ │ ├── sampler │ │ │ ├── CitrixBaseSampler.java │ │ │ ├── CitrixSampleResult.java │ │ │ ├── CitrixSampleResultConverter.java │ │ │ ├── CitrixSessionHolder.java │ │ │ ├── InteractionSampler.java │ │ │ ├── KeySequenceItem.java │ │ │ ├── MouseSequenceItem.java │ │ │ ├── SamplerHelper.java │ │ │ ├── SamplerResultHelper.java │ │ │ ├── SamplerRunException.java │ │ │ ├── SamplerType.java │ │ │ ├── StartApplicationSampler.java │ │ │ └── gui │ │ │ │ ├── CitrixSamplerGUI.java │ │ │ │ ├── InteractionSamplerGUI.java │ │ │ │ ├── KeySequenceModel.java │ │ │ │ ├── LineNumberTableModel.java │ │ │ │ ├── ModifiersPanel.java │ │ │ │ ├── MouseButtonsPanel.java │ │ │ │ ├── MouseSequenceModel.java │ │ │ │ └── StartApplicationSamplerGUI.java │ │ │ └── utils │ │ │ ├── CitrixUtils.java │ │ │ ├── DialogHelper.java │ │ │ ├── EnumHelper.java │ │ │ └── TestPlanHelper.java │ └── resources │ │ ├── com │ │ └── blazemeter │ │ │ ├── jmeter │ │ │ └── citrix │ │ │ │ ├── cursors │ │ │ │ └── dnd_clause.png │ │ │ │ ├── installer │ │ │ │ └── saveservice-excerpt.properties │ │ │ │ ├── resources │ │ │ │ └── messages.properties │ │ │ │ └── template │ │ │ │ ├── bzmCitrixTemplate.xml │ │ │ │ ├── bzmCitrixTemplateWithParameters.xml │ │ │ │ ├── citrixRecordingTemplate.jmx │ │ │ │ └── citrixRecordingTemplateWithParameters.jmx │ │ │ └── labs-logo │ │ │ ├── blazemeter-labs-light-logo.png │ │ │ └── blazemeter-labs-logo.png │ │ ├── dark-theme │ │ ├── add_action.png │ │ ├── discard.png │ │ ├── full_screenshot.png │ │ ├── selection_screenshot.png │ │ └── text_ocr.png │ │ └── light-theme │ │ ├── add_action.png │ │ ├── discard.png │ │ ├── full_screenshot.png │ │ ├── selection_screenshot.png │ │ └── text_ocr.png │ └── test │ ├── java │ └── com │ │ └── blazemeter │ │ └── jmeter │ │ └── citrix │ │ ├── assertions │ │ └── TestAssertionHelper.java │ │ ├── installer │ │ └── WinRegistryTest.java │ │ ├── recorder │ │ └── gui │ │ │ ├── CapturePanelTest.java │ │ │ ├── CitrixRecorderGUITest.java │ │ │ ├── JUnitJMeter.java │ │ │ └── SwingTestRunner.java │ │ └── sampler │ │ ├── InteractionSamplerTest.java │ │ └── SampleHelperTest.java │ └── resources │ ├── 4328_1536568867580.png │ ├── 4328_1536568879467.png │ ├── citrixRecord.xml │ ├── hash_not_same_01.png │ ├── hash_not_same_02.png │ ├── hash_same_01.png │ ├── hash_same_02.png │ ├── jmeter.properties │ ├── log4j2.xml │ ├── messages.properties │ └── zipFile.zip ├── config ├── citrix.properties ├── saveservice-excerpt.properties ├── setup-x64.reg └── setup-x86.reg ├── images ├── app_started_sampler_step.png ├── app_started_window.png ├── assertion_creation_using_step.png ├── citrix_assertion.png ├── citrix_assessment_extractor.png ├── citrix_close.png ├── citrix_interaction_informations.png ├── citrix_ocr_extractor.png ├── citrix_recorder_configuration.png ├── citrix_recording_template.png ├── csv_data_set_config.png ├── csv_data_set_config_data_sample.png ├── debug_jtl_configure_detailed.png ├── download_ica.png ├── dwm_settings.png ├── end_clause.png ├── example_plan.png ├── ica_file_saver.png ├── input_text_sampler.png ├── launcher_sampler.png ├── navigate_to_save.png ├── no_scaling_settings.png ├── notepad_citrix_example.png ├── playback_view_results_tree.png ├── playback_view_results_tree_request_tab.png ├── playback_view_results_tree_response_data_tab.png ├── recorder.png ├── recorder_status_started.png ├── recording_panel.png ├── save_popup.png ├── session_state_assertion.png ├── start_button.png ├── stop_recording_button.png ├── template_test_plan.png ├── thread_group_config.png ├── updates_settings.png ├── vrt_citrix_renderer.png ├── vrt_citrix_renderer_selection.png ├── vrt_display_sample.png ├── vrt_saving_recording.png └── windows_balck_screen_issue.png └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | .settings/ 2 | .classpath 3 | .project 4 | target/ 5 | /jmeter-files/recordings/ 6 | 7 | ### Intellij+iml ### 8 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 9 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 10 | 11 | # User-specific stuff 12 | .idea/**/workspace.xml 13 | .idea/**/tasks.xml 14 | .idea/**/usage.statistics.xml 15 | .idea/**/dictionaries 16 | .idea/**/shelf 17 | .idea/**/vcs.xml 18 | 19 | # Generated files 20 | .idea/**/contentModel.xml 21 | 22 | # Sensitive or high-churn files 23 | .idea/**/dataSources/ 24 | .idea/**/dataSources.ids 25 | .idea/**/dataSources.local.xml 26 | .idea/**/sqlDataSources.xml 27 | .idea/**/dynamic.xml 28 | .idea/**/uiDesigner.xml 29 | .idea/**/dbnavigator.xml 30 | 31 | # Gradle 32 | .idea/**/gradle.xml 33 | .idea/**/libraries 34 | 35 | # Gradle and Maven with auto-import 36 | # When using Gradle or Maven with auto-import, you should exclude module files, 37 | # since they will be recreated, and may cause churn. Uncomment if using 38 | # auto-import. 39 | # .idea/artifacts 40 | # .idea/compiler.xml 41 | # .idea/jarRepositories.xml 42 | # .idea/modules.xml 43 | # .idea/*.iml 44 | # .idea/modules 45 | # *.iml 46 | # *.ipr 47 | 48 | # CMake 49 | cmake-build-*/ 50 | 51 | # Mongo Explorer plugin 52 | .idea/**/mongoSettings.xml 53 | 54 | # File-based project format 55 | *.iws 56 | 57 | # IntelliJ 58 | out/ 59 | 60 | # mpeltonen/sbt-idea plugin 61 | .idea_modules/ 62 | 63 | # JIRA plugin 64 | atlassian-ide-plugin.xml 65 | 66 | # Cursive Clojure plugin 67 | .idea/replstate.xml 68 | 69 | # Crashlytics plugin (for Android Studio and IntelliJ) 70 | com_crashlytics_export_strings.xml 71 | crashlytics.properties 72 | crashlytics-build.properties 73 | fabric.properties 74 | 75 | # Editor-based Rest Client 76 | .idea/httpRequests 77 | 78 | # Android studio 3.1+ serialized cache file 79 | .idea/caches/build_file_checksums.ser 80 | 81 | ### Intellij+iml Patch ### 82 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 83 | 84 | *.iml 85 | modules.xml 86 | .idea/misc.xml 87 | *.ipr 88 | .idea/jarRepositories.xml 89 | .idea/encodings.xml 90 | .idea/compiler.xml 91 | .idea/codeStyles/codeStyleConfig.xml 92 | .idea/checkstyleidea-libs/readme.txt 93 | .idea/checkstyle-idea.xml 94 | .idea/sonarlint/ 95 | *.log 96 | citrix-jmeter/.DS_Store 97 | -------------------------------------------------------------------------------- /DEBUG.md: -------------------------------------------------------------------------------- 1 | ## Enable Citrix debug log 2 | 3 | To enable the maximum level of debugging, a debugging setting must be incorporated in the log4j2 configuration file. 4 | 5 | In the log4j2.xml file inside the JMeter bin folder, insert the following line inside the `` clause. 6 | 7 | ```xml 8 | 9 | ``` 10 | 11 | Alternatively it can be activated when starting JMeter indicating the log level by argument 12 | 13 | ``` 14 | jmeter -Lcom.blazemeter.jmeter.citrix=DEBUG 15 | ``` 16 | 17 | ## Enable thread trace on JMeter log files 18 | 19 | In the JMeter default log configuration, it's not possible to associate each line to which virtual user generate that line. 20 | To achieve this, the thread identifier must be incorporated into the log pattern. 21 | 22 | In the log4j2.xml file inside the JMeter bin folder. 23 | Locate and update the text inside the `` tag incorporating the thread name `%t` and thread identifier `%tid` between the values `%d` and `%p`. 24 | 25 | Example: 26 | ``` 27 | 28 | 29 | %d [%t id:%tid] %p %c{1.}: %m%n 30 | 31 | 32 | 33 | 34 | %d [%t id:%tid] %p %c{1.}: %m%n 35 | 36 | 37 | ... 38 | ``` 39 | 40 | ## Enable Write results to file on View Results Tree listener 41 | 42 | The View Results Tree listener by default records all operations and show it on the graphic interface. 43 | To share the results for debugging using a `JMeter Text Log (JTL)` file, you must previously enable to write JTL file and set the maximum possible verbosity to ensure all data needed inside the file. 44 | 45 | To enable JTL file saving, in the `filename` field provide the name of the xml file where the log information will be stored. 46 | 47 | To ensure maximum verbosity, **make sure** that the configuration section contains all activated options. Go to `Configure` and check them all. 48 | 49 | The default Citrix Plugin template provides a View Results Tree listener for the main playback thread group as well as one inside Citrix Recorder. 50 | If your test project does not have a View Results Tree listener, you can add one in order to allow saving a JTL file for debugging purpose. 51 | 52 | 53 | ## Save JMeter console output in a log file 54 | 55 | There are JMeter-level operations that emit debug information outside of the log4j2 logging system. 56 | In order to capture this output, the JMeter output must be redirected to a log file. 57 | 58 | To be able to do it, you must run JMeter from command line incorporating at the end the redirection to a file 59 | 60 | Example: 61 | ``` 62 | jmeter >jmeter-console.log 2>&1 63 | ``` 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /LICENSES.md: -------------------------------------------------------------------------------- 1 | # Licenses used: 2 | 3 | ## Drag and drop icon by ChangHoon Baek from the Noun Project 4 | 5 | * https://creativecommons.org/licenses/by/3.0/us/legalcode 6 | 7 | ## OCR recognition : Tesseract OCR engine with Tess4J JNA wrapper 8 | 9 | * Apache License, v2.0 (http://www.apache.org/licenses/LICENSE-2.0.html) 10 | 11 | ## COM4J License: 12 | 13 | * BSD 2-Clause "Simplified" License (https://github.com/kohsuke/com4j/blob/master/LICENSE.txt) 14 | 15 | 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JMeter-Citrix-plugin 2 | 3 | [![License](http://img.shields.io/:license-apache-brightgreen.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) 4 | ![Build Status](https://github.com/abstracta/CitrixPlugin/workflows/build/badge.svg?branch=master) 5 | 6 | This JMeter plugin enable load-testing Citrix XenApp exposed applications. 7 | 8 | When working with this plugin, there will be 2 phases: 9 | 10 | * The recording of the Citrix application 11 | * The sampling of the created test plan 12 | 13 | At the end of sampling, you can check the results in regular JMeter listeners. 14 | 15 | --- 16 | ## Citrix Server and Client supported 17 | 18 | Information about Citrix server and client versions supported in [System requirements and compatibility](PRE_REQUISITES.md#system-requirements-and-compatibility) 19 | 20 | ## Setup 21 | 22 | Before the installation, please follow the instructions in [Pre-Requisites](PRE_REQUISITES.md) 23 | 24 | When requirements have been satisfied, follow the instructions mentioned in [Setup](SETUP.md) 25 | 26 | ## Getting Started 27 | 28 | After installing the plugin, you can start by doing your first recording and test run 29 | 30 | You can start reading [Getting Started](MANUAL.md) in the user manual. 31 | 32 | ## Troubleshooting and Support 33 | 34 | If you face any errors or problems, you can find information on the page [Troubleshooting](TROUBLESHOOTING.md) 35 | 36 | To get support of this plugin, use [JMeter Plugins support forums](https://groups.google.com/forum/#!forum/jmeter-plugins) 37 | 38 | -------------------------------------------------------------------------------- /citrix-client-win/.gitignore: -------------------------------------------------------------------------------- 1 | .project 2 | .classpath 3 | target 4 | -------------------------------------------------------------------------------- /citrix-client-win/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 4.0.0 7 | 8 | com.blazemeter.jmeter 9 | citrix-parent 10 | 0.7.7 11 | 12 | citrix-client-win 13 | 14 | 15 | 16 | ${project.parent.groupId} 17 | citrix-common 18 | ${project.parent.version} 19 | provided 20 | 21 | 22 | 23 | org.jvnet.com4j 24 | com4j 25 | 2.1 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | org.apache.maven.plugins 34 | maven-javadoc-plugin 35 | 3.3.1 36 | 37 | 8 38 | com.blazemeter.jmeter.citrix.client.windows.com4j:com.blazemeter.jmeter.citrix.client.windows.com4j.* 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/KeyEvent.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows; 2 | 3 | /** 4 | * Provides Windows specific key event. 5 | */ 6 | public class KeyEvent { 7 | private final int keyId; 8 | 9 | /** 10 | * Instantiates a new {@link KeyEvent}. 11 | * 12 | * @param keyId the key identifier 13 | */ 14 | public KeyEvent(int keyId) { 15 | this.keyId = keyId; 16 | } 17 | 18 | /** 19 | * Gets the key identifier of this event. 20 | * 21 | * @return the key identifier 22 | */ 23 | public final int getKeyId() { 24 | return keyId; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/MouseEvent.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows; 2 | 3 | /** 4 | * Provides Windows specific mouse events. 5 | */ 6 | public class MouseEvent { 7 | 8 | private final int buttonId; 9 | private final int modifiers; 10 | private final int xPos; 11 | private final int yPos; 12 | 13 | /** 14 | * Instantiates a new {@link MouseEvent}. 15 | * 16 | * @param buttonId the mouse button identifier 17 | * @param modifiers the modifiers flags 18 | * @param xPos the mouse cursor horizontal position 19 | * @param yPos the mouse cursor vertical position 20 | */ 21 | public MouseEvent(int buttonId, int modifiers, int xPos, int yPos) { 22 | this.buttonId = buttonId; 23 | this.modifiers = modifiers; 24 | this.xPos = xPos; 25 | this.yPos = yPos; 26 | } 27 | 28 | /** 29 | * Gets the mouse button identifier. 30 | * 31 | * @return the mouse button identifier 32 | */ 33 | public int getButtonId() { 34 | return buttonId; 35 | } 36 | 37 | /** 38 | * Gets the modifiers flags. 39 | * 40 | * @return the modifiers flags 41 | */ 42 | public int getModifiers() { 43 | return modifiers; 44 | } 45 | 46 | /** 47 | * Gets the mouse cursor horizontal position. 48 | * 49 | * @return the mouse cursor horizontal position 50 | */ 51 | public int getXPos() { 52 | return xPos; 53 | } 54 | 55 | /** 56 | * Gets the mouse cursor vertical position. 57 | * 58 | * @return the mouse cursor vertical position 59 | */ 60 | public int getYPos() { 61 | return yPos; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/WinCitrixClientFactory.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows; 2 | 3 | import com.blazemeter.jmeter.citrix.client.CitrixClient; 4 | import com.blazemeter.jmeter.citrix.client.factory.AbstractCitrixClientFactory; 5 | import com.blazemeter.jmeter.citrix.client.windows.com4j.ICAColorDepth; 6 | 7 | public class WinCitrixClientFactory extends AbstractCitrixClientFactory { 8 | 9 | private static final String SCREENSHOT_DIR_PROPERTY = "screenshots_dir"; 10 | private static final String KEEP_SCREENSHOTS_PROPERTY = "keep_screenshots"; 11 | private static final String HORIZONTAL_RESOLUTION_PROPERTY = "horizontal_resolution"; 12 | private static final String VERTICAL_RESOLUTION_PROPERTY = "vertical_resolution"; 13 | private static final String COLOR_DEPTH_PROPERTY = "color_depth"; 14 | private static final String SCALING_PROPERTY = "scaling"; 15 | 16 | private static final String ICAFILE_TIMEOUT = "icafile_timeout_ms"; 17 | private static final String CONNECT_TIMEOUT = "connect_timeout_ms"; 18 | private static final String ACTIVEAPP_TIMEOUT = "activeapp_timeout_ms"; 19 | private static final String LOGON_TIMEOUT = "logon_timeout_ms"; 20 | private static final String LOGOFF_TIMEOUT = "logoff_timeout_ms"; 21 | private static final String DISCONNECT_TIMEOUT = "disconnect_timeout_ms"; 22 | private static final String SOCKET_TIMEOUT = "socket_timeout_ms"; 23 | 24 | @Override 25 | public CitrixClient createClient() { 26 | WinCitrixClient client = new WinCitrixClient(); 27 | 28 | // Configure client using properties map 29 | 30 | client.setScreenshotDirectory(getClientProperty(SCREENSHOT_DIR_PROPERTY)); 31 | client.setKeepingScreenshots( 32 | Boolean.parseBoolean(getClientProperty(KEEP_SCREENSHOTS_PROPERTY)) 33 | ); 34 | client.setICAFileTimeoutInMs( 35 | getClientPropertyAsLong(ICAFILE_TIMEOUT, client.getICAFileTimeoutInMs()) 36 | ); 37 | client.setConnectTimeoutInMs( 38 | getClientPropertyAsLong(CONNECT_TIMEOUT, client.getConnectTimeoutInMs()) 39 | ); 40 | client.setActiveAppTimeoutInMs( 41 | getClientPropertyAsLong(ACTIVEAPP_TIMEOUT, client.getActiveAppTimeoutInMs()) 42 | ); 43 | client.setLogonTimeoutInMs( 44 | getClientPropertyAsLong(LOGON_TIMEOUT, client.getLogonTimeoutInMs()) 45 | ); 46 | client.setLogoffTimeoutInMs( 47 | getClientPropertyAsLong(LOGOFF_TIMEOUT, client.getLogoffTimeoutInMs()) 48 | ); 49 | client.setDisconnectTimeoutInMs( 50 | getClientPropertyAsLong(DISCONNECT_TIMEOUT, client.getDisconnectTimeoutInMs()) 51 | ); 52 | client.setSocketTimeoutInMs( 53 | getClientPropertyAsLong(SOCKET_TIMEOUT, client.getSocketTimeoutInMs()) 54 | ); 55 | 56 | // Force desired HRes or VRes only when is defined in property 57 | if (!getClientProperty(HORIZONTAL_RESOLUTION_PROPERTY).isEmpty()) { 58 | client.setDesiredHRes(getClientPropertyAsInteger(HORIZONTAL_RESOLUTION_PROPERTY)); 59 | } 60 | if (!getClientProperty(VERTICAL_RESOLUTION_PROPERTY).isEmpty()) { 61 | client.setDesiredVRes(getClientPropertyAsInteger(VERTICAL_RESOLUTION_PROPERTY)); 62 | } 63 | 64 | // Force color depth only when is defined in property 65 | if (!getClientProperty(COLOR_DEPTH_PROPERTY).isEmpty()) { 66 | client.setDesiredColorDepth( 67 | Enum.valueOf(ICAColorDepth.class, getClientProperty(COLOR_DEPTH_PROPERTY)) 68 | ); 69 | } 70 | 71 | if (!getClientProperty(SCALING_PROPERTY).isEmpty()) { 72 | client.setScalingEnabled( 73 | Boolean.parseBoolean(getClientProperty(SCALING_PROPERTY)) 74 | ); 75 | } 76 | 77 | return client; 78 | } 79 | } 80 | 81 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/com4j/ClassFactory.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows.com4j; 2 | 3 | import com4j.COM4J; 4 | import com4j.Com4jObject; 5 | 6 | /** 7 | * Defines methods to create COM objects. 8 | */ 9 | public abstract class ClassFactory { 10 | private ClassFactory() { 11 | } // instanciation is not allowed 12 | 13 | 14 | /** 15 | * Citrix ICA Client. 16 | */ 17 | public static com.blazemeter.jmeter.citrix.client.windows.com4j.IICAClient createICAClient() { 18 | return COM4J.createInstance(com.blazemeter.jmeter.citrix.client.windows.com4j.IICAClient.class, 19 | "{238F6F83-B8B4-11CF-8771-00A024541EE3}"); 20 | } 21 | 22 | /** 23 | * ICA Client Properties. 24 | */ 25 | public static Com4jObject createICAClientProp() { 26 | return COM4J.createInstance(Com4jObject.class, "{238F6F85-B8B4-11CF-8771-00A024541EE3}"); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/com4j/ICAColorDepth.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows.com4j; 2 | 3 | import com4j.ComEnum; 4 | 5 | /** 6 | *

7 | * List of ICA color depths. 8 | *

9 | */ 10 | public enum ICAColorDepth implements ComEnum { 11 | /** 12 | *

13 | * The value of this constant is 1. 14 | *

15 | */ 16 | Color16(1), //NOSONAR 17 | /** 18 | *

19 | * The value of this constant is 2. 20 | *

21 | */ 22 | Color256(2), //NOSONAR 23 | /** 24 | *

25 | * The value of this constant is 4. 26 | *

27 | */ 28 | Color16Bit(4), //NOSONAR 29 | /** 30 | *

31 | * The value of this constant is 8. 32 | *

33 | */ 34 | Color24Bit(8); //NOSONAR 35 | 36 | private final int value; 37 | 38 | ICAColorDepth(int value) { 39 | this.value = value; 40 | } 41 | 42 | public int comEnumValue() { 43 | return value; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/com4j/ICAScalingMode.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows.com4j; 2 | 3 | /** 4 | *

5 | * List of ICA scaling modes. 6 | *

7 | */ 8 | public enum ICAScalingMode { 9 | /** 10 | *

11 | * The value of this constant is 0. 12 | *

13 | */ 14 | ScalingModeDisabled, //NOSONAR // 0 15 | /** 16 | *

17 | * The value of this constant is 1. 18 | *

19 | */ 20 | ScalingModePercent, //NOSONAR // 1 21 | /** 22 | *

23 | * The value of this constant is 2. 24 | *

25 | */ 26 | ScalingModeSize, //NOSONAR // 2 27 | /** 28 | *

29 | * The value of this constant is 3. 30 | *

31 | */ 32 | ScalingModeAutoSize, //NOSONAR // 3 33 | } 34 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/com4j/ICASessionCounter.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows.com4j; 2 | 3 | /** 4 | *

5 | * List of ICA session counters. 6 | *

7 | */ 8 | public enum ICASessionCounter { 9 | /** 10 | *

11 | * The value of this constant is 0. 12 | *

13 | */ 14 | SessionIncomingBytes, //NOSONAR // 0 15 | /** 16 | *

17 | * The value of this constant is 1. 18 | *

19 | */ 20 | SessionOutgoingBytes, //NOSONAR // 1 21 | /** 22 | *

23 | * The value of this constant is 2. 24 | *

25 | */ 26 | SessionIncomingFrames, //NOSONAR // 2 27 | /** 28 | *

29 | * The value of this constant is 3. 30 | *

31 | */ 32 | SessionOutgoingFrames, //NOSONAR // 3 33 | /** 34 | *

35 | * The value of this constant is 4. 36 | *

37 | */ 38 | SessionIncomingErrors, //NOSONAR // 4 39 | /** 40 | *

41 | * The value of this constant is 5. 42 | *

43 | */ 44 | SessionOutgoingErrors, //NOSONAR // 5 45 | /** 46 | *

47 | * The value of this constant is 6. 48 | *

49 | */ 50 | SessionLastLatency, //NOSONAR // 6 51 | /** 52 | *

53 | * The value of this constant is 7. 54 | *

55 | */ 56 | SessionAverageLatency, //NOSONAR // 7 57 | /** 58 | *

59 | * The value of this constant is 8. 60 | *

61 | */ 62 | SessionLatencyDeviation, //NOSONAR // 8 63 | } 64 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/com4j/ICASessionEndAction.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows.com4j; 2 | 3 | /** 4 | *

5 | * List of ICA session end actions. 6 | *

7 | */ 8 | public enum ICASessionEndAction { 9 | /** 10 | *

11 | * The value of this constant is 0. 12 | *

13 | */ 14 | SessionEndDefault, //NOSONAR // 0 15 | /** 16 | *

17 | * The value of this constant is 1. 18 | *

19 | */ 20 | SessionEndRestart, //NOSONAR // 1 21 | } 22 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/com4j/ICASessionString.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows.com4j; 2 | 3 | /** 4 | *

5 | * List of ICA session strings. 6 | *

7 | */ 8 | public enum ICASessionString { 9 | /** 10 | *

11 | * The value of this constant is 0. 12 | *

13 | */ 14 | SessionServer, //NOSONAR // 0 15 | /** 16 | *

17 | * The value of this constant is 1. 18 | *

19 | */ 20 | SessionUsername, //NOSONAR // 1 21 | /** 22 | *

23 | * The value of this constant is 2. 24 | *

25 | */ 26 | SessionDomain, //NOSONAR // 2 27 | } 28 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/com4j/ICASoundQuality.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows.com4j; 2 | 3 | import com4j.ComEnum; 4 | 5 | /** 6 | *

7 | * List of ICA sound qualities. 8 | *

9 | */ 10 | public enum ICASoundQuality implements ComEnum { 11 | /** 12 | *

13 | * The value of this constant is -1. 14 | *

15 | */ 16 | SoundQualityNone(-1), //NOSONAR 17 | /** 18 | *

19 | * The value of this constant is 0. 20 | *

21 | */ 22 | SoundQualityHigh(0), //NOSONAR 23 | /** 24 | *

25 | * The value of this constant is 1. 26 | *

27 | */ 28 | SoundQualityMedium(1), //NOSONAR 29 | /** 30 | *

31 | * The value of this constant is 2. 32 | *

33 | */ 34 | SoundQualityLow(2); //NOSONAR 35 | 36 | private final int value; 37 | 38 | ICASoundQuality(int value) { 39 | this.value = value; 40 | } 41 | 42 | public int comEnumValue() { 43 | return value; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/com4j/ICAVCDataType.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows.com4j; 2 | 3 | /** 4 | *

5 | * List of ICA virtual channel data types. 6 | *

7 | */ 8 | @SuppressWarnings("checkstyle:AbbreviationAsWordInName") 9 | public enum ICAVCDataType { 10 | /** 11 | *

12 | * The value of this constant is 0. 13 | *

14 | */ 15 | DataTypeString, //NOSONAR // 0 16 | /** 17 | *

18 | * The value of this constant is 1. 19 | *

20 | */ 21 | DataTypeBinaryString, //NOSONAR // 1 22 | /** 23 | *

24 | * The value of this constant is 2. 25 | *

26 | */ 27 | DataTypeBinary, //NOSONAR // 2 28 | } 29 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/com4j/ICAWindowType.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows.com4j; 2 | 3 | /** 4 | *

5 | * List of ICA window types. 6 | *

7 | */ 8 | public enum ICAWindowType { 9 | /** 10 | *

11 | * The value of this constant is 0. 12 | *

13 | */ 14 | WindowTypeICAClientObject, //NOSONAR // 0 15 | /** 16 | *

17 | * The value of this constant is 1. 18 | *

19 | */ 20 | WindowTypeControl, //NOSONAR // 1 21 | /** 22 | *

23 | * The value of this constant is 2. 24 | *

25 | */ 26 | WindowTypeClient, //NOSONAR // 2 27 | /** 28 | *

29 | * The value of this constant is 3. 30 | *

31 | */ 32 | WindowTypeContainer, //NOSONAR // 3 33 | } 34 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/com4j/IKeyboard.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows.com4j; 2 | 3 | import com4j.Com4jObject; 4 | import com4j.DISPID; 5 | import com4j.IID; 6 | import com4j.VTID; 7 | 8 | /** 9 | * IKeyboard Interface. 10 | */ 11 | @IID("{17BFCA0A-C42E-4AC9-A693-29473FF9BA6C}") 12 | public interface IKeyboard extends Com4jObject { 13 | // Methods: 14 | 15 | /** 16 | *

17 | * method SendKeyDown. 18 | *

19 | * 20 | * @param keyId Mandatory int parameter. 21 | */ 22 | 23 | @DISPID(100) //= 0x64. The runtime will prefer the VTID if present 24 | @VTID(7) 25 | void sendKeyDown( 26 | int keyId); 27 | 28 | 29 | /** 30 | *

31 | * method SendKeyUp. 32 | *

33 | * 34 | * @param keyId Mandatory int parameter. 35 | */ 36 | 37 | @DISPID(101) //= 0x65. The runtime will prefer the VTID if present 38 | @VTID(8) 39 | void sendKeyUp( 40 | int keyId); 41 | 42 | 43 | // Properties: 44 | } 45 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/com4j/IMouse.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows.com4j; 2 | 3 | import com4j.Com4jObject; 4 | import com4j.DISPID; 5 | import com4j.IID; 6 | import com4j.VTID; 7 | 8 | /** 9 | * IMouse Interface. 10 | */ 11 | @IID("{02093274-7B69-4FEB-B7FD-3A010561A5F3}") 12 | public interface IMouse extends Com4jObject { 13 | // Methods: 14 | 15 | /** 16 | *

17 | * method SendMouseDown. 18 | *

19 | * 20 | * @param buttonId Mandatory int parameter. 21 | * @param modifiers Mandatory int parameter. 22 | * @param xPos Mandatory int parameter. 23 | * @param yPos Mandatory int parameter. 24 | */ 25 | 26 | @DISPID(100) //= 0x64. The runtime will prefer the VTID if present 27 | @VTID(7) 28 | void sendMouseDown( 29 | int buttonId, 30 | int modifiers, 31 | int xPos, 32 | int yPos); 33 | 34 | 35 | /** 36 | *

37 | * method SendMouseUp. 38 | *

39 | * 40 | * @param buttonId Mandatory int parameter. 41 | * @param modifiers Mandatory int parameter. 42 | * @param xPos Mandatory int parameter. 43 | * @param yPos Mandatory int parameter. 44 | */ 45 | 46 | @DISPID(101) //= 0x65. The runtime will prefer the VTID if present 47 | @VTID(8) 48 | void sendMouseUp( 49 | int buttonId, 50 | int modifiers, 51 | int xPos, 52 | int yPos); 53 | 54 | 55 | /** 56 | *

57 | * method SendMouseMove. 58 | *

59 | * 60 | * @param buttonId Mandatory int parameter. 61 | * @param modifiers Mandatory int parameter. 62 | * @param xPos Mandatory int parameter. 63 | * @param yPos Mandatory int parameter. 64 | */ 65 | 66 | @DISPID(102) //= 0x66. The runtime will prefer the VTID if present 67 | @VTID(9) 68 | void sendMouseMove( 69 | int buttonId, 70 | int modifiers, 71 | int xPos, 72 | int yPos); 73 | 74 | 75 | // Properties: 76 | } 77 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/com4j/IWindows.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows.com4j; 2 | 3 | import com4j.Com4jObject; 4 | import com4j.DISPID; 5 | import com4j.DefaultMethod; 6 | import com4j.IID; 7 | import com4j.VTID; 8 | 9 | /** 10 | * IWindows Interface. 11 | */ 12 | @IID("{9B371833-5E4F-4B72-A8F6-CB8E762999F4}") 13 | public interface IWindows extends Com4jObject, Iterable { 14 | // Methods: 15 | 16 | /** 17 | *

18 | * Getter method for the COM property "Item". 19 | *

20 | * 21 | * @param n Mandatory int parameter. 22 | * @return Returns a value of type com.blazemeter.jmeter.citrix.client.windows.com4j.IWindow 23 | */ 24 | 25 | @DISPID(0) //= 0x0. The runtime will prefer the VTID if present 26 | @VTID(7) 27 | @DefaultMethod 28 | com.blazemeter.jmeter.citrix.client.windows.com4j.IWindow item( 29 | int n); 30 | 31 | 32 | /** 33 | *

34 | * Getter method for the COM property "_NewEnum". 35 | *

36 | */ 37 | 38 | @DISPID(-4) //= 0xfffffffc. The runtime will prefer the VTID if present 39 | @VTID(8) 40 | java.util.Iterator iterator(); 41 | 42 | /** 43 | *

44 | * Getter method for the COM property "Count". 45 | *

46 | * 47 | * @return Returns a value of type int 48 | */ 49 | 50 | @DISPID(1) //= 0x1. The runtime will prefer the VTID if present 51 | @VTID(9) 52 | int count(); 53 | 54 | 55 | // Properties: 56 | } 57 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/com4j/KeyModifier.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows.com4j; 2 | 3 | import com4j.ComEnum; 4 | 5 | /** 6 | *

7 | * Key modifier buttons. 8 | *

9 | */ 10 | public enum KeyModifier implements ComEnum { 11 | /** 12 | *

13 | * The value of this constant is 1. 14 | *

15 | */ 16 | KeyModifierShift(1), //NOSONAR 17 | /** 18 | *

19 | * The value of this constant is 2. 20 | *

21 | */ 22 | KeyModifierControl(2), //NOSONAR 23 | /** 24 | *

25 | * The value of this constant is 4. 26 | *

27 | */ 28 | KeyModifierAlt(4), //NOSONAR 29 | /** 30 | *

31 | * The value of this constant is 8. 32 | *

33 | */ 34 | KeyModifierExtended(8); //NOSONAR 35 | 36 | private final int value; 37 | 38 | KeyModifier(int value) { 39 | this.value = value; 40 | } 41 | 42 | public int comEnumValue() { 43 | return value; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/com4j/MouseButton.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows.com4j; 2 | 3 | import com4j.ComEnum; 4 | 5 | /** 6 | *

7 | * Mouse buttons. 8 | *

9 | */ 10 | public enum MouseButton implements ComEnum { 11 | /** 12 | *

13 | * The value of this constant is 1. 14 | *

15 | */ 16 | MouseButtonLeft(1), //NOSONAR 17 | /** 18 | *

19 | * The value of this constant is 2. 20 | *

21 | */ 22 | MouseButtonRight(2), //NOSONAR 23 | /** 24 | *

25 | * The value of this constant is 4. 26 | *

27 | */ 28 | MouseButtonMiddle(4); //NOSONAR 29 | 30 | private final int value; 31 | 32 | MouseButton(int value) { 33 | this.value = value; 34 | } 35 | 36 | public int comEnumValue() { 37 | return value; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/com4j/OutputMode.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows.com4j; 2 | 3 | /** 4 | *

5 | * Client Output Modes. 6 | *

7 | */ 8 | public enum OutputMode { 9 | /** 10 | *

11 | * The value of this constant is 0. 12 | *

13 | */ 14 | OutputModeNonHeadless, //NOSONAR // 0 15 | /** 16 | *

17 | * The value of this constant is 1. 18 | *

19 | */ 20 | OutputModeNormal, //NOSONAR // 1 21 | /** 22 | *

23 | * The value of this constant is 2. 24 | *

25 | */ 26 | OutputModeRenderless, //NOSONAR // 2 27 | /** 28 | *

29 | * The value of this constant is 3. 30 | *

31 | */ 32 | OutputModeWindowless, //NOSONAR // 3 33 | } 34 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/com4j/WindowExStyle.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows.com4j; 2 | 3 | import com4j.ComEnum; 4 | 5 | /** 6 | *

7 | * Window extended style masks. 8 | *

9 | */ 10 | public enum WindowExStyle implements ComEnum { 11 | /** 12 | *

13 | * The value of this constant is 1. 14 | *

15 | */ 16 | WindowsExStyleDLGMODALFRAME(1), //NOSONAR 17 | /** 18 | *

19 | * The value of this constant is 4. 20 | *

21 | */ 22 | WindowsExStyleNOPARENTNOTIFY(4), //NOSONAR 23 | /** 24 | *

25 | * The value of this constant is 8. 26 | *

27 | */ 28 | WindowsExStyleTOPMOST(8), //NOSONAR 29 | /** 30 | *

31 | * The value of this constant is 16. 32 | *

33 | */ 34 | WindowsExStyleACCEPTFILES(16), //NOSONAR 35 | /** 36 | *

37 | * The value of this constant is 32. 38 | *

39 | */ 40 | WindowsExStyleTRANSPARENT(32), //NOSONAR 41 | /** 42 | *

43 | * The value of this constant is 64. 44 | *

45 | */ 46 | WindowsExStyleMDICHILD(64), //NOSONAR 47 | /** 48 | *

49 | * The value of this constant is 128. 50 | *

51 | */ 52 | WindowsExStyleTOOLWINDOW(128), //NOSONAR 53 | /** 54 | *

55 | * The value of this constant is 256. 56 | *

57 | */ 58 | WindowsExStyleWINDOWEDGE(256), //NOSONAR 59 | /** 60 | *

61 | * The value of this constant is 512. 62 | *

63 | */ 64 | WindowsExStyleCLIENTEDGE(512), //NOSONAR 65 | /** 66 | *

67 | * The value of this constant is 1024. 68 | *

69 | */ 70 | WindowsExStyleCONTEXTHELP(1024), //NOSONAR 71 | /** 72 | *

73 | * The value of this constant is 4096. 74 | *

75 | */ 76 | WindowsExStyleRIGHT(4096), //NOSONAR 77 | /** 78 | *

79 | * The value of this constant is 0. 80 | *

81 | */ 82 | WindowsExStyleLEFT(0), //NOSONAR 83 | /** 84 | *

85 | * The value of this constant is 8192. 86 | *

87 | */ 88 | WindowsExStyleRTLREADING(8192), //NOSONAR 89 | /** 90 | *

91 | * The value of this constant is 0. 92 | *

93 | */ 94 | WindowsExStyleLTRREADING(0), //NOSONAR 95 | /** 96 | *

97 | * The value of this constant is 16384. 98 | *

99 | */ 100 | WindowsExStyleLEFTSCROLLBAR(16384), //NOSONAR 101 | /** 102 | *

103 | * The value of this constant is 0. 104 | *

105 | */ 106 | WindowsExStyleRIGHTSCROLLBAR(0), //NOSONAR 107 | /** 108 | *

109 | * The value of this constant is 65536. 110 | *

111 | */ 112 | WindowsExStyleCONTROLPARENT(65536), //NOSONAR 113 | /** 114 | *

115 | * The value of this constant is 131072. 116 | *

117 | */ 118 | WindowsExStyleSTATICEDGE(131072), //NOSONAR 119 | /** 120 | *

121 | * The value of this constant is 262144. 122 | *

123 | */ 124 | WindowsExStyleAPPWINDOW(262144), //NOSONAR 125 | /** 126 | *

127 | * The value of this constant is 768. 128 | *

129 | */ 130 | WindowsExStyleOVERLAPPEDWINDOW(768), //NOSONAR 131 | /** 132 | *

133 | * The value of this constant is 392. 134 | *

135 | */ 136 | WindowsExStylePALETTEWINDOW(392); //NOSONAR 137 | 138 | private final int value; 139 | 140 | WindowExStyle(int value) { 141 | this.value = value; 142 | } 143 | 144 | public int comEnumValue() { 145 | return value; 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/com4j/WindowStyle.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows.com4j; 2 | 3 | import com4j.ComEnum; 4 | 5 | /** 6 | *

7 | * Window style masks. 8 | *

9 | */ 10 | public enum WindowStyle implements ComEnum { 11 | /** 12 | *

13 | * The value of this constant is 0. 14 | *

15 | */ 16 | WindowStyleOVERLAPPED(0), //NOSONAR 17 | /** 18 | *

19 | * The value of this constant is -2147483648. 20 | *

21 | */ 22 | WindowStylePOPUP(-2147483648), //NOSONAR 23 | /** 24 | *

25 | * The value of this constant is 1073741824. 26 | *

27 | */ 28 | WindowStyleCHILD(1073741824), //NOSONAR 29 | /** 30 | *

31 | * The value of this constant is 536870912. 32 | *

33 | */ 34 | WindowStyleMINIMIZE(536870912), //NOSONAR 35 | /** 36 | *

37 | * The value of this constant is 268435456. 38 | *

39 | */ 40 | WindowStyleVISIBLE(268435456), //NOSONAR 41 | /** 42 | *

43 | * The value of this constant is 134217728. 44 | *

45 | */ 46 | WindowStyleDISABLED(134217728), //NOSONAR 47 | /** 48 | *

49 | * The value of this constant is 67108864. 50 | *

51 | */ 52 | WindowStyleCLIPSIBLINGS(67108864), //NOSONAR 53 | /** 54 | *

55 | * The value of this constant is 33554432. 56 | *

57 | */ 58 | WindowStyleCLIPCHILDREN(33554432), //NOSONAR 59 | /** 60 | *

61 | * The value of this constant is 16777216. 62 | *

63 | */ 64 | WindowStyleMAXIMIZE(16777216), //NOSONAR 65 | /** 66 | *

67 | * The value of this constant is 12582912. 68 | *

69 | */ 70 | WindowStyleCAPTION(12582912), //NOSONAR 71 | /** 72 | *

73 | * The value of this constant is 8388608. 74 | *

75 | */ 76 | WindowStyleBORDER(8388608), //NOSONAR 77 | /** 78 | *

79 | * The value of this constant is 4194304. 80 | *

81 | */ 82 | WindowStyleDLGFRAME(4194304), //NOSONAR 83 | /** 84 | *

85 | * The value of this constant is 2097152. 86 | *

87 | */ 88 | WindowStyleVSCROLL(2097152), //NOSONAR 89 | /** 90 | *

91 | * The value of this constant is 1048576. 92 | *

93 | */ 94 | WindowStyleHSCROLL(1048576), //NOSONAR 95 | /** 96 | *

97 | * The value of this constant is 524288. 98 | *

99 | */ 100 | WindowStyleSYSMENU(524288), //NOSONAR 101 | /** 102 | *

103 | * The value of this constant is 262144. 104 | *

105 | */ 106 | WindowStyleTHICKFRAME(262144), //NOSONAR 107 | /** 108 | *

109 | * The value of this constant is 131072. 110 | *

111 | */ 112 | WindowStyleGROUP(131072), //NOSONAR 113 | /** 114 | *

115 | * The value of this constant is 65536. 116 | *

117 | */ 118 | WindowStyleTABSTOP(65536), //NOSONAR 119 | /** 120 | *

121 | * The value of this constant is 131072. 122 | *

123 | */ 124 | WindowStyleMINIMIZEBOX(131072), //NOSONAR 125 | /** 126 | *

127 | * The value of this constant is 65536. 128 | *

129 | */ 130 | WindowStyleMAXIMIZEBOX(65536); //NOSONAR 131 | 132 | private final int value; 133 | 134 | WindowStyle(int value) { 135 | this.value = value; 136 | } 137 | 138 | public int comEnumValue() { 139 | return value; 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/com4j/events/_IKeyboardEvents.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows.com4j.events; 2 | 3 | import com4j.DISPID; 4 | import com4j.IID; 5 | 6 | /** 7 | * _IKeyboardEvents Interface. 8 | */ 9 | @SuppressWarnings("checkstyle:TypeName") 10 | @IID("{8A5961DF-314E-4B7C-B57F-AAF35EA33079}") 11 | public abstract class _IKeyboardEvents { // NOSONAR 12 | // Methods: 13 | 14 | /** 15 | *

16 | * method OnKeyUp. 17 | *

18 | * 19 | * @param keyId Mandatory int parameter. 20 | * @param modifierState Mandatory int parameter. 21 | */ 22 | 23 | @DISPID(1) 24 | public void onKeyUp( 25 | int keyId, 26 | int modifierState) { 27 | throw new UnsupportedOperationException(); 28 | } 29 | 30 | 31 | /** 32 | *

33 | * method OnKeyDown. 34 | *

35 | * 36 | * @param keyId Mandatory int parameter. 37 | * @param modifierState Mandatory int parameter. 38 | */ 39 | 40 | @DISPID(2) 41 | public void onKeyDown( 42 | int keyId, 43 | int modifierState) { 44 | throw new UnsupportedOperationException(); 45 | } 46 | 47 | 48 | // Properties: 49 | } 50 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/com4j/events/_IMouseEvents.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows.com4j.events; 2 | 3 | import com4j.DISPID; 4 | import com4j.IID; 5 | 6 | /** 7 | * _IMouseEvents Interface. 8 | */ 9 | @SuppressWarnings("checkstyle:TypeName") 10 | @IID("{24013613-FF51-4B50-9832-37FA561594ED}") 11 | public abstract class _IMouseEvents { //NOSONAR 12 | // Methods: 13 | 14 | /** 15 | *

16 | * method OnMove. 17 | *

18 | * 19 | * @param buttonState Mandatory int parameter. 20 | * @param modifierState Mandatory int parameter. 21 | * @param xPos Mandatory int parameter. 22 | * @param yPos Mandatory int parameter. 23 | */ 24 | 25 | @DISPID(1) 26 | public void onMove( 27 | int buttonState, 28 | int modifierState, 29 | int xPos, 30 | int yPos) { 31 | throw new UnsupportedOperationException(); 32 | } 33 | 34 | 35 | /** 36 | *

37 | * method OnMouseDown. 38 | *

39 | * 40 | * @param buttonState Mandatory int parameter. 41 | * @param modifierState Mandatory int parameter. 42 | * @param xPos Mandatory int parameter. 43 | * @param yPos Mandatory int parameter. 44 | */ 45 | 46 | @DISPID(3) 47 | public void onMouseDown( 48 | int buttonState, 49 | int modifierState, 50 | int xPos, 51 | int yPos) { 52 | throw new UnsupportedOperationException(); 53 | } 54 | 55 | 56 | /** 57 | *

58 | * method OnMouseUp. 59 | *

60 | * 61 | * @param buttonState Mandatory int parameter. 62 | * @param modifierState Mandatory int parameter. 63 | * @param xPos Mandatory int parameter. 64 | * @param yPos Mandatory int parameter. 65 | */ 66 | 67 | @DISPID(2) 68 | public void onMouseUp( 69 | int buttonState, 70 | int modifierState, 71 | int xPos, 72 | int yPos) { 73 | throw new UnsupportedOperationException(); 74 | } 75 | 76 | 77 | /** 78 | *

79 | * method OnDoubleClick. 80 | *

81 | */ 82 | 83 | @DISPID(4) 84 | public void onDoubleClick() { 85 | throw new UnsupportedOperationException(); 86 | } 87 | 88 | 89 | // Properties: 90 | } 91 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/com4j/events/_IScreenShotEvents.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows.com4j.events; 2 | 3 | import com4j.DISPID; 4 | import com4j.IID; 5 | 6 | /** 7 | * _IScreenShotEvents Interface. 8 | */ 9 | 10 | @SuppressWarnings("checkstyle:TypeName") 11 | @IID("{785A16E9-4E42-4C87-84AD-BFB4A60570A3}") 12 | public abstract class _IScreenShotEvents { //NOSONAR 13 | // Methods: 14 | 15 | /** 16 | *

17 | * method OnUpdate. 18 | *

19 | * 20 | * @param bitmapHash Mandatory String parameter. 21 | */ 22 | 23 | @DISPID(1) 24 | public void onUpdate( 25 | String bitmapHash) { 26 | throw new UnsupportedOperationException(); 27 | } 28 | 29 | 30 | // Properties: 31 | } 32 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/com4j/events/_ISessionEvents.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows.com4j.events; 2 | 3 | import com.blazemeter.jmeter.citrix.client.windows.com4j.IWindow; 4 | import com4j.DISPID; 5 | import com4j.IID; 6 | 7 | /** 8 | * _ISessionEvents Interface. 9 | */ 10 | 11 | @SuppressWarnings("checkstyle:TypeName") 12 | @IID("{24FD31DB-3560-4C78-8950-30F03352D830}") 13 | public abstract class _ISessionEvents { //NOSONAR 14 | // Methods: 15 | 16 | /** 17 | *

18 | * method OnWindowCreate. 19 | *

20 | * 21 | * @param window Mandatory IWindow parameter. 22 | */ 23 | 24 | @DISPID(1) 25 | public void onWindowCreate(IWindow window) { 26 | throw new UnsupportedOperationException(); 27 | } 28 | 29 | 30 | /** 31 | *

32 | * method OnWindowDestroy. 33 | *

34 | * 35 | * @param window Mandatory IWindow parameter. 36 | */ 37 | 38 | @DISPID(2) 39 | public void onWindowDestroy(IWindow window) { 40 | throw new UnsupportedOperationException(); 41 | } 42 | 43 | 44 | /** 45 | *

46 | * method OnPingAck. 47 | *

48 | * 49 | * @param pingInfo Mandatory String parameter. 50 | * @param roundTripTime Mandatory int parameter. 51 | */ 52 | 53 | @DISPID(4) 54 | public void onPingAck( 55 | String pingInfo, 56 | int roundTripTime) { 57 | throw new UnsupportedOperationException(); 58 | } 59 | 60 | 61 | /** 62 | *

63 | * method OnWindowForeground. 64 | *

65 | * 66 | * @param windowID Mandatory int parameter. 67 | */ 68 | 69 | @DISPID(5) 70 | public void onWindowForeground( 71 | int windowID) { 72 | throw new UnsupportedOperationException(); 73 | } 74 | 75 | 76 | // Properties: 77 | } 78 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/com4j/events/_IWindowEvents.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows.com4j.events; 2 | 3 | import com4j.DISPID; 4 | import com4j.IID; 5 | 6 | /** 7 | * _IWindowEvents Interface. 8 | */ 9 | 10 | @SuppressWarnings("checkstyle:TypeName") 11 | @IID("{49813E6D-17FF-41A1-9A7B-95C3D5B44185}") 12 | public abstract class _IWindowEvents { //NOSONAR 13 | // Methods: 14 | 15 | /** 16 | *

17 | * method OnMove. 18 | *

19 | * 20 | * @param xPos Mandatory int parameter. 21 | * @param yPos Mandatory int parameter. 22 | */ 23 | 24 | @DISPID(1) 25 | public void onMove( 26 | int xPos, 27 | int yPos) { 28 | throw new UnsupportedOperationException(); 29 | } 30 | 31 | 32 | /** 33 | *

34 | * method OnSize. 35 | *

36 | * 37 | * @param width Mandatory int parameter. 38 | * @param height Mandatory int parameter. 39 | */ 40 | 41 | @DISPID(2) 42 | public void onSize( 43 | int width, 44 | int height) { 45 | throw new UnsupportedOperationException(); 46 | } 47 | 48 | 49 | /** 50 | *

51 | * method OnActivate. 52 | *

53 | */ 54 | 55 | @DISPID(3) 56 | public void onActivate() { 57 | throw new UnsupportedOperationException(); 58 | } 59 | 60 | 61 | /** 62 | *

63 | * method OnDeactivate. 64 | *

65 | */ 66 | 67 | @DISPID(4) 68 | public void onDeactivate() { 69 | throw new UnsupportedOperationException(); 70 | } 71 | 72 | 73 | /** 74 | *

75 | * method OnMinimize. 76 | *

77 | */ 78 | 79 | @DISPID(5) 80 | public void onMinimize() { 81 | throw new UnsupportedOperationException(); 82 | } 83 | 84 | 85 | /** 86 | *

87 | * method OnCaptionChange. 88 | *

89 | * 90 | * @param caption Mandatory java.lang.String parameter. 91 | */ 92 | 93 | @DISPID(6) 94 | public void onCaptionChange( 95 | java.lang.String caption) { 96 | throw new UnsupportedOperationException(); 97 | } 98 | 99 | 100 | /** 101 | *

102 | * method OnStyleChange. 103 | *

104 | * 105 | * @param style Mandatory int parameter. 106 | * @param extendedStyle Mandatory int parameter. 107 | */ 108 | 109 | @DISPID(7) 110 | public void onStyleChange( 111 | int style, 112 | int extendedStyle) { 113 | throw new UnsupportedOperationException(); 114 | } 115 | 116 | 117 | /** 118 | *

119 | * method OnSmallIconChange. 120 | *

121 | * 122 | * @param smallIconHash Mandatory java.lang.String parameter. 123 | */ 124 | 125 | @DISPID(8) 126 | public void onSmallIconChange( 127 | java.lang.String smallIconHash) { 128 | throw new UnsupportedOperationException(); 129 | } 130 | 131 | 132 | /** 133 | *

134 | * method OnLargeIconChange. 135 | *

136 | * 137 | * @param largeIconHash Mandatory java.lang.String parameter. 138 | */ 139 | 140 | @DISPID(9) 141 | public void onLargeIconChange( 142 | java.lang.String largeIconHash) { 143 | throw new UnsupportedOperationException(); 144 | } 145 | 146 | 147 | /** 148 | *

149 | * method OnDestroy. 150 | *

151 | */ 152 | 153 | @DISPID(10) 154 | public void onDestroy() { 155 | throw new UnsupportedOperationException(); 156 | } 157 | 158 | 159 | // Properties: 160 | } 161 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/com4j/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | >WFICALib - Citrix ICA Client 5 | 6 | 7 |

WFICALib

8 |

Citrix ICA Client

9 | 10 | 11 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/events/KeyboardAdapter.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows.events; 2 | 3 | import com.blazemeter.jmeter.citrix.client.windows.com4j.events._IKeyboardEvents; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | public class KeyboardAdapter extends _IKeyboardEvents { 8 | 9 | private static final Logger LOGGER = LoggerFactory.getLogger(KeyboardAdapter.class); 10 | 11 | @Override 12 | public void onKeyDown(int keyId, int modifierState) { 13 | LOGGER.debug("onKeyDown: keyId={} (0x{}, {}), modifierState=0b{}", keyId, 14 | Integer.toHexString(keyId), 15 | (char) keyId, Integer.toBinaryString(modifierState)); 16 | } 17 | 18 | @Override 19 | public void onKeyUp(int keyId, int modifierState) { 20 | LOGGER.debug("onKeyUp: keyId={} (0x{}, {}), modifierState=0b{}", keyId, 21 | Integer.toHexString(keyId), 22 | (char) keyId, Integer.toBinaryString(modifierState)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/events/MouseAdapter.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows.events; 2 | 3 | import com.blazemeter.jmeter.citrix.client.windows.com4j.events._IMouseEvents; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | public class MouseAdapter extends _IMouseEvents { 8 | 9 | private static final Logger LOGGER = LoggerFactory.getLogger(MouseAdapter.class); 10 | 11 | @Override 12 | public void onDoubleClick() { 13 | LOGGER.debug("onDoubleClick"); 14 | } 15 | 16 | @Override 17 | public void onMouseDown(int buttonState, int modifierState, int xPos, int yPos) { 18 | if (LOGGER.isDebugEnabled()) { 19 | LOGGER.debug("onMouseDown: buttonState=0b{}, modifierState=0b{}, xPos={}, yPos={}", 20 | Integer.toBinaryString(buttonState), Integer.toBinaryString(modifierState), xPos, yPos); 21 | } 22 | } 23 | 24 | @Override 25 | public void onMouseUp(int buttonState, int modifierState, int xPos, int yPos) { 26 | if (LOGGER.isDebugEnabled()) { 27 | LOGGER.debug("onMouseUp: buttonState=0b{}, modifierState=0b{}, xPos={}, yPos={}", 28 | Integer.toBinaryString(buttonState), Integer.toBinaryString(modifierState), xPos, yPos); 29 | } 30 | } 31 | 32 | @Override 33 | public void onMove(int buttonState, int modifierState, int xPos, int yPos) { 34 | if (LOGGER.isTraceEnabled()) { 35 | LOGGER.trace("onMove: buttonState=0b{}, modifierState=0b{}, xPos={}, yPos={}", 36 | Integer.toBinaryString(buttonState), Integer.toBinaryString(modifierState), xPos, yPos); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/events/SessionAdapter.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows.events; 2 | 3 | import com.blazemeter.jmeter.citrix.client.windows.com4j.IWindow; 4 | import com.blazemeter.jmeter.citrix.client.windows.com4j.events._ISessionEvents; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | public class SessionAdapter extends _ISessionEvents { 9 | 10 | private static final Logger LOGGER = LoggerFactory.getLogger(SessionAdapter.class); 11 | 12 | @Override 13 | public void onPingAck(String pingInfo, int roundTripTime) { 14 | LOGGER.debug("onPingAck: pingInfo={}, roundTripTime={}", pingInfo, roundTripTime); 15 | } 16 | 17 | @Override 18 | public void onWindowCreate(IWindow window) { 19 | if (LOGGER.isDebugEnabled()) { 20 | LOGGER.debug("onWindowCreate: window=[ID={}, caption={}, style=0x{}, extendedStyle=0x{}]", 21 | window.windowID(), 22 | window.caption(), Integer.toHexString(window.style()), 23 | Integer.toHexString(window.extendedStyle())); 24 | } 25 | } 26 | 27 | @Override 28 | public void onWindowDestroy(IWindow window) { 29 | if (LOGGER.isDebugEnabled()) { 30 | LOGGER.debug("onWindowDestroy: window=[ID={}, caption={}, style=0x{}, extendedStyle=0x{}]", 31 | window.windowID(), 32 | window.caption(), Integer.toHexString(window.style()), 33 | Integer.toHexString(window.extendedStyle())); 34 | } 35 | } 36 | 37 | @Override 38 | public void onWindowForeground(int windowID) { 39 | if (LOGGER.isDebugEnabled()) { 40 | LOGGER.debug("onWindowForeground: windowID={}", windowID); 41 | } 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /citrix-client-win/src/main/java/com/blazemeter/jmeter/citrix/client/windows/events/WindowAdapter.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.windows.events; 2 | 3 | import com.blazemeter.jmeter.citrix.client.windows.com4j.events._IWindowEvents; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | public class WindowAdapter extends _IWindowEvents { 8 | 9 | private static final Logger LOGGER = LoggerFactory.getLogger(WindowAdapter.class); 10 | 11 | private final int windowID; 12 | 13 | public WindowAdapter(int windowID) { 14 | this.windowID = windowID; 15 | } 16 | 17 | public final int getWindowID() { 18 | return windowID; 19 | } 20 | 21 | @Override 22 | public void onActivate() { 23 | LOGGER.debug("onActivate for window {}", windowID); 24 | } 25 | 26 | @Override 27 | public void onCaptionChange(String caption) { 28 | LOGGER.debug("onCaptionChange for window {}: caption={}", windowID, caption); 29 | } 30 | 31 | @Override 32 | public void onDeactivate() { 33 | LOGGER.debug("onDeactivate for window {}", windowID); 34 | } 35 | 36 | @Override 37 | public void onDestroy() { 38 | LOGGER.debug("onDestroy for window {}", windowID); 39 | } 40 | 41 | @Override 42 | public void onLargeIconChange(String largeIconHash) { 43 | LOGGER.debug("onLargeIconChange for window {}: largeIconHash={}", windowID, largeIconHash); 44 | } 45 | 46 | @Override 47 | public void onMinimize() { 48 | LOGGER.debug("onMinimize for window {}", windowID); 49 | } 50 | 51 | @Override 52 | public void onMove(int xPos, int yPos) { 53 | LOGGER.debug("onMove for window {}: xPos={}, yPos={}", windowID, xPos, yPos); 54 | } 55 | 56 | @Override 57 | public void onSize(int width, int height) { 58 | LOGGER.debug("onSize for window {}: width={}, height={}", windowID, width, height); 59 | } 60 | 61 | @Override 62 | public void onSmallIconChange(String smallIconHash) { 63 | LOGGER.debug("onSmallIconChange for window {}: smallIconHash={}", windowID, smallIconHash); 64 | } 65 | 66 | @Override 67 | public void onStyleChange(int style, int extendedStyle) { 68 | if (LOGGER.isDebugEnabled()) { 69 | LOGGER.debug("onStyleChange for window {}: style=0x{}, extendedStyle=0x{}", windowID, 70 | Integer.toHexString(style), Integer.toHexString(extendedStyle)); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /citrix-common/.gitignore: -------------------------------------------------------------------------------- 1 | .project 2 | .classpath 3 | target 4 | .settings -------------------------------------------------------------------------------- /citrix-common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 4.0.0 7 | 8 | com.blazemeter.jmeter 9 | citrix-parent 10 | 0.7.7 11 | 12 | 13 | 14 | net.java.dev.jna 15 | jna 16 | 5.6.0 17 | 18 | 19 | 20 | net.java.dev.jna 21 | jna-platform 22 | 5.6.0 23 | 24 | 25 | 26 | org.ini4j 27 | ini4j 28 | 0.5.4 29 | 30 | 31 | citrix-common 32 | 33 | -------------------------------------------------------------------------------- /citrix-common/src/main/java/com/blazemeter/jmeter/citrix/client/Win32Utils.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client; 2 | 3 | import static com.sun.jna.platform.win32.WinUser.MAPVK_VK_TO_VSC; //NOSONAR 4 | 5 | import com.sun.jna.platform.win32.User32; //NOSONAR 6 | import com.sun.jna.platform.win32.WinDef; //NOSONAR 7 | import java.awt.event.KeyEvent; 8 | 9 | public class Win32Utils { 10 | 11 | private Win32Utils() { 12 | 13 | } 14 | 15 | public static int getVirtualKey(int keyCode) { 16 | // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-vkkeyscanexw 17 | WinDef.HKL keyLayoutID = User32.INSTANCE.GetKeyboardLayout(0); 18 | return User32.INSTANCE.VkKeyScanExW((char) keyCode, keyLayoutID); 19 | } 20 | 21 | public static char getVKCharacter(int vkCode, boolean vkShift, boolean vkAlt, boolean vkCtrl) { 22 | 23 | //https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getkeyboardlayout 24 | int currentThread = 0; 25 | WinDef.HKL keyLayoutID = User32.INSTANCE.GetKeyboardLayout(currentThread); 26 | 27 | // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-mapvirtualkeyexa 28 | int scanCode = User32.INSTANCE.MapVirtualKeyEx(vkCode, MAPVK_VK_TO_VSC, keyLayoutID); 29 | 30 | // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-tounicodeex 31 | byte[] keyStates = new byte[256]; 32 | byte keyDownState = (byte) 128; 33 | keyStates[KeyEvent.VK_SHIFT] = vkShift ? keyDownState : 0; 34 | keyStates[KeyEvent.VK_ALT] = vkAlt ? keyDownState : 0; 35 | keyStates[KeyEvent.VK_CONTROL] = vkCtrl ? keyDownState : 0; 36 | 37 | char[] buff = new char[1]; 38 | int buffCharSize = 1; 39 | int menuActiveFlag = 0; 40 | int ret = User32.INSTANCE.ToUnicodeEx( 41 | vkCode, scanCode, keyStates, buff, buffCharSize, menuActiveFlag, keyLayoutID 42 | ); 43 | 44 | switch (ret) { 45 | case -1: //Error 46 | return (char) -1; 47 | 48 | case 0: //No Translation 49 | return (char) 0; 50 | 51 | default: //Returning key... 52 | return buff[0]; 53 | } 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /citrix-common/src/main/java/com/blazemeter/jmeter/citrix/client/WindowInfo.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client; 2 | 3 | import java.awt.Rectangle; 4 | 5 | /** 6 | * Provides details about existing windows in citrix session. 7 | */ 8 | public class WindowInfo { 9 | private Rectangle area; 10 | private String caption; 11 | 12 | /** 13 | * Instantiates a new {@link WindowInfo}. 14 | * 15 | * @param area the area of the window 16 | * @param caption the caption of the window 17 | */ 18 | public WindowInfo(Rectangle area, String caption) { 19 | this.area = area; 20 | this.caption = caption; 21 | } 22 | 23 | public WindowInfo(WindowInfo info) { 24 | this.area = new Rectangle(info.getArea()); 25 | this.caption = info.getCaption(); 26 | } 27 | 28 | /** 29 | * Gets the area of the window. 30 | * 31 | * @return the area of the window 32 | */ 33 | public Rectangle getArea() { 34 | return area; 35 | } 36 | 37 | /** 38 | * Sets the area of the window. 39 | * 40 | * @param area the area of the window 41 | */ 42 | public void setArea(Rectangle area) { 43 | this.area = area; 44 | } 45 | 46 | /** 47 | * Gets the caption of the window. 48 | * 49 | * @return the caption of the window 50 | */ 51 | public String getCaption() { 52 | return caption; 53 | } 54 | 55 | /** 56 | * Sets the caption of the window. 57 | * 58 | * @param caption the caption of the window 59 | */ 60 | public void setCaption(String caption) { 61 | this.caption = caption; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /citrix-common/src/main/java/com/blazemeter/jmeter/citrix/client/events/ClientEvent.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.events; 2 | 3 | import com.blazemeter.jmeter.citrix.client.CitrixClient; 4 | import java.io.Serializable; 5 | import java.util.Date; 6 | 7 | public class ClientEvent implements Serializable { 8 | 9 | /** 10 | * 11 | */ 12 | private static final long serialVersionUID = 2404479292064665761L; 13 | private final transient CitrixClient source; 14 | private final long timestamp; 15 | 16 | public ClientEvent(CitrixClient source) { 17 | this.source = source; 18 | this.timestamp = new Date().getTime(); 19 | } 20 | 21 | public CitrixClient getSource() { 22 | return this.source; 23 | } 24 | 25 | public long getTimestamp() { 26 | return timestamp; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /citrix-common/src/main/java/com/blazemeter/jmeter/citrix/client/events/EventHelper.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.events; 2 | 3 | import java.util.EnumSet; 4 | import java.util.Set; 5 | import java.util.stream.Collectors; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | public class EventHelper { 10 | 11 | private static final Logger LOGGER = LoggerFactory.getLogger(EventHelper.class); 12 | 13 | private EventHelper() { 14 | } 15 | 16 | public static Set toButtons(final int value) { 17 | Set result = EnumSet.noneOf(MouseButton.class); 18 | int copy = value; 19 | for (MouseButton button : MouseButton.values()) { 20 | final int bValue = button.getValue(); 21 | if ((bValue & value) == bValue) { 22 | result.add(button); 23 | copy -= bValue; 24 | } 25 | } 26 | if (copy != 0) { 27 | String copyString = Integer.toBinaryString(copy); 28 | LOGGER.warn( 29 | "Converting integer value to set of buttons: Value {} contains unsupported flags {}", 30 | value, 31 | copyString); 32 | } 33 | return result; 34 | } 35 | 36 | public static int fromButtons(Set buttons) { 37 | int flags = 0; 38 | if (buttons != null) { 39 | for (MouseButton button : buttons) { 40 | flags += button.getValue(); 41 | } 42 | } 43 | return flags; 44 | } 45 | 46 | public static Set toModifiers(final int value) { 47 | Set result = EnumSet.noneOf(Modifier.class); 48 | int copy = value; 49 | for (Modifier modifier : Modifier.values()) { 50 | final int mValue = modifier.getValue(); 51 | if ((mValue & value) == mValue) { 52 | result.add(modifier); 53 | copy -= mValue; 54 | } 55 | } 56 | if (copy != 0) { 57 | String copyString = Integer.toBinaryString(copy); 58 | LOGGER.warn( 59 | "Converting integer value to set of modifiers: Value {} contains unsupported flags {}", 60 | value, 61 | copyString); 62 | } 63 | return result; 64 | } 65 | 66 | public static String getModifiersText(final Set modifiers) { 67 | return modifiers.stream() 68 | .map(Modifier::name) 69 | .collect(Collectors.joining("+")); 70 | } 71 | 72 | public static int fromModifiers(Set modifiers) { 73 | int flags = 0; 74 | if (modifiers != null) { 75 | for (Modifier modifier : modifiers) { 76 | flags += modifier.getValue(); 77 | } 78 | } 79 | return flags; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /citrix-common/src/main/java/com/blazemeter/jmeter/citrix/client/events/EventInfo.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.events; 2 | 3 | import com.blazemeter.jmeter.citrix.client.CitrixClient; 4 | 5 | /** 6 | * Represents details about events occured during a Citrix session. 7 | */ 8 | public interface EventInfo { 9 | 10 | /** 11 | * Gets the source of this event. 12 | * 13 | * @return the source of this event 14 | */ 15 | CitrixClient getSource(); 16 | 17 | /** 18 | * Gets the timestamp of this event. 19 | * 20 | * @return the timestamp of this event 21 | */ 22 | long getTimestamp(); 23 | } 24 | -------------------------------------------------------------------------------- /citrix-common/src/main/java/com/blazemeter/jmeter/citrix/client/events/Modifier.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.events; 2 | 3 | /** 4 | * Defines the modifiers keys that impact the events state. 5 | */ 6 | public enum Modifier { 7 | /** 8 | * Shift key is pressed. 9 | */ 10 | SHIFT(1), 11 | /** 12 | * Control key is pressed. 13 | */ 14 | CONTROL(2), 15 | /** 16 | * Alt key is pressed. 17 | */ 18 | ALT(4), 19 | /** 20 | * Used to build extended modifier state. 21 | */ 22 | EXTENDED(8); 23 | 24 | private final int value; 25 | 26 | Modifier(int value) { 27 | this.value = value; 28 | } 29 | 30 | /** 31 | * Get the integer value of the modifier. 32 | * 33 | * @return the integer value of the modifier 34 | */ 35 | public int getValue() { 36 | return value; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /citrix-common/src/main/java/com/blazemeter/jmeter/citrix/client/events/MouseButton.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.events; 2 | 3 | /** 4 | * Enumerates the buttons of a mouse. 5 | */ 6 | public enum MouseButton { 7 | /** 8 | * Left button. 9 | */ 10 | LEFT(1), 11 | /** 12 | * Right button. 13 | */ 14 | RIGHT(2), 15 | /** 16 | * Middle button. 17 | */ 18 | MIDDLE(4); 19 | 20 | private final int value; 21 | 22 | MouseButton(int value) { 23 | this.value = value; 24 | } 25 | 26 | /** 27 | * Gets the integer value of the button. 28 | * 29 | * @return the integer value of the button 30 | */ 31 | public int getValue() { 32 | return value; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /citrix-common/src/main/java/com/blazemeter/jmeter/citrix/client/events/WindowEvent.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.events; 2 | 3 | import com.blazemeter.jmeter.citrix.client.CitrixClient; 4 | import com.blazemeter.jmeter.citrix.client.WindowInfo; 5 | 6 | /** 7 | * Provides events about Citrix in-session windows. 8 | */ 9 | public class WindowEvent extends ClientEvent { 10 | 11 | private static final long serialVersionUID = -1758399947925884485L; 12 | private final WindowState winState; 13 | private final WindowInfo winInfo; 14 | 15 | /** 16 | * Instantiates a WindowEvent. 17 | * 18 | * @param source the source of the event 19 | * @param winState the type of foreground window change 20 | * @param info details about the window involved in the event 21 | */ 22 | public WindowEvent(CitrixClient source, WindowState winState, WindowInfo info) { 23 | super(source); 24 | if (winState == null) { 25 | throw new IllegalArgumentException("winState must not be null."); 26 | } 27 | this.winState = winState; 28 | this.winInfo = info; 29 | } 30 | 31 | /** 32 | * Gets the type of window change. 33 | * 34 | * @return the type of window change 35 | */ 36 | public WindowState getWindowState() { 37 | return winState; 38 | } 39 | 40 | /** 41 | * Gets details about the window involved in the event. 42 | * 43 | * @return details about the window involved in the event 44 | */ 45 | public WindowInfo getWindowInfo() { 46 | return winInfo; 47 | } 48 | 49 | /** 50 | * Enumerates the types of window events. 51 | */ 52 | public enum WindowState { 53 | /** 54 | * The window has just been created. 55 | */ 56 | CREATED, 57 | 58 | /** 59 | * The window has just been closed. 60 | */ 61 | CLOSED, 62 | 63 | /** 64 | * The windows has just been activated. 65 | */ 66 | ACTIVATED, 67 | 68 | /** 69 | * THe window has just been deactivated. 70 | */ 71 | DEACTIVATED, 72 | 73 | /** 74 | * The window area has changed. 75 | */ 76 | CHANGE_AREA, 77 | 78 | /** 79 | * The window caption has changed. 80 | */ 81 | CHANGE_CAPTION, 82 | 83 | /** 84 | * The window gets the foregound. 85 | */ 86 | FOREGROUND 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /citrix-common/src/main/java/com/blazemeter/jmeter/citrix/client/factory/CitrixClientFactory.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.factory; 2 | 3 | import com.blazemeter.jmeter.citrix.client.CitrixClient; 4 | import java.util.Properties; 5 | 6 | /** 7 | * Represents a factory use to instantiate {@link CitrixClient} objects. 8 | */ 9 | public interface CitrixClientFactory { 10 | 11 | /** 12 | * Create a new {@link CitrixClient}.
13 | * The Citrix client type depends on this factory implementation. 14 | * 15 | * @return A Citrix client 16 | */ 17 | CitrixClient createClient(); 18 | 19 | /** 20 | * Gets the properties used to initialize client. 21 | * 22 | * @return the properties used to initialize client 23 | */ 24 | Properties getClientProperties(); 25 | 26 | /** 27 | * Sets the properties used to initialize client. 28 | * 29 | * @param properties the properties used to initialize client 30 | */ 31 | void setClientProperties(Properties properties); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /citrix-common/src/main/java/com/blazemeter/jmeter/citrix/client/handler/CitrixClientAdapter.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.handler; 2 | 3 | import com.blazemeter.jmeter.citrix.client.CitrixClient; 4 | import com.blazemeter.jmeter.citrix.client.events.InteractionEvent; 5 | import com.blazemeter.jmeter.citrix.client.events.Modifier; 6 | import com.blazemeter.jmeter.citrix.client.events.MouseButton; 7 | import com.blazemeter.jmeter.citrix.client.events.SessionEvent; 8 | import com.blazemeter.jmeter.citrix.client.events.WindowEvent; 9 | import java.awt.Point; 10 | import java.util.Set; 11 | 12 | /** 13 | * Provides an adapter for Citrix client event handling. 14 | */ 15 | public class CitrixClientAdapter implements CitrixClientHandler { 16 | 17 | @Override 18 | public void handleInteractionEvent(InteractionEvent interactionEvent) { 19 | // NOOP 20 | } 21 | 22 | @Override 23 | public void handleSessionEvent(SessionEvent sessionEvent) { 24 | // NOOP 25 | } 26 | 27 | @Override 28 | public void handleWindowEvent(WindowEvent windowEvent) { 29 | // NOOP 30 | } 31 | 32 | @Override 33 | public void handleKeyQuery(CitrixClient source, boolean keyUp, int keyCode) { 34 | // NOOP 35 | } 36 | 37 | @Override 38 | public void handleMouseButtonQuery(CitrixClient source, boolean up, Set buttons, 39 | Point position, 40 | Set modifiers, Point originalPosition) { 41 | // NOOP 42 | } 43 | 44 | @Override 45 | public void handleMouseMoveQuery(CitrixClient source, Set buttons, Point position, 46 | Set modifiers, Point originalPosition) { 47 | // NOOP 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /citrix-common/src/main/java/com/blazemeter/jmeter/citrix/client/handler/CitrixClientHandler.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.handler; 2 | 3 | import com.blazemeter.jmeter.citrix.client.CitrixClient; 4 | import com.blazemeter.jmeter.citrix.client.events.InteractionEvent; 5 | import com.blazemeter.jmeter.citrix.client.events.Modifier; 6 | import com.blazemeter.jmeter.citrix.client.events.MouseButton; 7 | import com.blazemeter.jmeter.citrix.client.events.SessionEvent; 8 | import com.blazemeter.jmeter.citrix.client.events.WindowEvent; 9 | import java.awt.Point; 10 | import java.util.Set; 11 | 12 | /** 13 | * Represents a handler for {@link CitrixClient}. 14 | */ 15 | public interface CitrixClientHandler { 16 | 17 | /** 18 | * Handles the user interaction. 19 | * 20 | * @param interactionEvent the user interaction 21 | */ 22 | void handleInteractionEvent(InteractionEvent interactionEvent); 23 | 24 | /** 25 | * Handles the session event. 26 | * 27 | * @param sessionEvent the session event 28 | */ 29 | void handleSessionEvent(SessionEvent sessionEvent); 30 | 31 | /** 32 | * Handles the window event. 33 | * 34 | * @param winEvent the foreground windows event 35 | */ 36 | void handleWindowEvent(WindowEvent winEvent); 37 | 38 | /** 39 | * Handles a key query. 40 | * 41 | * @param source the client where the query occurred 42 | * @param up true, if the key is up; false otherwise 43 | * @param keyCode the code of the key 44 | */ 45 | void handleKeyQuery(CitrixClient source, boolean up, int keyCode); 46 | 47 | /** 48 | * Handles a mouse buttons change query. 49 | * 50 | * @param source the client where the query occurred 51 | * @param up true, if the mouse buttons are up; false otherwise 52 | * @param buttons the set of involved mouse buttons 53 | * @param position the absolute position of mouse cursor 54 | * @param modifiers the set of modifier keys pressed when the query 55 | * occurred 56 | * @param originalPosition the relative to foreground window position of the 57 | * mouse cursor; null if query is not relative 58 | */ 59 | void handleMouseButtonQuery(CitrixClient source, boolean up, Set buttons, 60 | Point position, 61 | Set modifiers, Point originalPosition); 62 | 63 | /** 64 | * Handles a mouse move query. 65 | * 66 | * @param source the client where the query occurred 67 | * @param buttons the set of pressed mouse buttons 68 | * @param position the absolute position of mouse cursor 69 | * @param modifiers the set of modifier keys pressed when the query 70 | * occurred 71 | * @param originalPosition the relative to foreground window position of the 72 | * mouse cursor; null if query is not relative 73 | */ 74 | void handleMouseMoveQuery(CitrixClient source, Set buttons, Point position, 75 | Set modifiers, Point originalPosition); 76 | } 77 | -------------------------------------------------------------------------------- /citrix-common/src/main/java/com/blazemeter/jmeter/citrix/client/handler/CitrixClientHandlerException.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client.handler; 2 | 3 | /** 4 | * Provides exception when Citrix client fails. 5 | */ 6 | public class CitrixClientHandlerException extends Exception { 7 | 8 | private static final long serialVersionUID = 8096627550410319461L; 9 | 10 | /** 11 | * Instantiates a new {@link CitrixClientHandlerException}. 12 | */ 13 | public CitrixClientHandlerException() { 14 | } 15 | 16 | /** 17 | * Instantiates a new {@link CitrixClientHandlerException}. 18 | * 19 | * @param message the description of the error 20 | */ 21 | public CitrixClientHandlerException(String message) { 22 | super(message); 23 | } 24 | 25 | /** 26 | * Instantiates a new {@link CitrixClientHandlerException}. 27 | * 28 | * @param cause the cause of this error 29 | */ 30 | public CitrixClientHandlerException(Throwable cause) { 31 | super(cause); 32 | } 33 | 34 | /** 35 | * Instantiates a new {@link CitrixClientHandlerException}. 36 | * 37 | * @param message the description of the error 38 | * @param cause the cause of this error 39 | */ 40 | public CitrixClientHandlerException(String message, Throwable cause) { 41 | super(message, cause); 42 | } 43 | 44 | /** 45 | * Instantiates a new {@link CitrixClientHandlerException}. 46 | * 47 | * @param message the description of the error 48 | * @param cause the cause of this error 49 | * @param enableSuppression whether or not suppression is enabled or disabled 50 | * @param writableStackTrace whether or not the stack trace should be writable 51 | */ 52 | public CitrixClientHandlerException(String message, Throwable cause, boolean enableSuppression, 53 | boolean writableStackTrace) { 54 | super(message, cause, enableSuppression, writableStackTrace); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /citrix-jmeter/.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .project 3 | /target 4 | .settings 5 | /dependency-reduced-pom.xml 6 | -------------------------------------------------------------------------------- /citrix-jmeter/plugin-metadata/descriptor-test.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "id": "bzm-jmeter-citrix-plugin", 3 | "name": "BlazeMeter JMeter Citrix plugin", 4 | "description": "Plugin which provides the ability to load tests Citrix exposed application with Apache JMeter", 5 | "screenshotUrl": "http://localhost:8082/Blazemeter/CitrixPlugin/master/docs/images/presentationScreenshot.png", 6 | "helpUrl": "http://localhost:8082/Blazemeter/CitrixPlugin/master/docs/README.md", 7 | "vendor": "BlazeMeter", 8 | "markerClass": "com.blazemeter.jmeter.citrix.recorder.gui.CitrixRecorderGUI", 9 | "componentClasses": [ 10 | "com.blazemeter.jmeter.citrix.assertion.CitrixAssertion", 11 | "com.blazemeter.jmeter.citrix.assertion.gui.CitrixAssertionGui", 12 | "com.blazemeter.jmeter.citrix.assertion.CitrixSessionAssertion", 13 | "com.blazemeter.jmeter.citrix.assertion.gui.CitrixSessionAssertionGui", 14 | "com.blazemeter.jmeter.citrix.gui.CitrixResultRenderer", 15 | "com.blazemeter.jmeter.citrix.listener.CitrixIcaFileSaver", 16 | "com.blazemeter.jmeter.citrix.listener.gui.CitrixIcaFileSaverGui", 17 | "com.blazemeter.jmeter.citrix.recorder.CitrixRecorder", 18 | "com.blazemeter.jmeter.citrix.recorder.gui.CitrixRecorderGUI", 19 | "com.blazemeter.jmeter.citrix.sampler.StartApplicationSampler", 20 | "com.blazemeter.jmeter.citrix.sampler.gui.StartApplicationSamplerGUI", 21 | "com.blazemeter.jmeter.citrix.sampler.InteractionSampler", 22 | "com.blazemeter.jmeter.citrix.sampler.gui.CitrixSamplerGUI" 23 | ], 24 | "versions": { 25 | "1.1.0": { 26 | "downloadUrl": "http://localhost:8082/Blazemeter/CitrixPlugin/releases/download/v1.1.0/bzm-jmeter-citrix-plugin-1.1.0.jar", 27 | "depends":["jmeter-core", "jmeter-components", "jmeter-http"] 28 | } 29 | } 30 | }] -------------------------------------------------------------------------------- /citrix-jmeter/plugin-metadata/descriptor.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "bzm-jmeter-citrix-plugin", 3 | "name": "BlazeMeter - Citrix Plugin", 4 | "description": "Support for Citrix protocol (only available for Microsoft Windows)", 5 | "screenshotUrl": "https://github.com/Blazemeter/CitrixPlugin/raw/master/citrix-jmeter/plugin-metadata/presentationScreenshot.png", 6 | "helpUrl": "https://github.com/Blazemeter/CitrixPlugin/blob/master/README.md", 7 | "vendor": "BlazeMeter", 8 | "markerClass": "com.blazemeter.jmeter.citrix.recorder.gui.CitrixRecorderGUI", 9 | "componentClasses": [ 10 | "com.blazemeter.jmeter.citrix.assertion.CitrixAssertion", 11 | "com.blazemeter.jmeter.citrix.assertion.gui.CitrixAssertionGui", 12 | "com.blazemeter.jmeter.citrix.assertion.CitrixSessionAssertion", 13 | "com.blazemeter.jmeter.citrix.assertion.gui.CitrixSessionAssertionGui", 14 | "com.blazemeter.jmeter.citrix.gui.CitrixResultRenderer", 15 | "com.blazemeter.jmeter.citrix.listener.CitrixIcaFileSaver", 16 | "com.blazemeter.jmeter.citrix.listener.gui.CitrixIcaFileSaverGui", 17 | "com.blazemeter.jmeter.citrix.recorder.CitrixRecorder", 18 | "com.blazemeter.jmeter.citrix.recorder.gui.CitrixRecorderGUI", 19 | "com.blazemeter.jmeter.citrix.sampler.StartApplicationSampler", 20 | "com.blazemeter.jmeter.citrix.sampler.gui.StartApplicationSamplerGUI", 21 | "com.blazemeter.jmeter.citrix.sampler.InteractionSampler", 22 | "com.blazemeter.jmeter.citrix.sampler.gui.CitrixSamplerGUI" 23 | ], 24 | "versions": { 25 | "0.6.0": { 26 | "downloadUrl": "https://github.com/Blazemeter/CitrixPlugin/releases/download/0.6.0/citrix-jmeter-0.6.0.jar", 27 | "depends":["jmeter-core", "jmeter-components", "jmeter-http"] 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /citrix-jmeter/plugin-metadata/presentationScreenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/citrix-jmeter/plugin-metadata/presentationScreenshot.png -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/assertion/CitrixSessionAssertion.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.assertion; 2 | 3 | import com.blazemeter.jmeter.citrix.clause.SessionState; 4 | import com.blazemeter.jmeter.citrix.client.CitrixClient; 5 | import com.blazemeter.jmeter.citrix.sampler.CitrixSessionHolder; 6 | import com.blazemeter.jmeter.citrix.utils.CitrixUtils; 7 | import java.io.Serializable; 8 | import java.text.MessageFormat; 9 | import org.apache.jmeter.assertions.Assertion; 10 | import org.apache.jmeter.assertions.AssertionResult; 11 | import org.apache.jmeter.samplers.SampleResult; 12 | import org.apache.jmeter.testelement.AbstractTestElement; 13 | 14 | /** 15 | * Checks if a Citrix session is open / closed. 16 | */ 17 | public class CitrixSessionAssertion extends AbstractTestElement implements Serializable, Assertion { 18 | 19 | /** 20 | * Key for storing expected state. 21 | */ 22 | public static final String STATE_KEY = "CitrixSessionAssertion.state"; // $NON-NLS-1$ 23 | /** 24 | * 25 | */ 26 | private static final long serialVersionUID = 3518438785145149054L; 27 | private static final MessageFormat STATE_MESSAGE_FORMAT = new MessageFormat( 28 | CitrixUtils.getResString("citrix_assertion_session_state", false)); //$NON-NLS-1$ 29 | 30 | /** 31 | * Returns the result of the Assertion. Here it checks whether the Sample took 32 | * to long to be considered successful. If so an AssertionResult containing a 33 | * FailureMessage will be returned. Otherwise the returned AssertionResult will 34 | * reflect the success of the Sample. 35 | */ 36 | @Override 37 | public AssertionResult getResult(SampleResult response) { 38 | AssertionResult result = new AssertionResult(getName()); 39 | result.setFailure(false); 40 | CitrixClient citrixClient = CitrixSessionHolder.getClient(); 41 | boolean connected = citrixClient != null && citrixClient.isConnected(); 42 | boolean success = (getExpectedState() == SessionState.OPEN) == connected; 43 | result.setFailure(!success); 44 | result.setFailureMessage( 45 | STATE_MESSAGE_FORMAT.format(new Object[] {getExpectedState(), 46 | connected ? SessionState.OPEN : SessionState.CLOSED})); 47 | return result; 48 | } 49 | 50 | /** 51 | * @return {@link SessionState} 52 | */ 53 | public SessionState getExpectedState() { 54 | return SessionState.valueOf(getPropertyAsString(STATE_KEY, SessionState.OPEN.name())); 55 | } 56 | 57 | /** 58 | * Set state. 59 | * 60 | * @param state {@link SessionState} 61 | */ 62 | public void setExpectedState(SessionState state) { 63 | setProperty(STATE_KEY, state.name()); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/assertion/gui/CitrixAssertionGUI.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.assertion.gui; 2 | 3 | import com.blazemeter.jmeter.citrix.assertion.CitrixAssertion; 4 | import com.blazemeter.jmeter.citrix.clause.CheckType; 5 | import com.blazemeter.jmeter.citrix.clause.gui.ClausePanel; 6 | import com.blazemeter.jmeter.citrix.utils.CitrixUtils; 7 | import com.blazemeter.jmeter.commons.BlazemeterLabsLogo; 8 | import java.awt.BorderLayout; 9 | import javax.swing.Box; 10 | import org.apache.jmeter.assertions.gui.AbstractAssertionGui; 11 | import org.apache.jmeter.testelement.TestElement; 12 | 13 | /** 14 | * GUI for {@link CitrixAssertion}. 15 | */ 16 | public class CitrixAssertionGUI extends AbstractAssertionGui { // NOSONAR Ignore Inheritance warning 17 | private static final long serialVersionUID = 1686121565577093423L; 18 | 19 | private ClausePanel pnlClause; 20 | 21 | public CitrixAssertionGUI() { 22 | init(); 23 | } 24 | 25 | private void init() { // WARNING: called from ctor so must not be overridden 26 | // (i.e. must be private or final) 27 | 28 | setLayout(new BorderLayout(0, 10)); 29 | setBorder(makeBorder()); 30 | 31 | Box box = Box.createVerticalBox(); 32 | box.add(makeTitlePanel()); 33 | box.add(Box.createVerticalStrut(10)); 34 | pnlClause = new ClausePanel(CheckType.ASSERTION_CHECKS, false); 35 | pnlClause.setTimeoutVisible(false); 36 | box.add(pnlClause); 37 | box.add(Box.createVerticalStrut(10)); 38 | box.add(new BlazemeterLabsLogo("https://github.com/Blazemeter/CitrixPlugin")); 39 | add(box, BorderLayout.NORTH); 40 | } 41 | 42 | @Override 43 | public String getStaticLabel() { 44 | return CitrixUtils.getResString(getLabelResource(), false); // $NON-NLS-1$ 45 | } 46 | 47 | @Override 48 | public String getLabelResource() { 49 | return "citrix_assertion_title"; //$NON-NLS-1$ 50 | } 51 | 52 | @Override 53 | public TestElement createTestElement() { 54 | CitrixAssertion el = new CitrixAssertion(); 55 | modifyTestElement(el); 56 | return el; 57 | } 58 | 59 | /** 60 | * Modifies a given TestElement to mirror the data in the gui components. 61 | * 62 | * @see org.apache.jmeter.gui.JMeterGUIComponent#modifyTestElement(TestElement) 63 | */ 64 | @Override 65 | public void modifyTestElement(TestElement el) { 66 | configureTestElement(el); 67 | CitrixAssertion assertion = (CitrixAssertion) el; 68 | pnlClause.updateClause(); 69 | assertion.setClause(pnlClause.getClause()); 70 | } 71 | 72 | /** 73 | * A newly created component can be initialized with the contents of a Test 74 | * Element object by calling this method. The component is responsible for 75 | * querying the Test Element object for the relevant information to display in 76 | * its GUI. 77 | * 78 | * @see org.apache.jmeter.gui.JMeterGUIComponent#configure(TestElement) 79 | */ 80 | @Override 81 | public void configure(TestElement el) { 82 | super.configure(el); 83 | CitrixAssertion assertion = (CitrixAssertion) el; 84 | pnlClause.setClause(assertion.getClause()); 85 | } 86 | 87 | /** 88 | * Implements JMeterGUIComponent.clearGui. 89 | */ 90 | @Override 91 | public void clearGui() { 92 | super.clearGui(); 93 | pnlClause.setClause(CitrixAssertion.createDefaultClause()); 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/clause/CheckResult.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.clause; 2 | 3 | import com.blazemeter.jmeter.citrix.client.CitrixClient.Snapshot; 4 | 5 | /** 6 | * Provides information on clause check. 7 | */ 8 | public class CheckResult { 9 | private final Object value; 10 | private final Snapshot snapshot; 11 | private final boolean successful; 12 | 13 | /** 14 | * Instantiates a new {@link CheckResult}. 15 | * 16 | * @param snapshot the snapshot used during this check 17 | * @param value the computed value during this check 18 | * @param successful true, if the check succeeded; false otherwise 19 | */ 20 | public CheckResult(Snapshot snapshot, Object value, boolean successful) { 21 | this.snapshot = snapshot; 22 | this.value = value; 23 | this.successful = successful; 24 | } 25 | 26 | /** 27 | * Gets the computed value during this check. 28 | * 29 | * @return the computed value during this check 30 | */ 31 | public Object getValue() { 32 | return value; 33 | } 34 | 35 | /** 36 | * Gets the snapshot used during this check. 37 | * 38 | * @return the snapshot used during this check 39 | */ 40 | public Snapshot getSnapshot() { 41 | return snapshot; 42 | } 43 | 44 | /** 45 | * Indicates whether the check succeeded. 46 | * 47 | * @return true, if the check succeeded; false otherwise 48 | */ 49 | public boolean isSuccessful() { 50 | return successful; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/clause/ClauseComputationException.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.clause; 2 | 3 | /** 4 | * Provides exception when clause value computation fails. 5 | */ 6 | public class ClauseComputationException extends Exception { 7 | 8 | private static final long serialVersionUID = 8096627550410319461L; 9 | 10 | /** 11 | * Instantiate a new {@link ClauseComputationException}. 12 | */ 13 | public ClauseComputationException() { 14 | } 15 | 16 | /** 17 | * Instantiate a new {@link ClauseComputationException}. 18 | * 19 | * @param message the description of the error 20 | */ 21 | public ClauseComputationException(String message) { 22 | super(message); 23 | } 24 | 25 | /** 26 | * Instantiate a new {@link ClauseComputationException}. 27 | * 28 | * @param cause the cause of this error 29 | */ 30 | public ClauseComputationException(Throwable cause) { 31 | super(cause); 32 | } 33 | 34 | /** 35 | * Instantiate a new {@link ClauseComputationException}. 36 | * 37 | * @param message the description of the error 38 | * @param cause the cause of this error 39 | */ 40 | public ClauseComputationException(String message, Throwable cause) { 41 | super(message, cause); 42 | } 43 | 44 | /** 45 | * Instantiate a new {@link ClauseComputationException}. 46 | * 47 | * @param message the description of the error 48 | * @param cause the cause of this error 49 | * @param enableSuppression whether or not suppression is enabled or disabled 50 | * @param writableStackTrace whether or not the stack trace should be writable 51 | */ 52 | public ClauseComputationException(String message, Throwable cause, boolean enableSuppression, 53 | boolean writableStackTrace) { 54 | super(message, cause, enableSuppression, writableStackTrace); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/clause/SessionState.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.clause; 2 | 3 | /** 4 | * Enumerates the Citrix session states. 5 | */ 6 | public enum SessionState { 7 | /** 8 | * The Citrix session is open. 9 | */ 10 | OPEN, 11 | 12 | /** 13 | * The Citrix session is closed. 14 | */ 15 | CLOSED 16 | } 17 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/clause/strategy/check/ClientChecker.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.clause.strategy.check; 2 | 3 | import com.blazemeter.jmeter.citrix.clause.CheckResult; 4 | import com.blazemeter.jmeter.citrix.clause.ClauseComputationException; 5 | import com.blazemeter.jmeter.citrix.client.CitrixClient; 6 | import com.blazemeter.jmeter.citrix.client.CitrixClientException; 7 | 8 | /** 9 | * Represents a method used to check clause while Citrix client polling. 10 | */ 11 | public interface ClientChecker { 12 | 13 | /** 14 | * Gets a check result based on the specified polling context. 15 | * 16 | * @param client the Citrix client to use 17 | * @param context the polling context 18 | * @return the result of the clause check 19 | * @throws CitrixClientException when Citrix client fails to operate 20 | * @throws ClauseComputationException when clause computation fails 21 | */ 22 | CheckResult check(CitrixClient client, PollingContext context) 23 | throws CitrixClientException, ClauseComputationException; 24 | } 25 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/clause/strategy/check/DiffChecker.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.clause.strategy.check; 2 | 3 | import com.blazemeter.jmeter.citrix.clause.CheckResult; 4 | import java.util.Objects; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | /** 9 | * Provides a {@link ClientChecker} that can detect difference on Citrix session 10 | * screen. 11 | */ 12 | public class DiffChecker extends AbstractScreenChecker { 13 | 14 | private static final Logger LOGGER = LoggerFactory.getLogger(DiffChecker.class); 15 | 16 | /** 17 | * Instantiates a new {@link DiffChecker}. 18 | * 19 | * @param imageAssessor the function called to do screenshot assessment 20 | */ 21 | public DiffChecker(ScreenshotAssessor imageAssessor) { 22 | super(imageAssessor); 23 | } 24 | 25 | @Override 26 | protected boolean isSuccess(PollingContext context, String resultValue) { 27 | // Compare with the previous result if it exists 28 | final CheckResult previous = context.getPrevious(); 29 | final boolean result = previous != null && !Objects.equals(resultValue, previous.getValue()); 30 | if (LOGGER.isDebugEnabled()) { 31 | LOGGER.debug("'{}' differs from previous result '{}': {}", resultValue, 32 | (previous != null ? previous.getValue() : null), result); 33 | } 34 | 35 | return result; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/clause/strategy/check/DirectChecker.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.clause.strategy.check; 2 | 3 | import com.blazemeter.jmeter.citrix.clause.CheckResult; 4 | import com.blazemeter.jmeter.citrix.clause.ClauseComputationException; 5 | import com.blazemeter.jmeter.citrix.client.CitrixClient.Snapshot; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | /** 10 | * Provides a {@link ClientChecker} that can do assessment on Citrix session 11 | * screen. 12 | */ 13 | public class DirectChecker extends AbstractScreenChecker implements SnapshotChecker { 14 | 15 | private static final Logger LOGGER = LoggerFactory.getLogger(DirectChecker.class); 16 | 17 | /** 18 | * Instantiates a new {@link DirectChecker}. 19 | * 20 | * @param imageAssessor the function called to do screenshot assessment 21 | */ 22 | public DirectChecker(ScreenshotAssessor imageAssessor) { 23 | super(imageAssessor); 24 | } 25 | 26 | @Override 27 | protected boolean isSuccess(PollingContext context, String resultValue) { 28 | // Using value predicate from the polling context 29 | final boolean success = context.getValuePredicate().test(resultValue); 30 | LOGGER.debug("{} matches the expected value: {}", resultValue, success); 31 | return success; 32 | } 33 | 34 | @Override 35 | public CheckResult check(Snapshot snapshot, PollingContext context) 36 | throws ClauseComputationException { 37 | return checkSnapshot(snapshot, context); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/clause/strategy/check/PollingContext.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.clause.strategy.check; 2 | 3 | import com.blazemeter.jmeter.citrix.clause.CheckResult; 4 | import com.blazemeter.jmeter.citrix.clause.Clause; 5 | import java.awt.Rectangle; 6 | import java.util.function.Predicate; 7 | 8 | /** 9 | * Provides a context shared by each clause checking while polling. 10 | *

11 | * This class allows to clause checks to be compliant with the current clause 12 | * definition. 13 | */ 14 | public class PollingContext { 15 | private final Predicate valuePredicate; 16 | private final AreaSelector areaSelector; 17 | private final Clause clause; 18 | private CheckResult previous = null; 19 | 20 | /** 21 | * Instantiates a new {@link PollingContext}. 22 | * 23 | * @param valuePredicate the predicate used to evaluate the clause check result 24 | * @param areaSelector the screenshot area selector 25 | * @param clause the Clause 26 | */ 27 | public PollingContext(Predicate valuePredicate, AreaSelector areaSelector, 28 | Clause clause) { 29 | this.valuePredicate = valuePredicate; 30 | this.areaSelector = areaSelector; 31 | this.clause = clause; 32 | } 33 | 34 | /** 35 | * Gets the predicate used to evaluate the clause check result. 36 | *

37 | * Can be null if the current checking strategy does not use 38 | * {@link Clause#getExpectedValue() expected value} 39 | * 40 | * @return the predicate used to evaluate the clause check result 41 | */ 42 | public Predicate getValuePredicate() { 43 | return valuePredicate; 44 | } 45 | 46 | /** 47 | * Gets the screenshot area selector. 48 | * 49 | * @return the screenshot area selector 50 | */ 51 | public AreaSelector getAreaSelector() { 52 | return areaSelector; 53 | } 54 | 55 | /** 56 | * Gets the previous check result. 57 | * 58 | * @return the previous check result 59 | */ 60 | public CheckResult getPrevious() { 61 | return previous; 62 | } 63 | 64 | /** 65 | * Sets the previous check result. 66 | * 67 | * @param previous the previous check result to set 68 | */ 69 | public void setPrevious(CheckResult previous) { 70 | this.previous = previous; 71 | } 72 | 73 | public Clause getClause() { 74 | return this.clause; 75 | } 76 | 77 | /** 78 | * Represents a screenshot area selector. 79 | */ 80 | public interface AreaSelector { 81 | /** 82 | * Gets selection based on the specified foreground area. 83 | * 84 | * @param fgArea the foreground area 85 | * @return the area selection 86 | */ 87 | Rectangle select(Rectangle fgArea); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/clause/strategy/check/ScreenshotAssessor.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.clause.strategy.check; 2 | 3 | import com.blazemeter.jmeter.citrix.clause.ClauseComputationException; 4 | import java.awt.Rectangle; 5 | import java.awt.image.BufferedImage; 6 | 7 | /** 8 | * Represents a function to call when computing clause value from a single 9 | * screenshot. 10 | */ 11 | public interface ScreenshotAssessor { 12 | 13 | /** 14 | * Does assessment on the specified image. 15 | * 16 | * @param screenshot the screenshot used as source 17 | * @param selection the sub area where to do computation; null for entire image 18 | * @param context the context 19 | * @return the computed value of the clause 20 | * @throws ClauseComputationException when computation fails 21 | */ 22 | String assess(BufferedImage screenshot, Rectangle selection, PollingContext context) 23 | throws ClauseComputationException; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/clause/strategy/check/SnapshotChecker.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.clause.strategy.check; 2 | 3 | import com.blazemeter.jmeter.citrix.clause.CheckResult; 4 | import com.blazemeter.jmeter.citrix.clause.ClauseComputationException; 5 | import com.blazemeter.jmeter.citrix.client.CitrixClient.Snapshot; 6 | 7 | /** 8 | * Represents a method used to check clause using a snapshot while polling 9 | * Citrix client state. 10 | */ 11 | public interface SnapshotChecker { 12 | 13 | /** 14 | * Gets the result a clause check from the specified snapshot. 15 | * 16 | * @param snapshot the snapshot to used to get screen info 17 | * @param context the current polling context 18 | * @return the result a clause check from the specified snapshot 19 | * @throws ClauseComputationException when clause computation fails 20 | */ 21 | CheckResult check(Snapshot snapshot, PollingContext context) throws ClauseComputationException; 22 | } 23 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/clause/strategy/format/AssessmentFormatter.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.clause.strategy.format; 2 | 3 | public interface AssessmentFormatter { 4 | String execute(Object value); 5 | } 6 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/clause/strategy/format/DiffResultFormatter.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.clause.strategy.format; 2 | 3 | import com.blazemeter.jmeter.citrix.clause.CheckResult; 4 | import com.blazemeter.jmeter.citrix.clause.Clause; 5 | 6 | /** 7 | * Provides a check result formatter dedicated to displaying change 8 | * detection between two screenshots. 9 | */ 10 | public class DiffResultFormatter implements ResultFormatter { 11 | 12 | @Override 13 | public String execute(CheckResult result, CheckResult previous, Clause clause, int index) { 14 | String value; 15 | if (previous == null) { 16 | // Dedicated message while no previous result exists 17 | value = "Unable to identify a change that occurred at the first valid check"; 18 | } else { 19 | if (result.isSuccessful()) { 20 | value = "Change detected : '" + result.getValue() + "' differs from previous '" + 21 | previous.getValue() 22 | + "'"; 23 | } else { 24 | value = "No change detected : '" + result.getValue() + "' equals to previous '" + 25 | previous.getValue() 26 | + "'"; 27 | } 28 | } 29 | return value; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/clause/strategy/format/RegularAssessmentFormatter.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.clause.strategy.format; 2 | 3 | public class RegularAssessmentFormatter implements AssessmentFormatter { 4 | 5 | @Override 6 | public String execute(Object value) { 7 | return value != null ? value.toString() : null; 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/clause/strategy/format/RegularResultFormatter.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.clause.strategy.format; 2 | 3 | import com.blazemeter.jmeter.citrix.clause.CheckResult; 4 | import com.blazemeter.jmeter.citrix.clause.Clause; 5 | 6 | /** 7 | * Provides a check result formatter dedicated to displaying the correspondence 8 | * with the expected value. 9 | */ 10 | public class RegularResultFormatter implements ResultFormatter { 11 | 12 | @Override 13 | public String execute(CheckResult result, CheckResult previous, Clause clause, int index) { 14 | String value; 15 | if (result.isSuccessful()) { 16 | if (clause.isUsingRegex()) { 17 | value = "'" + result.getValue() + "' matches the expecting regular expression '" 18 | + clause.getExpectedValueParametrized() + "'"; 19 | } else { 20 | value = "'" + result.getValue() + "' is equals to the expecting value '" + 21 | clause.getExpectedValueParametrized() 22 | + "'"; 23 | } 24 | } else { 25 | if (clause.isUsingRegex()) { 26 | value = "'" + result.getValue() + "' does not match the expecting regular expression '" 27 | + clause.getExpectedValueParametrized() + "'"; 28 | } else { 29 | value = "'" + result.getValue() + "' differs from the expecting value '" + 30 | clause.getExpectedValueParametrized() 31 | + "'"; 32 | } 33 | } 34 | return value; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/clause/strategy/format/ResultFormatter.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.clause.strategy.format; 2 | 3 | import com.blazemeter.jmeter.citrix.clause.CheckResult; 4 | import com.blazemeter.jmeter.citrix.clause.Clause; 5 | 6 | /** 7 | * Represents a method used to format a clause check result. 8 | */ 9 | public interface ResultFormatter { 10 | 11 | /** 12 | * Run the method to format a clause check result. 13 | * 14 | * @param result the result to format 15 | * @param previous the previous result 16 | * @param clause the checked clause 17 | * @param index the rank of the check 18 | * @return A formatted message describing the check result 19 | */ 20 | String execute(CheckResult result, CheckResult previous, Clause clause, int index); 21 | } 22 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/clause/strategy/format/WindowEventAssessmentFormatter.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.clause.strategy.format; 2 | 3 | import com.blazemeter.jmeter.citrix.client.WindowInfo; 4 | import com.blazemeter.jmeter.citrix.client.events.WindowEvent; 5 | 6 | public class WindowEventAssessmentFormatter implements AssessmentFormatter { 7 | 8 | @Override 9 | public String execute(Object value) { 10 | String result = null; 11 | if (value instanceof WindowEvent) { 12 | WindowEvent event = (WindowEvent) value; 13 | WindowInfo info = event.getWindowInfo(); 14 | result = info != null ? info.getCaption() : null; 15 | } 16 | return result; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/clause/strategy/format/WindowEventResultFormatter.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.clause.strategy.format; 2 | 3 | import com.blazemeter.jmeter.citrix.clause.CheckResult; 4 | import com.blazemeter.jmeter.citrix.clause.Clause; 5 | import com.blazemeter.jmeter.citrix.client.WindowInfo; 6 | import com.blazemeter.jmeter.citrix.client.events.WindowEvent; 7 | 8 | /** 9 | * Provides a check result formatter dedicated to displaying to displaying 10 | * window events that have occurred. 11 | */ 12 | public class WindowEventResultFormatter implements ResultFormatter { 13 | 14 | private final String expectedState; 15 | 16 | public WindowEventResultFormatter(String expectedState) { 17 | this.expectedState = expectedState; 18 | } 19 | 20 | // Format the specified window event 21 | private static String stringify(WindowEvent event) { 22 | String value; 23 | WindowInfo info = event.getWindowInfo(); 24 | if (info != null) { 25 | value = "'" + event.getWindowState() + "' event occured on window with caption '" + 26 | info.getCaption() + "'"; 27 | } else { 28 | value = "'" + event.getWindowState() + "' event occured"; 29 | } 30 | return value; 31 | } 32 | 33 | @Override 34 | public String execute(CheckResult result, CheckResult previous, Clause clause, int index) { 35 | Object resultValue = result.getValue(); 36 | if (!(resultValue instanceof WindowEvent)) { 37 | throw new IllegalArgumentException("result must have value property of type WindowEvent."); 38 | } 39 | WindowEvent event = (WindowEvent) resultValue; 40 | String value; 41 | if (result.isSuccessful()) { 42 | value = "The expected " + stringify(event); 43 | } else { 44 | if (clause.isUsingRegex()) { 45 | value = stringify(event) + " whereas expecting '" + expectedState 46 | + "' on window with caption matching regular pattern '" + clause.getExpectedValue() + 47 | "'"; 48 | } else { 49 | value = 50 | stringify(event) + " whereas expecting '" + expectedState + "' on window with caption '" 51 | + clause.getExpectedValue() + "'"; 52 | } 53 | } 54 | return value; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/client/CitrixClientFactoryException.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client; 2 | 3 | public class CitrixClientFactoryException extends Exception { 4 | private static final long serialVersionUID = 1L; 5 | 6 | public CitrixClientFactoryException(String message) { 7 | super(message); 8 | } 9 | 10 | public CitrixClientFactoryException(String message, Exception e) { 11 | super(message, e); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/client/CitrixClientFactoryHelper.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client; 2 | 3 | import com.blazemeter.jmeter.citrix.client.factory.CitrixClientFactory; 4 | import com.blazemeter.jmeter.citrix.utils.CitrixUtils; 5 | import java.lang.reflect.Constructor; 6 | import java.text.MessageFormat; 7 | import java.util.Properties; 8 | import org.apache.commons.lang3.SystemUtils; 9 | import org.apache.jmeter.util.JMeterUtils; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | /** 14 | * Client factory that returns the right client according to the specified one 15 | * in the jmeter.properties file. 16 | */ 17 | public class CitrixClientFactoryHelper { 18 | 19 | private static final Logger LOGGER = LoggerFactory.getLogger(CitrixClientFactoryHelper.class); 20 | 21 | private static final String FACTORY_PROPERTY = CitrixUtils.PROPERTIES_PFX + "client_factory"; 22 | private static final String CLIENT_PROPERTIES_PFX = FACTORY_PROPERTY + ".client_property."; 23 | private static final int CLIENT_PROPERTIES_PFX_LENGTH = CLIENT_PROPERTIES_PFX.length(); 24 | 25 | private static final String FACTORY_DEFAULT_WINDOWS = 26 | "com.blazemeter.jmeter.citrix.client.windows.WinCitrixClientFactory"; 27 | private static final String FACTORY_DEFAULT_OTHER = 28 | "com.blazemeter.jmeter.citrix.client.mock.MockCitrixClientFactory"; 29 | 30 | private static CitrixClientFactory instance; 31 | 32 | private CitrixClientFactoryHelper() { 33 | } 34 | 35 | /** 36 | *

37 | * Gets the singleton instance of the factory. 38 | *

39 | * 40 | * @return a factory defined on jmeter.properties 41 | * @throws CitrixClientFactoryException when the property is wrong 42 | */ 43 | public static synchronized CitrixClientFactory getInstance() throws CitrixClientFactoryException { 44 | if (instance == null) { 45 | Properties properties = JMeterUtils.getJMeterProperties(); 46 | String defaultValue = 47 | SystemUtils.IS_OS_WINDOWS ? FACTORY_DEFAULT_WINDOWS : FACTORY_DEFAULT_OTHER; 48 | String selectedClass = properties.getProperty(FACTORY_PROPERTY, defaultValue); 49 | try { 50 | Class clazz = Class.forName(selectedClass); 51 | Constructor constructor = clazz.getConstructor(); 52 | instance = (CitrixClientFactory) constructor.newInstance(); 53 | Properties clientProperties = new Properties(); 54 | for (String key : properties.stringPropertyNames()) { 55 | if (key.startsWith(CLIENT_PROPERTIES_PFX)) { 56 | clientProperties 57 | .put(key.substring(CLIENT_PROPERTIES_PFX_LENGTH), properties.getProperty(key)); 58 | } 59 | } 60 | instance.setClientProperties(clientProperties); 61 | } catch (Exception e) { 62 | String msg = MessageFormat 63 | .format("Unable to create client factory {0} from JMeter property {1}: {2}", 64 | selectedClass, FACTORY_PROPERTY, e.getMessage()); 65 | LOGGER.error(msg); 66 | throw new CitrixClientFactoryException(msg, e); 67 | } 68 | } 69 | return instance; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/client/SessionErrorLogger.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.client; 2 | 3 | import com.blazemeter.jmeter.citrix.client.events.SessionEvent; 4 | import com.blazemeter.jmeter.citrix.client.events.SessionEvent.EventType; 5 | import com.blazemeter.jmeter.citrix.client.events.SessionEvent.KnownError; 6 | import com.blazemeter.jmeter.citrix.client.handler.CitrixClientAdapter; 7 | import com.blazemeter.jmeter.citrix.utils.CitrixUtils; 8 | import java.util.Arrays; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | public class SessionErrorLogger extends CitrixClientAdapter { 13 | 14 | private static final Logger LOGGER = LoggerFactory.getLogger(SessionErrorLogger.class); 15 | 16 | private static KnownError lookupErrorByCode(int code) { 17 | return Arrays.stream(KnownError.values()).filter(e -> e.getCode() == code).findFirst() 18 | .orElse(null); 19 | } 20 | 21 | @Override 22 | public void handleSessionEvent(SessionEvent sessionEvent) { 23 | if (sessionEvent != null) { 24 | 25 | if (sessionEvent.getEventType() == EventType.ERROR) { 26 | final int code = sessionEvent.getErrorCode(); 27 | KnownError knownError = lookupErrorByCode(code); 28 | if (knownError == null) { 29 | LOGGER.error(CitrixUtils.getResString("session_error_logger_unknown_code_fmt", false), 30 | code); 31 | } else { 32 | switch (knownError) { 33 | case UNAVAILABLE_SESSION: 34 | LOGGER.error( 35 | CitrixUtils.getResString("session_error_logger_unavailable_session", false)); 36 | break; 37 | case NO_ERROR: 38 | default: 39 | // NOOP 40 | } 41 | } 42 | } else { 43 | LOGGER.debug("Session Event Type {} Code {}", sessionEvent.getEventType(), 44 | sessionEvent.getErrorCode()); 45 | } 46 | } 47 | } 48 | } 49 | 50 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/extractor/AssessmentExtractor.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.extractor; 2 | 3 | import com.blazemeter.jmeter.citrix.sampler.CitrixSampleResult; 4 | import org.apache.commons.lang3.StringUtils; 5 | import org.apache.jmeter.processor.PostProcessor; 6 | import org.apache.jmeter.samplers.SampleResult; 7 | import org.apache.jmeter.testelement.AbstractScopedTestElement; 8 | import org.apache.jmeter.threads.JMeterContext; 9 | import org.apache.jmeter.threads.JMeterVariables; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | public class AssessmentExtractor extends AbstractScopedTestElement implements PostProcessor { 14 | 15 | private static final Logger LOGGER = LoggerFactory.getLogger(AssessmentExtractor.class); 16 | 17 | private static final long serialVersionUID = -293822356913142746L; 18 | 19 | private static final String PROP_DEFAULT_VALUE = "AssessmentExtractor.defaultValue"; 20 | private static final String PROP_EMPTY_DEFAULT_VALUE = "AssessmentExtractor.emptyDefaultValue"; 21 | private static final String PROP_REF_NAME = "AssessmentExtractor.refName"; 22 | 23 | @Override 24 | public void process() { 25 | JMeterContext context = getThreadContext(); 26 | SampleResult previousResult = context.getPreviousResult(); 27 | if (previousResult instanceof CitrixSampleResult) { 28 | LOGGER.debug("Working on Citrix sample result"); 29 | CitrixSampleResult result = (CitrixSampleResult) previousResult; 30 | JMeterVariables vars = context.getVariables(); 31 | 32 | // Get variable name to populate 33 | final String refName = getRefName(); 34 | if (StringUtils.isBlank(refName)) { 35 | throw new IllegalArgumentException( 36 | "Variable name is required for AssessmentExtractor " + getName()); 37 | } 38 | 39 | // Get variable default value and put it in variable 40 | final String defaultValue = getDefaultValue(); 41 | if (StringUtils.isNotBlank(defaultValue) || isDefaultValueEmpty()) { 42 | LOGGER.debug("Sets default value '{}' to variable {}", defaultValue, refName); 43 | vars.put(refName, defaultValue); 44 | } 45 | 46 | // Extract assessment if it exists 47 | String assessment = result.getAssessment(); 48 | if (StringUtils.isNotBlank(assessment)) { 49 | LOGGER.debug("Sets value '{}' to variable {}", assessment, refName); 50 | vars.put(refName, assessment); 51 | } 52 | 53 | } else { 54 | LOGGER.debug("Only Citrix sample result are supported"); 55 | } 56 | } 57 | 58 | public String getDefaultValue() { 59 | return getPropertyAsString(PROP_DEFAULT_VALUE); 60 | } 61 | 62 | public void setDefaultValue(String defaultValue) { 63 | setProperty(PROP_DEFAULT_VALUE, defaultValue); 64 | } 65 | 66 | public boolean isDefaultValueEmpty() { 67 | return getPropertyAsBoolean(PROP_EMPTY_DEFAULT_VALUE); 68 | } 69 | 70 | public void setEmptyDefaultValue(boolean emptyDefaultValue) { 71 | setProperty(PROP_EMPTY_DEFAULT_VALUE, emptyDefaultValue); 72 | } 73 | 74 | public String getRefName() { 75 | return getPropertyAsString(PROP_REF_NAME); 76 | } 77 | 78 | public void setRefName(String refName) { 79 | setProperty(PROP_REF_NAME, refName); 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/gui/AreaChangedEvent.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.gui; 2 | 3 | import java.awt.Rectangle; 4 | import java.util.EventObject; 5 | 6 | /** 7 | * Provides event triggered when a property of type Rectangle is changed. 8 | */ 9 | public class AreaChangedEvent extends EventObject { 10 | 11 | private static final long serialVersionUID = -6345258791738580747L; 12 | 13 | private final Rectangle area; 14 | 15 | /** 16 | * Instantiates a new {@link AreaChangedEvent}. 17 | * 18 | * @param source the source of the event 19 | * @param area the new value of the Rectangle property 20 | */ 21 | public AreaChangedEvent(Object source, Rectangle area) { 22 | super(source); 23 | this.area = area; 24 | } 25 | 26 | /** 27 | * Gets the new value of the Rectangle property. 28 | * 29 | * @return the new value of the Rectangle property 30 | */ 31 | public Rectangle getArea() { 32 | return area; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/gui/BlazeMeterLabsLogo.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.gui; 2 | 3 | import java.awt.Cursor; 4 | import java.awt.Desktop; 5 | import java.awt.Graphics; 6 | import java.awt.event.MouseAdapter; 7 | import java.awt.event.MouseEvent; 8 | import java.io.IOException; 9 | import java.net.URI; 10 | import java.net.URISyntaxException; 11 | import javax.swing.GroupLayout; 12 | import javax.swing.ImageIcon; 13 | import javax.swing.JLabel; 14 | import javax.swing.JPanel; 15 | import javax.swing.UIManager; 16 | import org.slf4j.Logger; 17 | import org.slf4j.LoggerFactory; 18 | 19 | public class BlazeMeterLabsLogo extends JPanel { 20 | 21 | private static final long serialVersionUID = -2926310622121776666L; 22 | private static final Logger LOG = LoggerFactory 23 | .getLogger(com.blazemeter.jmeter.citrix.gui.BlazeMeterLabsLogo.class); 24 | private static final ImageIcon DEFAULT_LOGO = new ImageIcon( 25 | BlazeMeterLabsLogo.class.getResource("/com/blazemeter/labs-logo/blazemeter-labs-logo.png")); 26 | private static final ImageIcon DARK_LOGO = new ImageIcon( 27 | BlazeMeterLabsLogo.class 28 | .getResource("/com/blazemeter/labs-logo/blazemeter-labs-light-logo.png")); 29 | private static final String URL_TO_BROWSE = "https://github.com/Blazemeter/CitrixPlugin"; 30 | 31 | private final JLabel blazeMeterLabsLogo; 32 | 33 | public BlazeMeterLabsLogo() { 34 | blazeMeterLabsLogo = new JLabel(DEFAULT_LOGO); 35 | setBrowseOnClick(URL_TO_BROWSE); 36 | GroupLayout blazeMeterLabsLogoLayout = new GroupLayout(this); 37 | setLayout(blazeMeterLabsLogoLayout); 38 | blazeMeterLabsLogoLayout.setHorizontalGroup(blazeMeterLabsLogoLayout 39 | .createParallelGroup(GroupLayout.Alignment.CENTER).addComponent(blazeMeterLabsLogo)); 40 | blazeMeterLabsLogoLayout.setVerticalGroup(blazeMeterLabsLogoLayout 41 | .createParallelGroup(GroupLayout.Alignment.CENTER).addComponent(blazeMeterLabsLogo)); 42 | } 43 | 44 | @Override 45 | public void paint(Graphics g) { 46 | blazeMeterLabsLogo 47 | .setIcon("Darcula".equals(UIManager.getLookAndFeel().getID()) ? DARK_LOGO : DEFAULT_LOGO); 48 | super.paint(g); 49 | } 50 | 51 | private void setBrowseOnClick(String url) { 52 | blazeMeterLabsLogo.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); 53 | blazeMeterLabsLogo.addMouseListener(new MouseAdapter() { 54 | @Override 55 | public void mouseClicked(MouseEvent mouseEvent) { 56 | if (Desktop.isDesktopSupported()) { 57 | try { 58 | Desktop.getDesktop().browse(new URI(url)); 59 | } catch (IOException | URISyntaxException exception) { 60 | LOG.error("Problem when accessing repository", exception); 61 | } 62 | } 63 | } 64 | }); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/gui/SelectionChangedListener.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.gui; 2 | 3 | import java.util.EventListener; 4 | 5 | public interface SelectionChangedListener extends EventListener { 6 | void onSelectionChanged(AreaChangedEvent event); 7 | } 8 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/gui/SelectionChangedManager.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.gui; 2 | 3 | import java.awt.Rectangle; 4 | import javax.swing.event.EventListenerList; 5 | 6 | public class SelectionChangedManager implements SelectionChangedSubject { 7 | 8 | private final EventListenerList listenerList; 9 | 10 | public SelectionChangedManager(EventListenerList listenerList) { 11 | if (listenerList == null) { 12 | throw new IllegalArgumentException("listeners cannot be null."); 13 | } 14 | this.listenerList = listenerList; 15 | } 16 | 17 | @Override 18 | public void addSelectionChangedListener(SelectionChangedListener listener) { 19 | listenerList.add(SelectionChangedListener.class, listener); 20 | } 21 | 22 | @Override 23 | public void removeSelectionChangedListener(SelectionChangedListener listener) { 24 | listenerList.remove(SelectionChangedListener.class, listener); 25 | } 26 | 27 | public void trigger(Rectangle selection) { 28 | SelectionChangedListener[] listeners = 29 | listenerList.getListeners(SelectionChangedListener.class); 30 | for (SelectionChangedListener listener : listeners) { 31 | listener.onSelectionChanged( 32 | new AreaChangedEvent(this, selection != null ? new Rectangle(selection) : null)); 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/gui/SelectionChangedSubject.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.gui; 2 | 3 | public interface SelectionChangedSubject { 4 | 5 | void addSelectionChangedListener(SelectionChangedListener listener); 6 | 7 | void removeSelectionChangedListener(SelectionChangedListener listener); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/gui/SelectionPanel.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.gui; 2 | 3 | import java.awt.Dimension; 4 | import java.awt.GridBagConstraints; 5 | import java.awt.GridBagLayout; 6 | import java.awt.Point; 7 | import java.awt.Rectangle; 8 | import java.util.Objects; 9 | import javax.swing.JPanel; 10 | 11 | public class SelectionPanel extends JPanel implements SelectionChangedSubject { 12 | 13 | private static final long serialVersionUID = -4081910650471400803L; 14 | 15 | private final transient SelectionChangedManager selectionChangedManager = 16 | new SelectionChangedManager(listenerList); 17 | private boolean editable = true; 18 | private Rectangle selection; 19 | 20 | private PositionPanel pnlPosition; 21 | private DimensionPanel pnlDimension; 22 | 23 | public SelectionPanel() { 24 | initialize(); 25 | } 26 | 27 | @Override 28 | public void setEnabled(boolean enabled) { 29 | super.setEnabled(enabled); 30 | pnlDimension.setEnabled(enabled); 31 | pnlPosition.setEnabled(enabled); 32 | } 33 | 34 | public boolean isEditable() { 35 | return editable; 36 | } 37 | 38 | public void setEditable(boolean editable) { 39 | this.editable = editable; 40 | 41 | pnlPosition.setEditable(editable); 42 | pnlDimension.setEditable(editable); 43 | } 44 | 45 | public Rectangle getSelection() { 46 | return selection; 47 | } 48 | 49 | public void setSelection(Rectangle selection) { 50 | if (selection != null) { 51 | pnlPosition.setPosition(selection.getLocation()); 52 | pnlDimension.setDimension(selection.getSize()); 53 | } else { 54 | pnlPosition.setPosition(null); 55 | pnlDimension.setDimension(null); 56 | } 57 | updateSelection(); 58 | } 59 | 60 | public void updateSelection() { 61 | Point position = pnlPosition.getPosition(); 62 | Dimension dimension = pnlDimension.getDimension(); 63 | Rectangle newSelection; 64 | if (position != null && dimension != null) { 65 | newSelection = new Rectangle(position.x, position.y, dimension.width, dimension.height); 66 | } else { 67 | newSelection = null; 68 | } 69 | if (!Objects.equals(selection, newSelection)) { 70 | selection = newSelection; 71 | selectionChangedManager.trigger(selection); 72 | } 73 | } 74 | 75 | private void initialize() { 76 | setLayout(new GridBagLayout()); 77 | 78 | pnlPosition = new PositionPanel(); 79 | pnlPosition.addPositionChangedListener(e -> updateSelection()); 80 | GridBagConstraints gbcPosition = new GridBagConstraints(); 81 | gbcPosition.fill = GridBagConstraints.HORIZONTAL; 82 | gbcPosition.weightx = 1d; 83 | add(pnlPosition, gbcPosition); 84 | 85 | pnlDimension = new DimensionPanel(); 86 | pnlDimension.addDimensionChangedListener(e -> updateSelection()); 87 | GridBagConstraints gbcDimension = new GridBagConstraints(); 88 | gbcDimension.fill = GridBagConstraints.HORIZONTAL; 89 | gbcDimension.weightx = 1d; 90 | add(pnlDimension, gbcDimension); 91 | } 92 | 93 | @Override 94 | public void addSelectionChangedListener(SelectionChangedListener listener) { 95 | selectionChangedManager.addSelectionChangedListener(listener); 96 | } 97 | 98 | @Override 99 | public void removeSelectionChangedListener(SelectionChangedListener listener) { 100 | selectionChangedManager.removeSelectionChangedListener(listener); 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/installer/StreamGobbler.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.installer; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.InputStreamReader; 7 | import org.apache.commons.lang3.exception.ExceptionUtils; 8 | 9 | /** 10 | * Gobbles output of Stderr / Stdout when using Runtime.exec(). 11 | */ 12 | public class StreamGobbler extends Thread { 13 | private final InputStream is; 14 | private String result; 15 | private String exceptionResult; 16 | 17 | public StreamGobbler(InputStream is) { 18 | this.is = is; 19 | } 20 | 21 | /** 22 | * @see java.lang.Thread#run() 23 | */ 24 | @Override 25 | public void run() { 26 | StringBuilder buffer = new StringBuilder(); 27 | try (InputStreamReader isr = new InputStreamReader(is); 28 | BufferedReader br = new BufferedReader(isr)) { 29 | String line; 30 | while ((line = br.readLine()) != null) { 31 | buffer.append(line).append("\n"); 32 | } 33 | result = buffer.toString(); 34 | } catch (IOException ioe) { 35 | exceptionResult = ExceptionUtils.getStackTrace(ioe); 36 | } 37 | } 38 | 39 | /** 40 | * @return String Result 41 | */ 42 | public String getResult() { 43 | return result + (exceptionResult == null ? "" : ", exception:" + exceptionResult); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/installer/WinRegistry.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.installer; 2 | 3 | import com.sun.jna.platform.win32.Advapi32; 4 | import com.sun.jna.platform.win32.Advapi32Util; 5 | import com.sun.jna.platform.win32.Win32Exception; 6 | import com.sun.jna.platform.win32.WinNT; 7 | import com.sun.jna.platform.win32.WinReg; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | public class WinRegistry { 12 | 13 | public static final WinReg.HKEY HKEY_LOCAL_MACHINE = WinReg.HKEY_LOCAL_MACHINE; 14 | private static final int ERROR_CODE_ACCESS_DENIED = 5; 15 | 16 | private static final Logger LOGGER = LoggerFactory.getLogger(WinRegistry.class); 17 | 18 | /** 19 | * Reads value for the key from given path. 20 | * 21 | * @param hKey HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE 22 | * @param path Path to key 23 | * @param key Key name 24 | * @return String value 25 | */ 26 | public static String getValueForKey(WinReg.HKEY hKey, String path, String key) { 27 | Object value = Advapi32Util.registryGetValue(hKey, path, key); 28 | return value != null ? String.valueOf(value) : ""; 29 | } 30 | 31 | public static boolean setIntValueForKey(WinReg.HKEY hKey, String path, String key, int value) { 32 | try { 33 | if (!Advapi32Util.registryKeyExists(hKey, path)) { 34 | Advapi32Util.registryCreateKey(hKey, path); 35 | } 36 | Advapi32Util.registrySetIntValue(hKey, path, key, value); 37 | return true; 38 | } catch (Win32Exception ex) { 39 | if (ex.getErrorCode() != ERROR_CODE_ACCESS_DENIED) { 40 | LOGGER.error("Unknown error setting Registry value:", ex); 41 | } 42 | return false; 43 | } 44 | } 45 | 46 | public static boolean isAdmin() { 47 | Advapi32Util.Account[] groups = Advapi32Util.getCurrentUserGroups(); 48 | for (Advapi32Util.Account group : groups) { 49 | WinNT.PSIDByReference sid = new WinNT.PSIDByReference(); 50 | Advapi32.INSTANCE.ConvertStringSidToSid(group.sidString, sid); 51 | if (Advapi32.INSTANCE.IsWellKnownSid(sid.getValue(), 52 | WinNT.WELL_KNOWN_SID_TYPE.WinBuiltinAdministratorsSid)) { 53 | return true; 54 | } 55 | } 56 | return false; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/ocr/OcrException.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.ocr; 2 | 3 | /** 4 | * OCR Related exception. 5 | */ 6 | public class OcrException extends Exception { 7 | 8 | private static final long serialVersionUID = 706759572008574062L; 9 | 10 | /** 11 | * Instantiates a new {@link OcrException}. 12 | */ 13 | public OcrException() { 14 | super(); 15 | } 16 | 17 | /** 18 | * Instantiates a new {@link OcrException}. 19 | * 20 | * @param message the description of the error 21 | */ 22 | public OcrException(String message) { 23 | super(message); 24 | } 25 | 26 | /** 27 | * Instantiates a new {@link OcrException}. 28 | * 29 | * @param cause the cause of this error 30 | */ 31 | public OcrException(Throwable cause) { 32 | super(cause); 33 | } 34 | 35 | /** 36 | * Instantiates a new {@link OcrException}. 37 | * 38 | * @param message the description of the error 39 | * @param cause the cause of this error 40 | */ 41 | public OcrException(String message, Throwable cause) { 42 | super(message, cause); 43 | } 44 | 45 | /** 46 | * Instantiates a new {@link OcrException}. 47 | * 48 | * @param message the description of the error 49 | * @param cause the cause of this error 50 | * @param enableSuppression whether or not suppression is enabled or disabled 51 | * @param writableStackTrace whether or not the stack trace should be writable 52 | */ 53 | public OcrException(String message, Throwable cause, boolean enableSuppression, 54 | boolean writableStackTrace) { 55 | super(message, cause, enableSuppression, writableStackTrace); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/ocr/OcrManagerHolder.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.ocr; 2 | 3 | /** 4 | * Holds the OCR manager. 5 | */ 6 | public class OcrManagerHolder { 7 | 8 | protected static final ThreadLocal LOCAL_OCR = 9 | ThreadLocal.withInitial(OcrManager::new); 10 | 11 | private OcrManagerHolder() { 12 | super(); 13 | } 14 | 15 | /** 16 | * Gets the held {@link OcrManager}. 17 | * 18 | * @return held {@link OcrManager} 19 | */ 20 | public static OcrManager getManager() { 21 | return LOCAL_OCR.get(); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/recorder/CaptureItem.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.recorder; 2 | 3 | import com.blazemeter.jmeter.citrix.client.events.InteractionEvent; 4 | 5 | /** 6 | * Capture items are labeled Citrix interaction events. 7 | */ 8 | public class CaptureItem { 9 | private final InteractionEvent event; 10 | private String label; 11 | 12 | /** 13 | * Instantiates a new {@link CaptureItem} for the specified event. 14 | * 15 | * @param event the Citrix interaction event to encapsulate 16 | */ 17 | public CaptureItem(InteractionEvent event) { 18 | if (event == null) { 19 | throw new IllegalArgumentException("event cannot be null."); 20 | } 21 | this.event = event; 22 | } 23 | 24 | /** 25 | * Gets the label of this capture. 26 | * 27 | * @return the label of this capture 28 | */ 29 | public String getLabel() { 30 | return label; 31 | } 32 | 33 | /** 34 | * Defines the label of this capture. 35 | * 36 | * @param label the label to use 37 | */ 38 | public void setLabel(String label) { 39 | this.label = label; 40 | } 41 | 42 | /** 43 | * Gets the inner Citrix interaction event. 44 | * 45 | * @return the inner Citrix interaction event 46 | */ 47 | public InteractionEvent getEvent() { 48 | return event; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/recorder/CaptureLimitException.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.recorder; 2 | 3 | /** 4 | * Provides exception when capture size exceeds. 5 | */ 6 | public class CaptureLimitException extends Exception { 7 | 8 | private static final long serialVersionUID = 8096627550410319461L; 9 | 10 | private final int size; 11 | 12 | /** 13 | * Instantiate a new {@link CaptureLimitException}. 14 | * 15 | * @param size current size of the capture 16 | * @param message the description of the error 17 | * @param cause the cause of this error 18 | * @param enableSuppression whether or not suppression is enabled or disabled 19 | * @param writableStackTrace whether or not the stack trace should be writable 20 | */ 21 | public CaptureLimitException(int size, String message, Throwable cause, boolean enableSuppression, 22 | boolean writableStackTrace) { 23 | super(message, cause, enableSuppression, writableStackTrace); 24 | this.size = size; 25 | } 26 | 27 | /** 28 | * Instantiate a new {@link CaptureLimitException}. 29 | * 30 | * @param size current size of the capture 31 | * @param message the description of the error 32 | * @param cause the cause of this error 33 | */ 34 | public CaptureLimitException(int size, String message, Throwable cause) { 35 | super(message, cause); 36 | this.size = size; 37 | } 38 | 39 | /** 40 | * Instantiate a new {@link CaptureLimitException}. 41 | * 42 | * @param size current size of the capture 43 | * @param cause the cause of this error 44 | */ 45 | public CaptureLimitException(int size, Throwable cause) { 46 | super(cause); 47 | this.size = size; 48 | } 49 | 50 | /** 51 | * Instantiate a new {@link CaptureLimitException}. 52 | * 53 | * @param size current size of the capture 54 | * @param message the description of the error 55 | */ 56 | public CaptureLimitException(int size, String message) { 57 | super(message); 58 | this.size = size; 59 | } 60 | 61 | /** 62 | * Instantiate a new {@link CaptureLimitException}. 63 | * 64 | * @param size current size of the capture 65 | */ 66 | public CaptureLimitException(int size) { 67 | this.size = size; 68 | } 69 | 70 | public int getSize() { 71 | return size; 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/recorder/RecordingCitrixIcaFileSaver.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.recorder; 2 | 3 | import com.blazemeter.jmeter.citrix.listener.CitrixIcaFileSaver; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | import org.apache.jmeter.samplers.SampleEvent; 7 | import org.apache.jmeter.threads.JMeterVariables; 8 | 9 | /** 10 | * Child of {@link CitrixIcaFileSaver} that exists only to expose 11 | * the ICA variable to {@link CitrixRecorder}. 12 | */ 13 | public class RecordingCitrixIcaFileSaver extends CitrixIcaFileSaver { 14 | /** 15 | * 16 | */ 17 | private static final long serialVersionUID = 1L; 18 | private final List recordedIcaFiles = new ArrayList<>(); 19 | 20 | /** 21 | * 22 | */ 23 | public RecordingCitrixIcaFileSaver() { 24 | super(); 25 | } 26 | 27 | /** 28 | * @param name File name 29 | */ 30 | RecordingCitrixIcaFileSaver(String name) { 31 | super(name); 32 | } 33 | 34 | /** 35 | * @return the icaFile 36 | */ 37 | public String getRecordedIcaFile() { 38 | if (recordedIcaFiles.size() > 1) { 39 | throw new IllegalStateException("Multiple ICA files were downloaded"); 40 | } 41 | return recordedIcaFiles.isEmpty() ? null : recordedIcaFiles.get(0); 42 | } 43 | 44 | /* (non-Javadoc) 45 | * @see listener.CitrixIcaFileSaver#sampleOccurred(org.apache.jmeter.samplers.SampleEvent) 46 | */ 47 | @Override 48 | public void sampleOccurred(SampleEvent e) { 49 | JMeterVariables variables = getThreadContext().getVariables(); 50 | String fileBefore = variables.get(getVariableName()); 51 | super.sampleOccurred(e); 52 | String fileAfter = variables.get(getVariableName()); 53 | if (fileBefore == null && fileAfter != null 54 | || (fileBefore != null && fileAfter != null && !fileBefore.equals(fileAfter))) { 55 | recordedIcaFiles.add(fileAfter); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/recorder/TreeClonerForICADownloading.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.recorder; 2 | 3 | import com.blazemeter.jmeter.citrix.utils.CitrixUtils; 4 | import org.apache.jmeter.engine.TreeCloner; 5 | import org.apache.jmeter.threads.ThreadGroup; 6 | import org.apache.jmeter.timers.Timer; 7 | import org.apache.jmeter.util.JMeterUtils; 8 | import org.apache.jmeter.visualizers.backend.Backend; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | /** 13 | * Provides a {@link TreeCloner} that disables all Thread Groups. 14 | */ 15 | public class TreeClonerForICADownloading extends TreeCloner { 16 | 17 | private static final Logger LOGGER = LoggerFactory.getLogger(TreeClonerForICADownloading.class); 18 | 19 | private static final boolean ICA_DOWNLOADING_IGNORE_TIMERS = JMeterUtils 20 | .getPropDefault(CitrixUtils.PROPERTIES_PFX + "ica_downloading_ignore_timers", true); 21 | //$NON-NLS-1$ 22 | 23 | private static final boolean ICA_DOWNLOADING_IGNORE_BACKENDS = JMeterUtils 24 | .getPropDefault(CitrixUtils.PROPERTIES_PFX + "ica_downloading_ignore_backends", true); 25 | //$NON-NLS-1$ 26 | 27 | static { 28 | LOGGER.info("Running ICA file downloading with ignoreTimers:{}, ignoreBackends:{}", 29 | ICA_DOWNLOADING_IGNORE_TIMERS, ICA_DOWNLOADING_IGNORE_BACKENDS); 30 | } 31 | 32 | 33 | /** 34 | * Instantiates a new {@link TreeClonerForICADownloading}. 35 | */ 36 | public TreeClonerForICADownloading() { 37 | this(false); 38 | } 39 | 40 | /** 41 | * Instantiates a new {@link TreeClonerForICADownloading}. 42 | * 43 | * @param honourNoThreadClone indicates whether NoThreadClone is honoured 44 | * during cloning 45 | */ 46 | public TreeClonerForICADownloading(boolean honourNoThreadClone) { 47 | super(honourNoThreadClone); 48 | } 49 | 50 | @Override 51 | protected Object addNodeToTree(Object node) { 52 | // depending on jmeter properties, don't add timers or backends 53 | if ((ICA_DOWNLOADING_IGNORE_TIMERS && node instanceof Timer) 54 | || (ICA_DOWNLOADING_IGNORE_BACKENDS && node instanceof Backend)) { 55 | return node; 56 | } else { 57 | Object clonedNode = super.addNodeToTree(node); 58 | 59 | // Initialize cloned thread groups 60 | if (clonedNode instanceof ThreadGroup) { 61 | ThreadGroup threadGroup = (ThreadGroup) clonedNode; 62 | // No execution for others 63 | threadGroup.setNumThreads(0); 64 | } 65 | return clonedNode; 66 | } 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/recorder/gui/ActionItem.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.recorder.gui; 2 | 3 | class ActionItem { 4 | private final String command; 5 | private final String description; 6 | 7 | ActionItem(String command, String description) { 8 | this.command = command; 9 | this.description = description; 10 | } 11 | 12 | public String getCommand() { 13 | return command; 14 | } 15 | 16 | public String getDescription() { 17 | return description; 18 | } 19 | 20 | public String toString() { 21 | return description; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/recorder/gui/ActionItemRenderer.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.recorder.gui; 2 | 3 | import java.awt.Component; 4 | import javax.swing.JList; 5 | import javax.swing.plaf.basic.BasicComboBoxRenderer; 6 | 7 | class ActionItemRenderer extends BasicComboBoxRenderer { 8 | 9 | @Override 10 | public Component getListCellRendererComponent( 11 | JList list, Object value, int index, 12 | boolean isSelected, boolean cellHasFocus) { 13 | super.getListCellRendererComponent(list, value, index, 14 | isSelected, cellHasFocus); 15 | 16 | if (value != null || index == -1) { 17 | ActionItem item = (ActionItem) value; 18 | setText((item != null) ? item.getDescription() : "NAN"); 19 | } 20 | return this; 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/recorder/gui/BasePanel.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.recorder.gui; 2 | 3 | import com.blazemeter.jmeter.citrix.recorder.CitrixRecorder; 4 | import com.blazemeter.jmeter.commons.SwingUtils; 5 | import javax.swing.BorderFactory; 6 | import javax.swing.GroupLayout; 7 | import javax.swing.JPanel; 8 | import javax.swing.border.TitledBorder; 9 | 10 | public class BasePanel { 11 | 12 | protected JPanel mainPanel; 13 | 14 | protected CitrixRecorderGUI recorderGUI; 15 | 16 | protected SwingUtils.ButtonBuilder baseButtonBuilder; 17 | 18 | public BasePanel(CitrixRecorderGUI recorderGUI) { 19 | super(); 20 | this.recorderGUI = recorderGUI; 21 | 22 | // Set the event receiver to te recorder GUI 23 | baseButtonBuilder = 24 | new SwingUtils.ButtonBuilder().withActionListener(recorderGUI); 25 | 26 | } 27 | 28 | public JPanel getPanel() { 29 | return mainPanel; 30 | } 31 | 32 | protected GroupLayout buildGroupLayout(JPanel container) { 33 | GroupLayout layout = new GroupLayout(container); 34 | container.setLayout(layout); 35 | layout.setAutoCreateGaps(true); 36 | layout.setAutoCreateContainerGaps(true); 37 | return layout; 38 | } 39 | 40 | protected TitledBorder createTitledBorder(String title) { 41 | return BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), title); 42 | } 43 | 44 | protected CitrixRecorder getRecorder() { 45 | return this.recorderGUI.getRecorder(); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/recorder/gui/DownloadingControllerCellRenderer.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.recorder.gui; 2 | 3 | import java.awt.Component; 4 | import javax.swing.ImageIcon; 5 | import javax.swing.JTree; 6 | import javax.swing.tree.DefaultMutableTreeNode; 7 | import javax.swing.tree.DefaultTreeCellRenderer; 8 | import org.apache.jmeter.gui.tree.JMeterTreeNode; 9 | 10 | /** 11 | * This class provides a renderer for printing "ICA Downloading Controller" tree. 12 | */ 13 | public class DownloadingControllerCellRenderer extends DefaultTreeCellRenderer { 14 | 15 | private static final long serialVersionUID = -2787040480968015550L; 16 | 17 | @Override 18 | public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, 19 | boolean expanded, 20 | boolean leaf, int row, boolean hasFocus) { 21 | JMeterTreeNode node = (JMeterTreeNode) ((DefaultMutableTreeNode) value).getUserObject(); 22 | if (node != null) { 23 | super.getTreeCellRendererComponent(tree, node.getName(), selected, expanded, leaf, row, 24 | hasFocus); 25 | // print same icon as in test plan tree 26 | boolean enabled = node.isEnabled(); 27 | ImageIcon icon = node.getIcon(enabled); 28 | if (icon != null) { 29 | if (enabled) { 30 | setIcon(icon); 31 | } else { 32 | setDisabledIcon(icon); 33 | } 34 | } else if (!enabled) { // i.e. no disabled icon found 35 | // Must therefore set the enabled icon so there is at least some icon 36 | icon = node.getIcon(); 37 | if (icon != null) { 38 | setIcon(icon); 39 | } 40 | } 41 | } 42 | return this; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/recorder/gui/DownloadingControllerTreeSelectionModel.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.recorder.gui; 2 | 3 | import com.blazemeter.jmeter.citrix.utils.TestPlanHelper; 4 | import javax.swing.tree.DefaultMutableTreeNode; 5 | import javax.swing.tree.DefaultTreeSelectionModel; 6 | import javax.swing.tree.TreePath; 7 | import org.apache.jmeter.gui.tree.JMeterTreeNode; 8 | 9 | /** 10 | * Provides a selection model for Downloading Controller tree component. 11 | */ 12 | public class DownloadingControllerTreeSelectionModel extends DefaultTreeSelectionModel { 13 | 14 | private static final long serialVersionUID = -5011434911282903840L; 15 | 16 | /** 17 | *

18 | * Checks whether the specified node if selectable. 19 | *

20 | * 21 | * @param node the node to test 22 | * @return true if the node is selectable; false otherwise 23 | */ 24 | private boolean isValidDownloadingControllerNode(DefaultMutableTreeNode node) { 25 | JMeterTreeNode modelNode = null; 26 | if (node != null && node.getUserObject() instanceof JMeterTreeNode) { 27 | modelNode = (JMeterTreeNode) node.getUserObject(); 28 | } 29 | return modelNode != null && 30 | TestPlanHelper.isValidDownloadingController(modelNode.getTestElement()); 31 | } 32 | 33 | /** 34 | *

35 | * Apply the action when the specified node is selectable 36 | *

37 | *

38 | * WARNING : The {@link Runnable} interface is used just for its signature, not 39 | * for thread handling. 40 | *

41 | * 42 | * @param node the node to test 43 | * @param action the action to execute when node is selectable 44 | */ 45 | private void applyWhenValid(DefaultMutableTreeNode node, Runnable action) { 46 | if (isValidDownloadingControllerNode(node)) { 47 | action.run(); 48 | } 49 | } 50 | 51 | @Override 52 | public void setSelectionPath(TreePath path) { 53 | // Change the selection only when the matching node is valid 54 | applyWhenValid((DefaultMutableTreeNode) path.getLastPathComponent(), 55 | () -> super.setSelectionPath(path)); 56 | } 57 | 58 | @Override 59 | public void setSelectionPaths(TreePath[] paths) { 60 | // Change the selection only when the matching node is valid 61 | applyWhenValid((DefaultMutableTreeNode) paths[paths.length - 1].getLastPathComponent(), 62 | () -> super.setSelectionPaths(paths)); 63 | } 64 | 65 | @Override 66 | public void addSelectionPath(TreePath path) { 67 | // Add to the current selection only when the matching node is valid 68 | applyWhenValid((DefaultMutableTreeNode) path.getLastPathComponent(), 69 | () -> super.addSelectionPath(path)); 70 | } 71 | 72 | @Override 73 | public void addSelectionPaths(TreePath[] paths) { 74 | // Add to the current selection only when the matching node is valid 75 | applyWhenValid((DefaultMutableTreeNode) paths[paths.length - 1].getLastPathComponent(), 76 | () -> super.addSelectionPaths(paths)); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/recorder/gui/PageViewer.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.recorder.gui; 2 | 3 | import java.awt.CardLayout; 4 | import java.awt.Component; 5 | import java.awt.Container; 6 | import java.awt.Dimension; 7 | import java.awt.Insets; 8 | 9 | public class PageViewer extends CardLayout { 10 | 11 | @Override 12 | public Dimension preferredLayoutSize(Container parent) { 13 | Component current = findCurrentComponent(parent); 14 | if (current != null) { 15 | Insets insets = parent.getInsets(); 16 | Dimension pref = current.getPreferredSize(); 17 | pref.width += insets.left + insets.right; 18 | pref.height += insets.top + insets.bottom; 19 | return pref; 20 | } 21 | return super.preferredLayoutSize(parent); 22 | } 23 | 24 | public Component findCurrentComponent(Container parent) { 25 | for (Component comp : parent.getComponents()) { 26 | if (comp.isVisible()) { 27 | return comp; 28 | } 29 | } 30 | return null; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/recorder/gui/RecorderDialog.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.recorder.gui; 2 | 3 | import com.blazemeter.jmeter.citrix.utils.CitrixUtils; 4 | import java.awt.BorderLayout; 5 | import java.awt.GraphicsEnvironment; 6 | import java.awt.Rectangle; 7 | import java.awt.event.ActionEvent; 8 | import java.awt.event.ActionListener; 9 | import java.awt.event.ItemEvent; 10 | import java.awt.event.ItemListener; 11 | import java.awt.event.KeyEvent; 12 | import java.awt.event.KeyListener; 13 | import javax.swing.BorderFactory; 14 | import javax.swing.JDialog; 15 | import javax.swing.JFrame; 16 | import javax.swing.JPanel; 17 | import javax.swing.JRootPane; 18 | import javax.swing.WindowConstants; 19 | 20 | public class RecorderDialog extends JDialog implements ItemListener, KeyListener, ActionListener { 21 | 22 | public RecorderDialog() { 23 | super((JFrame) null, CitrixUtils.getResString("recorder_toolbar_title", false), 24 | false); 25 | this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); 26 | this.setResizable(false); 27 | init(); 28 | } 29 | 30 | @Override 31 | protected JRootPane createRootPane() { 32 | return new JRootPane(); 33 | } 34 | 35 | private void init() { 36 | this.getContentPane().setLayout(new BorderLayout(10, 10)); 37 | ((JPanel) this.getContentPane()) 38 | .setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); 39 | this.pack(); 40 | this.setLocation(5, 10); 41 | this.getContentPane().requestFocusInWindow(); 42 | } 43 | 44 | @Override 45 | public void setVisible(boolean b) { 46 | super.setVisible(b); 47 | setAlwaysOnTop(b); 48 | } 49 | 50 | @Override 51 | public void itemStateChanged(ItemEvent e) { 52 | // NOOP 53 | } 54 | 55 | public void setTopRightLocation() { 56 | Rectangle bounds = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice() 57 | .getDefaultConfiguration().getBounds(); 58 | int padding = 10; // for cognitive aid, not aligning the window with the background window 59 | this.setLocation((int) ((bounds.getWidth() - this.getWidth()) - padding), padding); 60 | this.validate(); 61 | this.repaint(); 62 | } 63 | 64 | /** 65 | * {@inheritDoc} 66 | */ 67 | @Override 68 | public void keyPressed(KeyEvent e) { 69 | // NOOP 70 | } 71 | 72 | /** 73 | * {@inheritDoc} 74 | */ 75 | @Override 76 | public void keyTyped(KeyEvent e) { 77 | // NOOP 78 | } 79 | 80 | /** 81 | * {@inheritDoc} 82 | */ 83 | @Override 84 | public void keyReleased(KeyEvent e) { 85 | // NOOP 86 | } 87 | 88 | @Override 89 | public void actionPerformed(ActionEvent event) { 90 | // NOOP 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/recorder/gui/ResultNodeRenderer.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.recorder.gui; 2 | 3 | import java.awt.Component; 4 | import javax.swing.ImageIcon; 5 | import javax.swing.JTree; 6 | import javax.swing.tree.DefaultTreeCellRenderer; 7 | import org.apache.jmeter.JMeter; 8 | import org.apache.jmeter.util.JMeterUtils; 9 | 10 | class ResultNodeRenderer extends DefaultTreeCellRenderer { 11 | private static final long serialVersionUID = 4159626601097711565L; 12 | 13 | private static final String ICON_SIZE = 14 | JMeterUtils.getPropDefault(JMeter.TREE_ICON_SIZE, JMeter.DEFAULT_TREE_ICON_SIZE); 15 | private static final ImageIcon STEPIMAGE = JMeterUtils.getImage( 16 | JMeterUtils 17 | .getPropDefault("viewResultsTree.success", "vrt/" + ICON_SIZE + "/security-high-2.png")); 18 | 19 | @Override 20 | public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, 21 | boolean expanded, 22 | boolean leaf, int row, boolean focus) { 23 | super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, focus); 24 | this.setIcon(STEPIMAGE); 25 | return this; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/recorder/gui/workers/DownloadIcaWorker.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.recorder.gui.workers; 2 | 3 | import com.blazemeter.jmeter.citrix.recorder.gui.CitrixRecorderGUI; 4 | import com.blazemeter.jmeter.citrix.utils.CitrixUtils; 5 | import java.nio.file.Path; 6 | import java.util.Optional; 7 | import java.util.concurrent.ExecutionException; 8 | import javax.swing.SwingWorker; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | public class DownloadIcaWorker extends SwingWorker, Object> { 13 | 14 | private static final Logger LOGGER = LoggerFactory.getLogger(DownloadIcaWorker.class); 15 | 16 | private final CitrixRecorderGUI crg; 17 | 18 | public DownloadIcaWorker(CitrixRecorderGUI crg) { 19 | this.crg = crg; 20 | } 21 | 22 | @Override 23 | protected Optional doInBackground() throws Exception { 24 | return crg.downloadIcaFile(); 25 | } 26 | 27 | /* 28 | * (non-Javadoc) 29 | * 30 | * @see javax.swing.SwingWorker#done() 31 | */ 32 | @Override 33 | protected void done() { 34 | crg.setWait(false); 35 | Optional path; 36 | try { 37 | path = get(); 38 | crg.downloadIcaFileDone(path); 39 | } catch (InterruptedException | ExecutionException e) { 40 | LOGGER.error("ICA file downloading error : {}", e.getMessage(), e); 41 | crg.appendStatus(CitrixUtils.getResString("recorder_ica_downloading_failed", false)); 42 | crg.stopRecordingNoCancel(); 43 | Thread.currentThread().interrupt(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/recorder/gui/workers/MonitorRecordingWorker.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.recorder.gui.workers; 2 | 3 | import static com.blazemeter.jmeter.citrix.recorder.gui.CitrixRecorderGUI.CLIENT_EXCEPTION; 4 | 5 | import com.blazemeter.jmeter.citrix.recorder.gui.CitrixRecorderGUI; 6 | import com.blazemeter.jmeter.citrix.utils.CitrixUtils; 7 | import java.util.concurrent.ExecutionException; 8 | import javax.swing.SwingWorker; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | public class MonitorRecordingWorker extends SwingWorker { 13 | 14 | private static final Logger LOGGER = LoggerFactory.getLogger(MonitorRecordingWorker.class); 15 | 16 | private final CitrixRecorderGUI crg; 17 | 18 | public MonitorRecordingWorker(CitrixRecorderGUI crg) { 19 | this.crg = crg; 20 | } 21 | 22 | @Override 23 | protected Boolean doInBackground() throws Exception { 24 | long chunkWaitTime = 1000; 25 | // Polling over client waiting the finish state 26 | while (crg.clientIsRunning() && !isCancelled()) { 27 | Thread.sleep(chunkWaitTime); 28 | LOGGER.info("[MonitorRecording] Monitoring..."); 29 | } 30 | return true; 31 | } 32 | 33 | @Override 34 | protected void done() { 35 | try { 36 | get(); 37 | if (crg.isRecording()) { 38 | crg.stopRecordingNoCancel(); 39 | } 40 | } catch (InterruptedException | ExecutionException e) { 41 | LOGGER.error("Error occurred recording citrix application {}", e.getMessage(), e); 42 | crg.appendStatus(CitrixUtils.getResString(CLIENT_EXCEPTION, false)); 43 | crg.stopRecordingNoCancel(); 44 | Thread.currentThread().interrupt(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/recorder/gui/workers/StartRecordingWorker.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.recorder.gui.workers; 2 | 3 | import com.blazemeter.jmeter.citrix.client.CitrixClientException; 4 | import com.blazemeter.jmeter.citrix.recorder.gui.CitrixRecorderGUI; 5 | import com.blazemeter.jmeter.citrix.utils.CitrixUtils; 6 | import java.nio.file.Path; 7 | import java.util.Optional; 8 | import java.util.concurrent.ExecutionException; 9 | import javax.swing.SwingWorker; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | public class StartRecordingWorker extends SwingWorker { 14 | 15 | private static final Logger LOGGER = LoggerFactory.getLogger(StartRecordingWorker.class); 16 | 17 | private final Optional icaPath; 18 | private final CitrixRecorderGUI crg; 19 | 20 | public StartRecordingWorker(CitrixRecorderGUI crg, Optional icaPath) { 21 | this.crg = crg; 22 | this.icaPath = icaPath; 23 | } 24 | 25 | /* 26 | * (non-Javadoc) 27 | * 28 | * @see javax.swing.SwingWorker#doInBackground() 29 | */ 30 | @Override 31 | protected Boolean doInBackground() throws Exception { 32 | crg.setWait(true); 33 | LOGGER.info("Started recording"); 34 | // SwingWorker doesn't allow to define the Thread Name 35 | // WA, set the thread name inside the running thread 36 | // Required for set a correct session title and for session instance identification. 37 | Thread.currentThread().setName("Citrix Recorder 1-1"); 38 | 39 | return crg.startRecord(icaPath); 40 | 41 | } 42 | 43 | /* 44 | * (non-Javadoc) 45 | * 46 | * @see javax.swing.SwingWorker#done() 47 | */ 48 | @Override 49 | protected void done() { 50 | crg.setWait(false); 51 | try { 52 | Boolean result = get(); 53 | if (Boolean.TRUE.equals(result)) { 54 | crg.appendStatus("Recording started"); 55 | } else { 56 | crg.appendStatus(CitrixUtils.getResString(CitrixRecorderGUI.CLIENT_EXCEPTION, false)); 57 | crg.setExpectedDisconnect(true); 58 | crg.stopRecordingNoCancel(); 59 | } 60 | } catch (InterruptedException | ExecutionException e) { 61 | Throwable ex = e.getCause(); 62 | if (ex instanceof CitrixClientException) { 63 | crg.appendStatus( 64 | "Recorder Error: " + 65 | ((CitrixClientException) ex).code() + " " + ex.getMessage()); 66 | } else { 67 | LOGGER.error("Error occurred starting citrix application {}", e.getMessage(), e); 68 | crg.appendStatus(CitrixUtils.getResString(CitrixRecorderGUI.CLIENT_EXCEPTION, false)); 69 | } 70 | crg.setExpectedDisconnect(true); 71 | crg.stopRecordingNoCancel(); 72 | Thread.currentThread().interrupt(); 73 | } 74 | } 75 | } 76 | 77 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/recorder/gui/workers/StopRecordingWorker.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.recorder.gui.workers; 2 | 3 | import com.blazemeter.jmeter.citrix.client.CitrixClientException; 4 | import com.blazemeter.jmeter.citrix.recorder.gui.CitrixRecorderGUI; 5 | import com.blazemeter.jmeter.citrix.utils.CitrixUtils; 6 | import com.blazemeter.jmeter.citrix.utils.DialogHelper; 7 | import java.util.concurrent.ExecutionException; 8 | import javax.swing.SwingWorker; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | public class StopRecordingWorker extends SwingWorker { 13 | 14 | private static final Logger LOGGER = LoggerFactory.getLogger(StopRecordingWorker.class); 15 | 16 | private final CitrixRecorderGUI crg; 17 | 18 | public StopRecordingWorker(CitrixRecorderGUI crg) { 19 | this.crg = crg; 20 | } 21 | 22 | @Override 23 | protected Boolean doInBackground() throws Exception { 24 | return crg.stopRecordingUI(); 25 | } 26 | 27 | @Override 28 | protected void done() { 29 | crg.setWait(false); 30 | try { 31 | get(); 32 | crg.stopRecordingNoCancel(); 33 | } catch (InterruptedException | ExecutionException e) { 34 | Throwable ex = e.getCause(); 35 | if (ex instanceof CitrixClientException) { 36 | crg.appendStatus( 37 | "Unable to stop Recorder: " + 38 | ((CitrixClientException) ex).code() + " " + ex.getMessage()); 39 | } else { 40 | LOGGER.error("Error occurred stopping citrix recorder {}", e.getMessage(), e); 41 | crg.appendStatus(CitrixUtils.getResString(CitrixRecorderGUI.CLIENT_EXCEPTION, false)); 42 | crg.stopRecordingNoCancel(); 43 | Thread.currentThread().interrupt(); 44 | } 45 | } finally { 46 | DialogHelper.focusJMeter(); 47 | } 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/recorder/gui/workers/WaitCaptureWorker.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.recorder.gui.workers; 2 | 3 | import com.blazemeter.jmeter.citrix.recorder.gui.CitrixRecorderGUI; 4 | import java.util.concurrent.ExecutionException; 5 | import javax.swing.SwingWorker; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | public class WaitCaptureWorker extends SwingWorker { 10 | 11 | private static final Logger LOGGER = LoggerFactory.getLogger(WaitCaptureWorker.class); 12 | 13 | private final CitrixRecorderGUI crg; 14 | 15 | public WaitCaptureWorker(CitrixRecorderGUI crg) { 16 | this.crg = crg; 17 | } 18 | 19 | /* 20 | * (non-Javadoc) 21 | * 22 | * @see javax.swing.SwingWorker#doInBackground() 23 | */ 24 | @Override 25 | protected Boolean doInBackground() throws Exception { 26 | return crg.waitCapture(); 27 | } 28 | 29 | /* 30 | * (non-Javadoc) 31 | * 32 | * @see javax.swing.SwingWorker#done() 33 | */ 34 | @Override 35 | protected void done() { 36 | try { 37 | boolean eventCaptured = get(); 38 | if (eventCaptured) { 39 | crg.enableCaptureActions(true); 40 | } 41 | } catch (InterruptedException | ExecutionException e) { 42 | LOGGER.error("Error occurred starting capture interact event {}", e.getMessage(), e); 43 | Thread.currentThread().interrupt(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/sampler/CitrixSessionHolder.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.sampler; 2 | 3 | import com.blazemeter.jmeter.citrix.client.CitrixClient; 4 | 5 | /** 6 | * Holds the Citrix Client and underlying session. 7 | */ 8 | public class CitrixSessionHolder { 9 | protected static final ThreadLocal LOCAL_CLIENT = new ThreadLocal<>(); 10 | 11 | /** 12 | * 13 | */ 14 | private CitrixSessionHolder() { 15 | super(); 16 | } 17 | 18 | /** 19 | * @return {@link CitrixClient} or null if not initialized 20 | */ 21 | public static CitrixClient getClient() { 22 | return LOCAL_CLIENT.get(); 23 | } 24 | 25 | /** 26 | * Setup CitrixClient as soon as available. 27 | * @param client {@link CitrixClient} or null if not initialized 28 | */ 29 | static void setClient(CitrixClient client) { 30 | LOCAL_CLIENT.set(client); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/sampler/KeySequenceItem.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.sampler; 2 | 3 | import com.blazemeter.jmeter.citrix.client.events.InteractionEvent.KeyState; 4 | import java.io.Serializable; 5 | 6 | public class KeySequenceItem implements Serializable { 7 | 8 | private static final long serialVersionUID = 2935074902697920184L; 9 | 10 | private KeyState keyState; 11 | private int keyCode; 12 | private long delay; 13 | 14 | public KeySequenceItem() { 15 | } 16 | 17 | public KeySequenceItem(KeyState keyState, int keyCode, long delay) { 18 | this.setKeyState(keyState); 19 | this.setKeyCode(keyCode); 20 | this.delay = delay; 21 | } 22 | 23 | /** 24 | * @return the keyState 25 | */ 26 | public KeyState getKeyState() { 27 | return keyState; 28 | } 29 | 30 | /** 31 | * @param keyState the keyState to set 32 | */ 33 | public void setKeyState(KeyState keyState) { 34 | if (keyState == null) { 35 | throw new IllegalArgumentException("keyState cannot be null"); 36 | } 37 | this.keyState = keyState; 38 | } 39 | 40 | /** 41 | * @return the keyCode 42 | */ 43 | public int getKeyCode() { 44 | return keyCode; 45 | } 46 | 47 | /** 48 | * @param keyCode the keyCode to set 49 | */ 50 | public void setKeyCode(int keyCode) { 51 | this.keyCode = keyCode; 52 | } 53 | 54 | /** 55 | * @return the delay 56 | */ 57 | public long getDelay() { 58 | return delay; 59 | } 60 | 61 | /** 62 | * @param delay the delay to set 63 | */ 64 | public void setDelay(long delay) { 65 | this.delay = delay; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/sampler/MouseSequenceItem.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.sampler; 2 | 3 | import com.blazemeter.jmeter.citrix.client.events.InteractionEvent.MouseAction; 4 | import com.blazemeter.jmeter.citrix.client.events.Modifier; 5 | import com.blazemeter.jmeter.citrix.client.events.MouseButton; 6 | import java.io.Serializable; 7 | import java.util.EnumSet; 8 | import java.util.Set; 9 | 10 | public class MouseSequenceItem implements Serializable { 11 | /** 12 | * 13 | */ 14 | private static final long serialVersionUID = 6163197927231021148L; 15 | private final Set buttons = EnumSet.noneOf(MouseButton.class); 16 | private final Set modifiers = EnumSet.noneOf(Modifier.class); 17 | private MouseAction action; 18 | private int x; 19 | private int y; 20 | private long delay; 21 | 22 | public MouseSequenceItem() { 23 | } 24 | 25 | public MouseSequenceItem(MouseAction action, int x, int y, Set buttons, 26 | Set modifiers, 27 | long delay) { 28 | this.setAction(action); 29 | this.setX(x); 30 | this.setY(y); 31 | if (buttons != null) { 32 | this.buttons.addAll(buttons); 33 | } 34 | if (modifiers != null) { 35 | this.modifiers.addAll(modifiers); 36 | } 37 | this.delay = delay; 38 | } 39 | 40 | public MouseAction getAction() { 41 | return action; 42 | } 43 | 44 | public void setAction(MouseAction action) { 45 | if (action == null) { 46 | throw new IllegalArgumentException("action cannot be null."); 47 | } 48 | this.action = action; 49 | } 50 | 51 | public int getX() { 52 | return x; 53 | } 54 | 55 | public void setX(int x) { 56 | this.x = x; 57 | } 58 | 59 | public int getY() { 60 | return y; 61 | } 62 | 63 | public void setY(int y) { 64 | this.y = y; 65 | } 66 | 67 | public Set getButtons() { 68 | return buttons; 69 | } 70 | 71 | public Set getModifiers() { 72 | return modifiers; 73 | } 74 | 75 | /** 76 | * @return the delay 77 | */ 78 | public long getDelay() { 79 | return delay; 80 | } 81 | 82 | /** 83 | * @param delay the delay to set 84 | */ 85 | public void setDelay(long delay) { 86 | this.delay = delay; 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/sampler/SamplerResultHelper.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.sampler; 2 | 3 | import com.blazemeter.jmeter.citrix.client.CitrixClient.Snapshot; 4 | import org.apache.jmeter.samplers.SampleResult; 5 | 6 | public class SamplerResultHelper { 7 | 8 | public static final String OK_CODE = "200"; 9 | public static final String APPLICATION_EXIT_CODE = "204"; 10 | 11 | private SamplerResultHelper() { 12 | 13 | } 14 | 15 | public static CitrixSampleResult createResult(CitrixBaseSampler sampler) { 16 | if (sampler == null) { 17 | throw new IllegalArgumentException("sampler must not be null."); 18 | } 19 | 20 | final CitrixSampleResult result = new CitrixSampleResult(); 21 | result.setSampleLabel(sampler.getName()); 22 | result.setDataType(SampleResult.BINARY); 23 | result.setEndClause(sampler.getEndClause()); 24 | return result; 25 | } 26 | 27 | public static void setResultOk(CitrixSampleResult result) { 28 | if (result != null) { 29 | result.setResponseCode(OK_CODE); 30 | result.setSuccessful(true); 31 | } 32 | } 33 | 34 | public static CitrixSampleResult buildOkResult(CitrixBaseSampler sampler, Snapshot snapshot) { 35 | final CitrixSampleResult result = createResult(sampler); 36 | result.setSnapshot(snapshot); 37 | setResultOk(result); 38 | return result; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/sampler/SamplerType.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.sampler; 2 | 3 | /** 4 | * Lists the types of interactions that the sampler can handle. 5 | */ 6 | public enum SamplerType { 7 | /** 8 | * The sampler simulates the entry of a text. 9 | */ 10 | TEXT, 11 | 12 | /** 13 | * The sampler simulates a sequence of keystokes. 14 | */ 15 | KEY_SEQUENCE, 16 | 17 | /** 18 | * The sampler simulates a click or double click with the mouse. 19 | */ 20 | MOUSE_CLICK, 21 | 22 | /** 23 | * The sampler simulates a sequence of clicks and movements with the mouse. 24 | */ 25 | MOUSE_SEQUENCE 26 | } 27 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/sampler/gui/CitrixSamplerGUI.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.sampler.gui; 2 | 3 | import com.blazemeter.jmeter.citrix.clause.gui.ClausePanel; 4 | import com.blazemeter.jmeter.citrix.sampler.CitrixBaseSampler; 5 | import com.blazemeter.jmeter.citrix.utils.CitrixUtils; 6 | import com.blazemeter.jmeter.commons.BlazemeterLabsLogo; 7 | import java.awt.BorderLayout; 8 | import javax.swing.Box; 9 | import javax.swing.JPanel; 10 | import javax.swing.border.TitledBorder; 11 | import org.apache.jmeter.samplers.gui.AbstractSamplerGui; 12 | import org.apache.jmeter.testelement.TestElement; 13 | 14 | /** 15 | * Base GUI for Citrix samplers. 16 | */ 17 | public abstract class CitrixSamplerGUI extends AbstractSamplerGui { // NOSONAR Ignore parent warning 18 | 19 | private static final long serialVersionUID = 8757492879770709417L; 20 | 21 | private ClausePanel pnlEndClause; 22 | 23 | public CitrixSamplerGUI() { 24 | super(); 25 | initialize(); 26 | } 27 | 28 | protected abstract JPanel createMainPanel(); 29 | 30 | protected abstract CitrixBaseSampler createCitrixSampler(); 31 | 32 | protected abstract void updateSampler(CitrixBaseSampler sampler); 33 | 34 | protected abstract void updateUI(CitrixBaseSampler sampler); 35 | 36 | protected abstract void clearUI(); 37 | 38 | private JPanel createClausePanel() { 39 | JPanel panel = new JPanel(new BorderLayout()); 40 | panel.setBorder( 41 | new TitledBorder(null, CitrixUtils.getResString("sampler_end_clause_title", false), 42 | TitledBorder.LEADING, TitledBorder.TOP, null, null)); 43 | 44 | pnlEndClause = new ClausePanel(true); 45 | panel.add(pnlEndClause, BorderLayout.NORTH); 46 | 47 | return panel; 48 | } 49 | 50 | private void initialize() { 51 | setLayout(new BorderLayout()); 52 | setBorder(makeBorder()); 53 | 54 | Box box = Box.createVerticalBox(); 55 | box.add(makeTitlePanel()); 56 | box.add(Box.createVerticalStrut(10)); 57 | box.add(createMainPanel()); 58 | box.add(Box.createVerticalStrut(10)); 59 | box.add(createClausePanel()); 60 | box.add(Box.createVerticalStrut(10)); 61 | box.add(new BlazemeterLabsLogo("https://github.com/Blazemeter/CitrixPlugin")); 62 | add(box, BorderLayout.NORTH); 63 | } 64 | 65 | @Override 66 | public final TestElement createTestElement() { 67 | CitrixBaseSampler el = createCitrixSampler(); 68 | modifyTestElement(el); 69 | return el; 70 | } 71 | 72 | protected void stopEditing() { 73 | // NOOP 74 | } 75 | 76 | @Override 77 | public final void modifyTestElement(TestElement element) { 78 | stopEditing(); 79 | configureTestElement(element); 80 | CitrixBaseSampler sampler = (CitrixBaseSampler) element; 81 | updateSampler(sampler); 82 | pnlEndClause.updateClause(); 83 | sampler.setEndClause(pnlEndClause.getClause()); 84 | } 85 | 86 | @Override 87 | public final void configure(TestElement el) { 88 | super.configure(el); 89 | CitrixBaseSampler sampler = (CitrixBaseSampler) el; 90 | updateUI(sampler); 91 | pnlEndClause.setClause(sampler.getEndClause()); 92 | } 93 | 94 | // should never be used as we override getStaticLabel 95 | @Override 96 | public final String getLabelResource() { 97 | return "interface_title"; //$NON-NLS-1$ 98 | } 99 | 100 | @Override 101 | public final void clearGui() { 102 | super.clearGui(); 103 | stopEditing(); 104 | clearUI(); 105 | pnlEndClause.setClause(null); 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/sampler/gui/LineNumberTableModel.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.sampler.gui; 2 | 3 | import javax.swing.table.AbstractTableModel; 4 | 5 | abstract class LineNumberTableModel extends AbstractTableModel { 6 | 7 | private static final long serialVersionUID = 8891118394163711665L; 8 | 9 | protected abstract int getDataColumnCount(); 10 | 11 | protected abstract Class getDataColumnClass(int columnIndex); 12 | 13 | protected abstract Object getDataValueAt(int row, int column); 14 | 15 | protected abstract void setDataValueAt(Object aValue, int rowIndex, int columnIndex); 16 | 17 | protected abstract String getDataColumnName(int column); 18 | 19 | protected abstract boolean isDataCellEditable(int rowIndex, int columnIndex); 20 | 21 | @Override 22 | public final int getColumnCount() { 23 | return getDataColumnCount() + 1; 24 | } 25 | 26 | @Override 27 | public final Class getColumnClass(int columnIndex) { 28 | return (columnIndex == 0) ? Integer.class : getDataColumnClass(columnIndex - 1); 29 | } 30 | 31 | @Override 32 | public final String getColumnName(int column) { 33 | return (column == 0) ? "" : getDataColumnName(column - 1); 34 | } 35 | 36 | @Override 37 | public final Object getValueAt(int row, int column) { 38 | return (column == 0) ? row + 1 : getDataValueAt(row, column - 1); 39 | } 40 | 41 | @Override 42 | public final boolean isCellEditable(int rowIndex, int columnIndex) { 43 | return columnIndex > 0 && isDataCellEditable(rowIndex, columnIndex - 1); 44 | } 45 | 46 | @Override 47 | public final void setValueAt(Object aValue, int rowIndex, int columnIndex) { 48 | if (columnIndex > 0) { 49 | setDataValueAt(aValue, rowIndex, columnIndex - 1); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/sampler/gui/StartApplicationSamplerGUI.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.sampler.gui; 2 | 3 | import com.blazemeter.jmeter.citrix.gui.GuiHelper; 4 | import com.blazemeter.jmeter.citrix.sampler.CitrixBaseSampler; 5 | import com.blazemeter.jmeter.citrix.sampler.StartApplicationSampler; 6 | import com.blazemeter.jmeter.citrix.utils.CitrixUtils; 7 | import java.awt.GridBagLayout; 8 | import javax.swing.JPanel; 9 | import javax.swing.JTextField; 10 | 11 | /** 12 | * GUI for ApplicationStartedSampler class. 13 | */ 14 | public class StartApplicationSamplerGUI extends CitrixSamplerGUI { // NOSONAR Ignore parent warning 15 | 16 | public static final String RSC_TITLE = "start_application_sampler_gui_title"; 17 | private static final long serialVersionUID = -7106863979451551913L; 18 | private JTextField tfICAPathVar; 19 | 20 | protected final JPanel createMainPanel() { 21 | JPanel panel = new JPanel(); 22 | panel.setLayout(new GridBagLayout()); 23 | 24 | tfICAPathVar = new JTextField(25); 25 | GuiHelper 26 | .addLabeledComponent(tfICAPathVar, "start_application_sampler_gui_ica_path_var", panel); 27 | 28 | return panel; 29 | } 30 | 31 | @Override 32 | public String getStaticLabel() { 33 | return CitrixUtils.getResString(RSC_TITLE, false); 34 | } 35 | 36 | @Override 37 | protected CitrixBaseSampler createCitrixSampler() { 38 | return new StartApplicationSampler(); 39 | } 40 | 41 | @Override 42 | protected void updateSampler(CitrixBaseSampler sampler) { 43 | StartApplicationSampler startSampler = (StartApplicationSampler) sampler; 44 | startSampler.setICAPathVar(tfICAPathVar.getText()); 45 | } 46 | 47 | @Override 48 | protected void updateUI(CitrixBaseSampler sampler) { 49 | StartApplicationSampler startSampler = (StartApplicationSampler) sampler; 50 | tfICAPathVar.setText(startSampler.getICAPathVar()); 51 | } 52 | 53 | @Override 54 | protected void clearUI() { 55 | tfICAPathVar.setText(""); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/utils/CitrixUtils.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.utils; 2 | 3 | import java.util.Locale; 4 | import java.util.MissingResourceException; 5 | import java.util.ResourceBundle; 6 | import org.apache.jmeter.util.JMeterUtils; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | /** 11 | * Similar work as JMeterUtils. Used to get statics Strings used by the plugin. 12 | * Theses Strings are stored in messages_loc.properties files. 13 | */ 14 | public class CitrixUtils { 15 | 16 | public static final String PROPERTIES_PFX = "bzm.citrix."; 17 | 18 | private static final Logger LOGGER = LoggerFactory.getLogger(CitrixUtils.class); 19 | 20 | private CitrixUtils() { 21 | } 22 | 23 | /** 24 | * Give the corresponding String to the given key. If isJMeterNative is true, 25 | * return the String contained in the JMeter.properties files. Else, give the 26 | * String contained in the Citrix.properties files. 27 | * 28 | * @param key property used to find the corresponding String 29 | * @param isJMeterNative tell if the key is in the JMeter properties files 30 | * @return the corresponding String to the key in the messages_loc.properties 31 | * files 32 | */ 33 | public static String getResString(String key, boolean isJMeterNative) { 34 | ResourceBundle resources; 35 | if (isJMeterNative) { 36 | return JMeterUtils.getResString(key); 37 | } 38 | 39 | String resKey = key.replace(' ', '_'); 40 | resKey = resKey.toLowerCase(java.util.Locale.ENGLISH); 41 | String resString; 42 | 43 | try { 44 | Locale loc = JMeterUtils.getLocale(); 45 | resources = ResourceBundle.getBundle("com.blazemeter.jmeter.citrix.resources.messages", loc); 46 | 47 | ResourceBundle bundle = resources; 48 | 49 | if (bundle.containsKey(resKey)) { 50 | resString = bundle.getString(resKey); 51 | } else { 52 | LOGGER.warn("ERROR! Resource string not found: [{}]", resKey); 53 | resString = JMeterUtils.RES_KEY_PFX + key + "]"; 54 | } 55 | } catch (MissingResourceException mre) { 56 | LOGGER.warn("ERROR! Resource string not found: [{}]", resKey, mre); 57 | resString = JMeterUtils.RES_KEY_PFX + key + "]"; 58 | } 59 | return resString; 60 | } 61 | 62 | /* 63 | Obtains the text from either JMeter's default values or from our messages.properties. 64 | Returns the key if the text is not found. 65 | */ 66 | public static String getText(String key) { 67 | String string = getResString(key, true); 68 | if (!string.contains("res_key")) { 69 | return string; 70 | } 71 | 72 | string = getResString(key, false); 73 | if (!string.contains("res_key")) { 74 | return string; 75 | } 76 | 77 | return key; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/utils/DialogHelper.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.utils; 2 | 3 | import com.helger.commons.annotation.VisibleForTesting; 4 | import java.awt.Component; 5 | import java.awt.Frame; 6 | import javax.swing.JFrame; 7 | import javax.swing.JOptionPane; 8 | import javax.swing.SwingUtilities; 9 | import org.apache.jmeter.gui.GuiPackage; 10 | 11 | public class DialogHelper { 12 | 13 | private static final int DEF_OPTION_VALE = -9; // The value to not collide with other options 14 | private static int defaultOptionDialogResponse = DEF_OPTION_VALE; 15 | 16 | private DialogHelper() { 17 | } 18 | 19 | @VisibleForTesting 20 | public static void setDefaultOptionDialogResponse(int value) { 21 | defaultOptionDialogResponse = value; 22 | } 23 | 24 | @VisibleForTesting 25 | public static void setDefaultOptionDialogResponse() { 26 | defaultOptionDialogResponse = DEF_OPTION_VALE; 27 | } 28 | 29 | public static void showAlert(String message) { 30 | JOptionPane.showMessageDialog(null, message, 31 | CitrixUtils.getResString("dialog_helper_title_warning", false), 32 | JOptionPane.WARNING_MESSAGE); 33 | } 34 | 35 | public static void showError(String message) { 36 | JOptionPane.showMessageDialog(null, message, 37 | CitrixUtils.getResString("dialog_helper_title_error", false), 38 | JOptionPane.ERROR_MESSAGE); 39 | } 40 | 41 | public static JFrame getJMeterFrameRoot() { 42 | GuiPackage jmInstance = GuiPackage.getInstance(); 43 | if (jmInstance != null) { 44 | return ((JFrame) SwingUtilities.getRoot(jmInstance.getMainToolbar().getTopLevelAncestor())); 45 | } else { 46 | return null; 47 | } 48 | } 49 | 50 | public static void minimizeJMeter() { 51 | // Minimize the main window so the Citrix client becomes visible and focused. 52 | // Windows +10 do not allows to change focus between apps. 53 | JFrame jmRoot = getJMeterFrameRoot(); 54 | if (jmRoot != null) { 55 | jmRoot.setState(Frame.ICONIFIED); 56 | } 57 | } 58 | 59 | public static void focusJMeter() { 60 | JFrame jmRoot = getJMeterFrameRoot(); 61 | if (jmRoot != null) { 62 | jmRoot.setState(Frame.NORMAL); 63 | } 64 | } 65 | 66 | public static int showOptionDialog(Component parentComponent, 67 | Object message, String title, int optionType, int messageType, 68 | Object[] options, Object initialValue) { 69 | if (defaultOptionDialogResponse != DEF_OPTION_VALE) { 70 | return defaultOptionDialogResponse; 71 | } else { 72 | return JOptionPane.showOptionDialog(parentComponent, 73 | message, 74 | title, 75 | optionType, 76 | messageType, null, options, initialValue); 77 | } 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/java/com/blazemeter/jmeter/citrix/utils/EnumHelper.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.utils; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.Set; 6 | import java.util.stream.Collectors; 7 | import java.util.stream.Stream; 8 | 9 | public class EnumHelper { 10 | 11 | private EnumHelper() { 12 | } 13 | 14 | public static > List> getWrappers(Class clazz, Set filter, 15 | boolean includeNone) { 16 | Stream stream = Arrays.stream(clazz.getEnumConstants()); 17 | if (filter != null) { 18 | stream = stream.filter(filter::contains); 19 | } 20 | List> result = 21 | stream.map(v -> new EnumWrapper<>(clazz, v)).collect(Collectors.toList()); 22 | if (includeNone) { 23 | result.add(0, new EnumWrapper<>(clazz, null)); 24 | } 25 | return result; 26 | } 27 | 28 | public static > List> getWrappers(Class clazz, 29 | boolean includeNone) { 30 | return getWrappers(clazz, null, includeNone); 31 | } 32 | 33 | public static > EnumWrapper[] getWrappersAsArray(Class clazz, 34 | Set filter, 35 | boolean includeNone) { 36 | List> wrappers = getWrappers(clazz, filter, includeNone); 37 | @SuppressWarnings("unchecked") 38 | EnumWrapper[] array = new EnumWrapper[wrappers.size()]; 39 | return wrappers.toArray(array); 40 | } 41 | 42 | public static > EnumWrapper[] getWrappersAsArray(Class clazz, 43 | boolean includeNone) { 44 | return getWrappersAsArray(clazz, null, includeNone); 45 | } 46 | 47 | public static > EnumWrapper lookup(EnumWrapper[] array, T value) { 48 | EnumWrapper result = null; 49 | int index = 0; 50 | while (index < array.length && result == null) { 51 | EnumWrapper current = array[index]; 52 | if (current.getEnumValue() == value) { 53 | result = current; 54 | } else { 55 | index++; 56 | } 57 | } 58 | return result; 59 | } 60 | 61 | public static class EnumWrapper> { 62 | private final Class clazz; 63 | private final T enumValue; 64 | 65 | public EnumWrapper(Class clazz, T value) { 66 | this.clazz = clazz; 67 | this.enumValue = value; 68 | } 69 | 70 | public T getEnumValue() { 71 | return enumValue; 72 | } 73 | 74 | public String getLabel() { 75 | String suffix = enumValue != null ? enumValue.name().toLowerCase() : "none"; 76 | return CitrixUtils 77 | .getResString("enum_helper_" + clazz.getSimpleName().toLowerCase() + "_" + suffix, false); 78 | } 79 | 80 | @Override 81 | public String toString() { 82 | return getLabel(); 83 | } 84 | 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/resources/com/blazemeter/jmeter/citrix/cursors/dnd_clause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/citrix-jmeter/src/main/resources/com/blazemeter/jmeter/citrix/cursors/dnd_clause.png -------------------------------------------------------------------------------- /citrix-jmeter/src/main/resources/com/blazemeter/jmeter/citrix/installer/saveservice-excerpt.properties: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Add the following line at the end of JMeter saveservice.properties file 4 | 5 | _com.blazemeter.jmeter.citrix.sampler.CitrixSampleResultConverter=collection 6 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/resources/com/blazemeter/jmeter/citrix/template/bzmCitrixTemplate.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 23 | 24 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/resources/com/blazemeter/jmeter/citrix/template/bzmCitrixTemplateWithParameters.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 32 | 33 | -------------------------------------------------------------------------------- /citrix-jmeter/src/main/resources/com/blazemeter/labs-logo/blazemeter-labs-light-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/citrix-jmeter/src/main/resources/com/blazemeter/labs-logo/blazemeter-labs-light-logo.png -------------------------------------------------------------------------------- /citrix-jmeter/src/main/resources/com/blazemeter/labs-logo/blazemeter-labs-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/citrix-jmeter/src/main/resources/com/blazemeter/labs-logo/blazemeter-labs-logo.png -------------------------------------------------------------------------------- /citrix-jmeter/src/main/resources/dark-theme/add_action.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/citrix-jmeter/src/main/resources/dark-theme/add_action.png -------------------------------------------------------------------------------- /citrix-jmeter/src/main/resources/dark-theme/discard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/citrix-jmeter/src/main/resources/dark-theme/discard.png -------------------------------------------------------------------------------- /citrix-jmeter/src/main/resources/dark-theme/full_screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/citrix-jmeter/src/main/resources/dark-theme/full_screenshot.png -------------------------------------------------------------------------------- /citrix-jmeter/src/main/resources/dark-theme/selection_screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/citrix-jmeter/src/main/resources/dark-theme/selection_screenshot.png -------------------------------------------------------------------------------- /citrix-jmeter/src/main/resources/dark-theme/text_ocr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/citrix-jmeter/src/main/resources/dark-theme/text_ocr.png -------------------------------------------------------------------------------- /citrix-jmeter/src/main/resources/light-theme/add_action.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/citrix-jmeter/src/main/resources/light-theme/add_action.png -------------------------------------------------------------------------------- /citrix-jmeter/src/main/resources/light-theme/discard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/citrix-jmeter/src/main/resources/light-theme/discard.png -------------------------------------------------------------------------------- /citrix-jmeter/src/main/resources/light-theme/full_screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/citrix-jmeter/src/main/resources/light-theme/full_screenshot.png -------------------------------------------------------------------------------- /citrix-jmeter/src/main/resources/light-theme/selection_screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/citrix-jmeter/src/main/resources/light-theme/selection_screenshot.png -------------------------------------------------------------------------------- /citrix-jmeter/src/main/resources/light-theme/text_ocr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/citrix-jmeter/src/main/resources/light-theme/text_ocr.png -------------------------------------------------------------------------------- /citrix-jmeter/src/test/java/com/blazemeter/jmeter/citrix/installer/WinRegistryTest.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.installer; 2 | 3 | import static org.hamcrest.CoreMatchers.is; 4 | import static org.junit.Assert.assertFalse; 5 | import static org.junit.Assert.assertNotSame; 6 | import static org.junit.Assume.assumeThat; 7 | 8 | import org.junit.Test; 9 | 10 | public class WinRegistryTest { 11 | 12 | @Test 13 | public void accessDeniedWinRegTest() { 14 | assumeThat(WinRegistry.isAdmin(), is(false)); 15 | 16 | String regPath = "SOFTWARE\\Citrix\\ICA Client"; 17 | String regKey = "DummyKey"; 18 | assertFalse( 19 | WinRegistry.setIntValueForKey(WinRegistry.HKEY_LOCAL_MACHINE, regPath, regKey, 0)); 20 | 21 | } 22 | 23 | @Test 24 | public void getWinVersionTest() { 25 | String regPath = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"; 26 | String regKey = "ProductName"; 27 | 28 | assertNotSame("", WinRegistry.getValueForKey(WinRegistry.HKEY_LOCAL_MACHINE, regPath, regKey)); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /citrix-jmeter/src/test/java/com/blazemeter/jmeter/citrix/recorder/gui/SwingTestRunner.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.recorder.gui; 2 | 3 | import static org.assertj.swing.junit.runner.Formatter.testNameFrom; 4 | 5 | import java.io.File; 6 | import java.nio.file.Paths; 7 | import java.util.List; 8 | import org.assertj.core.util.Files; 9 | import org.assertj.swing.junit.runner.FailureScreenshotTaker; 10 | import org.junit.rules.MethodRule; 11 | import org.junit.runners.BlockJUnit4ClassRunner; 12 | import org.junit.runners.model.FrameworkMethod; 13 | import org.junit.runners.model.InitializationError; 14 | import org.junit.runners.model.Statement; 15 | import org.mockito.junit.MockitoJUnit; 16 | import org.mockito.quality.Strictness; 17 | 18 | /** 19 | * Class which takes screenshot captures when a test fails and applies mockito rule (building mocks, 20 | * reset, etc). 21 | * 22 | * We use this to avoid having to use GuiTestRunner which requires GuiTest annotation and also would 23 | * require definition of Mockito rule for proper mocks initialization. Additionally, this class uses 24 | * existing failsafe reports directory to put failed-gui-tests which is cleaner than creating such 25 | * directory in root project directory (which is what GuiTestRunner does). 26 | */ 27 | public class SwingTestRunner extends BlockJUnit4ClassRunner { 28 | 29 | private static final FailureScreenshotTaker SCREENSHOT_TAKER = new FailureScreenshotTaker( 30 | buildGuiScreenshotsFolder()); 31 | private static final MethodRule MOCKITO_RULE = MockitoJUnit.rule().strictness(Strictness.LENIENT); 32 | 33 | private static File buildGuiScreenshotsFolder() { 34 | File ret = Paths.get("target", "failsafe-reports", "failed-gui-tests").toFile(); 35 | Files.delete(ret); 36 | ret.mkdirs(); 37 | return ret; 38 | } 39 | 40 | public SwingTestRunner(Class klass) throws InitializationError { 41 | super(klass); 42 | } 43 | 44 | @Override 45 | protected Statement methodInvoker(FrameworkMethod method, Object test) { 46 | return new Statement() { 47 | @Override 48 | public void evaluate() throws Throwable { 49 | try { 50 | method.invokeExplosively(test); 51 | } catch (Throwable t) { 52 | takeScreenshot(); 53 | throw t; 54 | } 55 | } 56 | 57 | private void takeScreenshot() { 58 | SCREENSHOT_TAKER 59 | .saveScreenshot(testNameFrom(method.getDeclaringClass(), method.getMethod())); 60 | } 61 | }; 62 | } 63 | 64 | @Override 65 | protected List rules(Object target) { 66 | List ret = super.rules(target); 67 | ret.add(MOCKITO_RULE); 68 | return ret; 69 | } 70 | 71 | } 72 | 73 | -------------------------------------------------------------------------------- /citrix-jmeter/src/test/java/com/blazemeter/jmeter/citrix/sampler/InteractionSamplerTest.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.sampler; 2 | 3 | import static org.junit.Assert.assertArrayEquals; 4 | 5 | import com.blazemeter.jmeter.citrix.sampler.InteractionSampler.Keystroke; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import org.junit.Test; 9 | 10 | public class InteractionSamplerTest { 11 | 12 | @Test 13 | public void generateKeystrokesFromText() { 14 | // From written text it gets the virtual key code to be used 15 | List keystrokes = InteractionSampler.sampleTextKeystrokes("Ctrx"); 16 | 17 | List expected = new ArrayList<>(); 18 | expected.add(new Keystroke(16, false, false)); 19 | expected.add(new Keystroke(67, false, true)); 20 | expected.add(new Keystroke(67, true, false)); 21 | expected.add(new Keystroke(16, true, false)); 22 | expected.add(new Keystroke(84, false, true)); 23 | expected.add(new Keystroke(84, true, false)); 24 | expected.add(new Keystroke(82, false, true)); 25 | expected.add(new Keystroke(82, true, false)); 26 | expected.add(new Keystroke(88, false, true)); 27 | expected.add(new Keystroke(88, true, true)); 28 | 29 | assertArrayEquals(expected.toArray(), keystrokes.toArray()); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /citrix-jmeter/src/test/java/com/blazemeter/jmeter/citrix/sampler/SampleHelperTest.java: -------------------------------------------------------------------------------- 1 | package com.blazemeter.jmeter.citrix.sampler; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import com.blazemeter.jmeter.citrix.client.CitrixClient; 6 | import com.blazemeter.jmeter.citrix.client.events.EventHelper; 7 | import com.blazemeter.jmeter.citrix.client.events.InteractionEvent; 8 | import com.blazemeter.jmeter.citrix.client.events.InteractionEvent.KeyState; 9 | import com.blazemeter.jmeter.citrix.client.events.Modifier; 10 | import com.blazemeter.jmeter.citrix.client.windows.WinCitrixClient; 11 | import com.blazemeter.jmeter.citrix.recorder.CaptureItem; 12 | import java.awt.event.KeyEvent; 13 | import org.junit.Test; 14 | 15 | public class SampleHelperTest { 16 | 17 | // This class is created to simplify the creation of events, just to be used in this test. 18 | private static class CustomKeyCaptureGroup extends SamplerHelper.KeyCaptureGroup { 19 | 20 | CustomKeyCaptureGroup(SamplerHelper.KeySamplerType type) { 21 | super(type); 22 | } 23 | 24 | protected void addCaptureKeyEvent( 25 | CitrixClient client, int keyCode, int modifier) { 26 | this.items.add(new CaptureItem( 27 | new InteractionEvent(client, client.getForegroundWindowID(), 28 | client.getForegroundWindowArea(), 29 | KeyState.KEY_DOWN, keyCode, 30 | EventHelper.toModifiers(modifier) 31 | ) 32 | )); 33 | this.items.add(new CaptureItem( 34 | new InteractionEvent(client, client.getForegroundWindowID(), 35 | client.getForegroundWindowArea(), 36 | KeyState.KEY_UP, keyCode, 37 | EventHelper.toModifiers(0) // Always KeyUp lost the modifier state 38 | ) 39 | )); 40 | } 41 | } 42 | 43 | @Test 44 | public void generateTextFromCapturedKeyEvents() { 45 | CustomKeyCaptureGroup group = new CustomKeyCaptureGroup(SamplerHelper.KeySamplerType.TEXT); 46 | 47 | WinCitrixClient client = new WinCitrixClient(); 48 | 49 | // The test write "Ctrx" using Key Events. 50 | // Use ASCII to ensure all virtual keyboard used are compatible to this 51 | 52 | group.addCaptureKeyEvent(client, KeyEvent.VK_C, Modifier.SHIFT.getValue()); 53 | group.addCaptureKeyEvent(client, KeyEvent.VK_T, 0); 54 | group.addCaptureKeyEvent(client, KeyEvent.VK_R, 0); 55 | group.addCaptureKeyEvent(client, KeyEvent.VK_X, 0); 56 | 57 | String text = SamplerHelper.getKeyCaptureGroupText(group); 58 | String expected = "Ctrx"; 59 | assertEquals(expected, text); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /citrix-jmeter/src/test/resources/4328_1536568867580.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/citrix-jmeter/src/test/resources/4328_1536568867580.png -------------------------------------------------------------------------------- /citrix-jmeter/src/test/resources/4328_1536568879467.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/citrix-jmeter/src/test/resources/4328_1536568879467.png -------------------------------------------------------------------------------- /citrix-jmeter/src/test/resources/citrixRecord.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 4328_1536568867580.png 8 | 9 | 10 | <html>Application started step</html> 11 | 12 | 13 | 1 \ first 14 | 15 | 16 | 17 | 18 | 19 | 20 | 4328_1536568879467.png 21 | 22 | 23 | <html>Text Input : RR<br></html> 24 | 25 | 26 | 2 \ second 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /citrix-jmeter/src/test/resources/hash_not_same_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/citrix-jmeter/src/test/resources/hash_not_same_01.png -------------------------------------------------------------------------------- /citrix-jmeter/src/test/resources/hash_not_same_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/citrix-jmeter/src/test/resources/hash_not_same_02.png -------------------------------------------------------------------------------- /citrix-jmeter/src/test/resources/hash_same_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/citrix-jmeter/src/test/resources/hash_same_01.png -------------------------------------------------------------------------------- /citrix-jmeter/src/test/resources/hash_same_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/citrix-jmeter/src/test/resources/hash_same_02.png -------------------------------------------------------------------------------- /citrix-jmeter/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /citrix-jmeter/src/test/resources/zipFile.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/citrix-jmeter/src/test/resources/zipFile.zip -------------------------------------------------------------------------------- /config/saveservice-excerpt.properties: -------------------------------------------------------------------------------- 1 | # Add the following line at the end of JMeter saveservice.properties file 2 | _com.blazemeter.jmeter.citrix.sampler.CitrixSampleResultConverter=collection -------------------------------------------------------------------------------- /config/setup-x64.reg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/config/setup-x64.reg -------------------------------------------------------------------------------- /config/setup-x86.reg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/config/setup-x86.reg -------------------------------------------------------------------------------- /images/app_started_sampler_step.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/app_started_sampler_step.png -------------------------------------------------------------------------------- /images/app_started_window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/app_started_window.png -------------------------------------------------------------------------------- /images/assertion_creation_using_step.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/assertion_creation_using_step.png -------------------------------------------------------------------------------- /images/citrix_assertion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/citrix_assertion.png -------------------------------------------------------------------------------- /images/citrix_assessment_extractor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/citrix_assessment_extractor.png -------------------------------------------------------------------------------- /images/citrix_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/citrix_close.png -------------------------------------------------------------------------------- /images/citrix_interaction_informations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/citrix_interaction_informations.png -------------------------------------------------------------------------------- /images/citrix_ocr_extractor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/citrix_ocr_extractor.png -------------------------------------------------------------------------------- /images/citrix_recorder_configuration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/citrix_recorder_configuration.png -------------------------------------------------------------------------------- /images/citrix_recording_template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/citrix_recording_template.png -------------------------------------------------------------------------------- /images/csv_data_set_config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/csv_data_set_config.png -------------------------------------------------------------------------------- /images/csv_data_set_config_data_sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/csv_data_set_config_data_sample.png -------------------------------------------------------------------------------- /images/debug_jtl_configure_detailed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/debug_jtl_configure_detailed.png -------------------------------------------------------------------------------- /images/download_ica.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/download_ica.png -------------------------------------------------------------------------------- /images/dwm_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/dwm_settings.png -------------------------------------------------------------------------------- /images/end_clause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/end_clause.png -------------------------------------------------------------------------------- /images/example_plan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/example_plan.png -------------------------------------------------------------------------------- /images/ica_file_saver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/ica_file_saver.png -------------------------------------------------------------------------------- /images/input_text_sampler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/input_text_sampler.png -------------------------------------------------------------------------------- /images/launcher_sampler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/launcher_sampler.png -------------------------------------------------------------------------------- /images/navigate_to_save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/navigate_to_save.png -------------------------------------------------------------------------------- /images/no_scaling_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/no_scaling_settings.png -------------------------------------------------------------------------------- /images/notepad_citrix_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/notepad_citrix_example.png -------------------------------------------------------------------------------- /images/playback_view_results_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/playback_view_results_tree.png -------------------------------------------------------------------------------- /images/playback_view_results_tree_request_tab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/playback_view_results_tree_request_tab.png -------------------------------------------------------------------------------- /images/playback_view_results_tree_response_data_tab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/playback_view_results_tree_response_data_tab.png -------------------------------------------------------------------------------- /images/recorder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/recorder.png -------------------------------------------------------------------------------- /images/recorder_status_started.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/recorder_status_started.png -------------------------------------------------------------------------------- /images/recording_panel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/recording_panel.png -------------------------------------------------------------------------------- /images/save_popup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/save_popup.png -------------------------------------------------------------------------------- /images/session_state_assertion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/session_state_assertion.png -------------------------------------------------------------------------------- /images/start_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/start_button.png -------------------------------------------------------------------------------- /images/stop_recording_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/stop_recording_button.png -------------------------------------------------------------------------------- /images/template_test_plan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/template_test_plan.png -------------------------------------------------------------------------------- /images/thread_group_config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/thread_group_config.png -------------------------------------------------------------------------------- /images/updates_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/updates_settings.png -------------------------------------------------------------------------------- /images/vrt_citrix_renderer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/vrt_citrix_renderer.png -------------------------------------------------------------------------------- /images/vrt_citrix_renderer_selection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/vrt_citrix_renderer_selection.png -------------------------------------------------------------------------------- /images/vrt_display_sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/vrt_display_sample.png -------------------------------------------------------------------------------- /images/vrt_saving_recording.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/vrt_saving_recording.png -------------------------------------------------------------------------------- /images/windows_balck_screen_issue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Blazemeter/CitrixPlugin/f9e58f6dc303d98ff33509680b3a17f26ea47eae/images/windows_balck_screen_issue.png --------------------------------------------------------------------------------