├── runtime-decompiler
├── .plugin_config
└── src
│ ├── main
│ ├── resources
│ │ ├── icons
│ │ │ ├── add_24dp.png
│ │ │ ├── attach_24dp.png
│ │ │ ├── detach_24dp.png
│ │ │ ├── init_24dp.png
│ │ │ ├── insert_24dp.png
│ │ │ ├── main-icon.png
│ │ │ ├── redo_24dp.png
│ │ │ ├── remove_24dp.png
│ │ │ ├── trash_24dp.png
│ │ │ ├── undo_24dp.png
│ │ │ ├── upload_24dp.png
│ │ │ ├── compile_24dp.png
│ │ │ ├── refresh_24dp.png
│ │ │ └── overwrite_24dp.png
│ │ └── org
│ │ │ └── jrd
│ │ │ └── backend
│ │ │ └── data
│ │ │ └── metadata.prop
│ └── java
│ │ └── org
│ │ ├── fife
│ │ └── ui
│ │ │ └── hex
│ │ │ ├── package-info.java
│ │ │ ├── event
│ │ │ ├── HexEditorListener.java
│ │ │ ├── HexEditorEvent.java
│ │ │ ├── HexSearchActionListener.java
│ │ │ └── HexSearchDocumentListener.java
│ │ │ └── swing
│ │ │ ├── HexSearchParseException.java
│ │ │ ├── SearchState.java
│ │ │ ├── ByteArrayTransferable.java
│ │ │ └── HexEditorTransferHandler.java
│ │ ├── jrd
│ │ ├── backend
│ │ │ ├── communication
│ │ │ │ ├── JrdAgent.java
│ │ │ │ ├── TopLevelErrorCandidate.java
│ │ │ │ ├── ErrorCandidate.java
│ │ │ │ ├── DelegatingJrdAgent.java
│ │ │ │ └── CallDecompilerAgent.java
│ │ │ ├── data
│ │ │ │ ├── cli
│ │ │ │ │ ├── FontChangeListener.java
│ │ │ │ │ ├── utils
│ │ │ │ │ │ ├── ReceivedType.java
│ │ │ │ │ │ ├── FqnAndClassToJar.java
│ │ │ │ │ │ ├── PluginWrapperWithMetaInfo.java
│ │ │ │ │ │ ├── ObtainedCodeWithNameAndBytecode.java
│ │ │ │ │ │ ├── PluginWithOptions.java
│ │ │ │ │ │ ├── BytecodeSorter.java
│ │ │ │ │ │ └── Saving.java
│ │ │ │ │ ├── workers
│ │ │ │ │ │ ├── InitClass.java
│ │ │ │ │ │ ├── ListJvms.java
│ │ │ │ │ │ ├── Shared.java
│ │ │ │ │ │ ├── ListPlugins.java
│ │ │ │ │ │ ├── Api.java
│ │ │ │ │ │ ├── Overrides.java
│ │ │ │ │ │ ├── ListAgents.java
│ │ │ │ │ │ └── AttachDetach.java
│ │ │ │ │ └── InMemoryJar.java
│ │ │ │ ├── Model.java
│ │ │ │ ├── BytemanCompanion.java
│ │ │ │ ├── DependenciesReader.java
│ │ │ │ ├── ArchiveManagerOptions.java
│ │ │ │ └── Main.java
│ │ │ ├── decompiling
│ │ │ │ ├── DecompilerWrapperDeserializer.java
│ │ │ │ ├── DecompilerWrapperSerializer.java
│ │ │ │ └── JavapDisassemblerWrapper.java
│ │ │ ├── core
│ │ │ │ ├── agentstore
│ │ │ │ │ ├── AgentLiveliness.java
│ │ │ │ │ └── AgentLoneliness.java
│ │ │ │ ├── VmDecompilerStatus.java
│ │ │ │ ├── AgentAttachManager.java
│ │ │ │ └── AgentLoader.java
│ │ │ └── completion
│ │ │ │ └── JrdCompletionSettings.java
│ │ └── frontend
│ │ │ ├── frame
│ │ │ ├── main
│ │ │ │ ├── decompilerview
│ │ │ │ │ ├── dummycompiler
│ │ │ │ │ │ ├── providers
│ │ │ │ │ │ │ ├── ExecuteMethodProvider.java
│ │ │ │ │ │ │ ├── SaveProvider.java
│ │ │ │ │ │ │ ├── UploadProvider.java
│ │ │ │ │ │ │ ├── ClasspathProvider.java
│ │ │ │ │ │ │ └── MainProviders.java
│ │ │ │ │ │ ├── AbstractCompileAction.java
│ │ │ │ │ │ ├── NullClassesProvider.java
│ │ │ │ │ │ ├── JustBearerAction.java
│ │ │ │ │ │ ├── templates
│ │ │ │ │ │ │ ├── BytemanTemplateMenuItem.java
│ │ │ │ │ │ │ ├── BytemanSkeletonTemplateMenuItem.java
│ │ │ │ │ │ │ ├── JasmTemplateMenuItem.java
│ │ │ │ │ │ │ └── Jasm2TemplateMenuItem.java
│ │ │ │ │ │ ├── ClassesAndMethodsProviderBasedClassesProvider.java
│ │ │ │ │ │ └── AbstractCompileAndRunAction.java
│ │ │ │ │ ├── verifiers
│ │ │ │ │ │ ├── GetSetText.java
│ │ │ │ │ │ ├── FileVerifier.java
│ │ │ │ │ │ ├── ClassVerifier.java
│ │ │ │ │ │ └── JarVerifier.java
│ │ │ │ │ ├── LinesProvider.java
│ │ │ │ │ ├── UndoRedoKeyAdapter.java
│ │ │ │ │ ├── InitAddClassJar.java
│ │ │ │ │ ├── ClassOverwriter.java
│ │ │ │ │ └── SupportedKeySets.java
│ │ │ │ ├── LoadingDialogProvider.java
│ │ │ │ ├── ModelProvider.java
│ │ │ │ ├── popup
│ │ │ │ │ ├── SingleFilePatch.java
│ │ │ │ │ └── ClassListPopupMenu.java
│ │ │ │ └── LoadingDialog.java
│ │ │ ├── plugins
│ │ │ │ ├── MessagePanel.java
│ │ │ │ ├── FileSelectorArrayAddRow.java
│ │ │ │ ├── TextInputPanel.java
│ │ │ │ ├── PluginListPanel.java
│ │ │ │ ├── PluginTopOptionPanel.java
│ │ │ │ ├── ConfigPanel.java
│ │ │ │ ├── FileSelectorPanel.java
│ │ │ │ └── FileSelectorArrayPanel.java
│ │ │ ├── remote
│ │ │ │ └── NewConnectionController.java
│ │ │ ├── overwrite
│ │ │ │ ├── LatestPaths.java
│ │ │ │ └── FileToClassValidator.java
│ │ │ ├── license
│ │ │ │ └── LicenseView.java
│ │ │ ├── about
│ │ │ │ └── AboutView.java
│ │ │ ├── filesystem
│ │ │ │ └── NewFsVmController.java
│ │ │ └── settings
│ │ │ │ ├── ChangeReporter.java
│ │ │ │ └── AgentSettingsPanel.java
│ │ │ └── utility
│ │ │ └── TeeOutputStream.java
│ │ └── kcc
│ │ ├── wordsets
│ │ └── ConnectedKeywords.java
│ │ ├── KeywordBasedCodeCompletionMain.java
│ │ └── CompletionItem.java
│ ├── plugins
│ ├── CfrDecompilerWrapper.json
│ ├── JdDecompilerWrapper.json
│ ├── JasmDecompilerWrapper.json
│ ├── JasmGDecompilerWrapper.json
│ ├── JcoderDecompilerWrapper.json
│ ├── JcoderGDecompilerWrapper.json
│ ├── Jasm7DecompilerWrapper.json
│ ├── JasmG7DecompilerWrapper.json
│ ├── Jcoder7DecompilerWrapper.json
│ ├── JcoderG7DecompilerWrapper.json
│ ├── FernflowerDecompilerWrapper.json
│ ├── ProcyonDecompilerWrapper.json
│ ├── ProcyonAssemblerDecompilerWrapper.json
│ ├── JasmDecompilerWrapper.java
│ ├── JcoderDecompilerWrapper.java
│ ├── JasmGDecompilerWrapper.java
│ └── JcoderGDecompilerWrapper.java
│ └── test
│ ├── java
│ └── org
│ │ └── jrd
│ │ ├── backend
│ │ └── data
│ │ │ └── cli
│ │ │ ├── TestingDummyHelper.java
│ │ │ ├── ModifiableDummyTestingHelper.java
│ │ │ ├── ArchiveManagerOptionsTest.java
│ │ │ └── InMemoryJarTest.java
│ │ └── frontend
│ │ ├── utility
│ │ └── AgentApiGeneratorTest.java
│ │ └── frame
│ │ └── overwrite
│ │ └── OverwriteClassDialogTest.java
│ └── resources
│ └── org
│ └── jrd
│ └── frontend
│ └── frame
│ └── main
│ └── popup
│ ├── testPatch2
│ └── testPatch1
├── decompiler_agent
├── README.md
└── src
│ └── main
│ ├── java
│ └── org
│ │ └── jrd
│ │ ├── agent
│ │ ├── ReceivedType.java
│ │ ├── AgentLogger.java
│ │ ├── ClassFilter.java
│ │ └── api
│ │ │ └── ClassClassLoaderMap.java
│ │ └── backend
│ │ └── data
│ │ └── package-info.java
│ └── resources
│ └── org
│ └── jrd
│ └── backend
│ └── data
│ └── metadata.prop
├── .gitignore
├── images
├── hex.sh
└── pom.xml
├── .plugin_config
├── codestyle_suppressions.xml
└── spotbugs_exclude.xml
├── bumpVersion.sh
└── .github
└── workflows
└── maven.yaml
/runtime-decompiler/.plugin_config:
--------------------------------------------------------------------------------
1 | ../.plugin_config/
--------------------------------------------------------------------------------
/decompiler_agent/README.md:
--------------------------------------------------------------------------------
1 | # thermostat-decompiler-agent
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/resources/icons/add_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/judovana/java-runtime-decompiler/master/runtime-decompiler/src/main/resources/icons/add_24dp.png
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/resources/icons/attach_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/judovana/java-runtime-decompiler/master/runtime-decompiler/src/main/resources/icons/attach_24dp.png
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/resources/icons/detach_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/judovana/java-runtime-decompiler/master/runtime-decompiler/src/main/resources/icons/detach_24dp.png
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/resources/icons/init_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/judovana/java-runtime-decompiler/master/runtime-decompiler/src/main/resources/icons/init_24dp.png
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/resources/icons/insert_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/judovana/java-runtime-decompiler/master/runtime-decompiler/src/main/resources/icons/insert_24dp.png
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/resources/icons/main-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/judovana/java-runtime-decompiler/master/runtime-decompiler/src/main/resources/icons/main-icon.png
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/resources/icons/redo_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/judovana/java-runtime-decompiler/master/runtime-decompiler/src/main/resources/icons/redo_24dp.png
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/resources/icons/remove_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/judovana/java-runtime-decompiler/master/runtime-decompiler/src/main/resources/icons/remove_24dp.png
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/resources/icons/trash_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/judovana/java-runtime-decompiler/master/runtime-decompiler/src/main/resources/icons/trash_24dp.png
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/resources/icons/undo_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/judovana/java-runtime-decompiler/master/runtime-decompiler/src/main/resources/icons/undo_24dp.png
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/resources/icons/upload_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/judovana/java-runtime-decompiler/master/runtime-decompiler/src/main/resources/icons/upload_24dp.png
--------------------------------------------------------------------------------
/decompiler_agent/src/main/java/org/jrd/agent/ReceivedType.java:
--------------------------------------------------------------------------------
1 | package org.jrd.agent;
2 |
3 | public enum ReceivedType {
4 | OVERWRITE_CLASS,
5 | ADD_CLASS,
6 | ADD_JAR
7 | }
8 |
--------------------------------------------------------------------------------
/decompiler_agent/src/main/resources/org/jrd/backend/data/metadata.prop:
--------------------------------------------------------------------------------
1 | groupId=${project.groupId}
2 | name=${project.parent.name}
3 | timestamp=${timestamp}
4 | version=${project.version}
5 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/resources/icons/compile_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/judovana/java-runtime-decompiler/master/runtime-decompiler/src/main/resources/icons/compile_24dp.png
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/resources/icons/refresh_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/judovana/java-runtime-decompiler/master/runtime-decompiler/src/main/resources/icons/refresh_24dp.png
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/resources/org/jrd/backend/data/metadata.prop:
--------------------------------------------------------------------------------
1 | groupId=${project.groupId}
2 | name=${project.parent.name}
3 | timestamp=${timestamp}
4 | version=${project.version}
5 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/resources/icons/overwrite_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/judovana/java-runtime-decompiler/master/runtime-decompiler/src/main/resources/icons/overwrite_24dp.png
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/fife/ui/hex/package-info.java:
--------------------------------------------------------------------------------
1 | package org.fife.ui.hex;
2 | /*
3 | * Reincarnation - by decompilation of the only found binary - of http://fifesoft.com/#/hexeditor
4 | */
5 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/communication/JrdAgent.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.communication;
2 |
3 | public interface JrdAgent {
4 |
5 | String submitRequest(String request);
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/data/cli/FontChangeListener.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data.cli;
2 |
3 | public interface FontChangeListener {
4 |
5 | void adjustFont(float value);
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/data/cli/utils/ReceivedType.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data.cli.utils;
2 |
3 | public enum ReceivedType {
4 | OVERWRITE_CLASS,
5 | ADD_CLASS,
6 | ADD_JAR
7 | }
8 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/decompilerview/dummycompiler/providers/ExecuteMethodProvider.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main.decompilerview.dummycompiler.providers;
2 |
3 | public interface ExecuteMethodProvider {
4 |
5 | String getMethodToExecute();
6 | }
7 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/decompilerview/dummycompiler/providers/SaveProvider.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main.decompilerview.dummycompiler.providers;
2 |
3 | import java.io.File;
4 |
5 | public interface SaveProvider {
6 |
7 | File getSaveDirectory();
8 | }
9 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/fife/ui/hex/event/HexEditorListener.java:
--------------------------------------------------------------------------------
1 | //
2 | // Decompiled by Procyon v0.5.36
3 | //
4 |
5 | package org.fife.ui.hex.event;
6 |
7 | import java.util.EventListener;
8 |
9 | public interface HexEditorListener extends EventListener {
10 | void hexBytesChanged(HexEditorEvent p0);
11 | }
12 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/plugins/CfrDecompilerWrapper.json:
--------------------------------------------------------------------------------
1 | {
2 | "Name": "Cfr",
3 | "WrapperURL": "file://${XDG_CONFIG_HOME}/plugins/CfrDecompilerWrapper.java",
4 | "DependencyURL": [
5 | "file://${HOME}/.m2/repository/org/benf/cfr/0.152/cfr-0.152.jar"
6 | ],
7 | "DecompilerDownloadURL": "https://www.benf.org/other/cfr/faq.html"
8 | }
9 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/plugins/JdDecompilerWrapper.json:
--------------------------------------------------------------------------------
1 | {
2 | "Name": "JD",
3 | "WrapperURL": "file://${XDG_CONFIG_HOME}/plugins/JdDecompilerWrapper.java",
4 | "DependencyURL": [
5 | "file://${HOME}/.m2/repository/org/jd/jd-core/1.1.3/jd-core-1.1.3.jar"
6 | ],
7 | "DecompilerDownloadURL": "https://github.com/java-decompiler/jd-core/"
8 | }
9 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/plugins/JasmDecompilerWrapper.json:
--------------------------------------------------------------------------------
1 | {
2 | "Name": "jasm",
3 | "WrapperURL": "file://${XDG_CONFIG_HOME}/plugins/JasmDecompilerWrapper.java",
4 | "DependencyURL": [
5 | "file://${HOME}/.m2/repository/org/openjdk/asmtools/9.0.b12-ea/asmtools-9.0.b12-ea.jar"
6 | ],
7 | "DecompilerDownloadURL": "https://github.com/openjdk/asmtools"
8 | }
9 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/plugins/JasmGDecompilerWrapper.json:
--------------------------------------------------------------------------------
1 | {
2 | "Name": "jasmG",
3 | "WrapperURL": "file://${XDG_CONFIG_HOME}/plugins/JasmGDecompilerWrapper.java",
4 | "DependencyURL": [
5 | "file://${HOME}/.m2/repository/org/openjdk/asmtools/9.0.b12-ea/asmtools-9.0.b12-ea.jar"
6 | ],
7 | "DecompilerDownloadURL": "https://github.com/openjdk/asmtools"
8 | }
9 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/plugins/JcoderDecompilerWrapper.json:
--------------------------------------------------------------------------------
1 | {
2 | "Name": "jcoder",
3 | "WrapperURL": "file://${XDG_CONFIG_HOME}/plugins/JcoderDecompilerWrapper.java",
4 | "DependencyURL": [
5 | "file://${HOME}/.m2/repository/org/openjdk/asmtools/9.0.b12-ea/asmtools-9.0.b12-ea.jar"
6 | ],
7 | "DecompilerDownloadURL": "https://github.com/openjdk/asmtools"
8 | }
9 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/plugins/JcoderGDecompilerWrapper.json:
--------------------------------------------------------------------------------
1 | {
2 | "Name": "jcoderG",
3 | "WrapperURL": "file://${XDG_CONFIG_HOME}/plugins/JcoderGDecompilerWrapper.java",
4 | "DependencyURL": [
5 | "file://${HOME}/.m2/repository/org/openjdk/asmtools/9.0.b12-ea/asmtools-9.0.b12-ea.jar"
6 | ],
7 | "DecompilerDownloadURL": "https://github.com/openjdk/asmtools"
8 | }
9 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/LoadingDialogProvider.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main;
2 |
3 | import java.awt.event.ActionListener;
4 |
5 | public interface LoadingDialogProvider {
6 | default void showLoadingDialog(ActionListener action, String title) {
7 | }
8 |
9 | default void hideLoadingDialog() {
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/plugins/Jasm7DecompilerWrapper.json:
--------------------------------------------------------------------------------
1 | {
2 | "Name": "jasm7",
3 | "WrapperURL": "file://${XDG_CONFIG_HOME}/plugins/Jasm7DecompilerWrapper.java",
4 | "DependencyURL": [
5 | "file://${HOME}/.m2/repository/org/openjdk/asmtools/asmtools-core/7.0.b10-ea/asmtools-core-7.0.b10-ea.jar"
6 | ],
7 | "DecompilerDownloadURL": "https://github.com/openjdk/asmtools"
8 | }
9 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/plugins/JasmG7DecompilerWrapper.json:
--------------------------------------------------------------------------------
1 | {
2 | "Name": "jasmG7",
3 | "WrapperURL": "file://${XDG_CONFIG_HOME}/plugins/JasmG7DecompilerWrapper.java",
4 | "DependencyURL": [
5 | "file://${HOME}/.m2/repository/org/openjdk/asmtools/asmtools-core/7.0.b10-ea/asmtools-core-7.0.b10-ea.jar"
6 | ],
7 | "DecompilerDownloadURL": "https://github.com/openjdk/asmtools"
8 | }
9 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/plugins/Jcoder7DecompilerWrapper.json:
--------------------------------------------------------------------------------
1 | {
2 | "Name": "jcoder7",
3 | "WrapperURL": "file://${XDG_CONFIG_HOME}/plugins/Jcoder7DecompilerWrapper.java",
4 | "DependencyURL": [
5 | "file://${HOME}/.m2/repository/org/openjdk/asmtools/asmtools-core/7.0.b10-ea/asmtools-core-7.0.b10-ea.jar"
6 | ],
7 | "DecompilerDownloadURL": "https://github.com/openjdk/asmtools"
8 | }
9 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/plugins/JcoderG7DecompilerWrapper.json:
--------------------------------------------------------------------------------
1 | {
2 | "Name": "jcoderG7",
3 | "WrapperURL": "file://${XDG_CONFIG_HOME}/plugins/JcoderG7DecompilerWrapper.java",
4 | "DependencyURL": [
5 | "file://${HOME}/.m2/repository/org/openjdk/asmtools/asmtools-core/7.0.b10-ea/asmtools-core-7.0.b10-ea.jar"
6 | ],
7 | "DecompilerDownloadURL": "https://github.com/openjdk/asmtools"
8 | }
9 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/fife/ui/hex/swing/HexSearchParseException.java:
--------------------------------------------------------------------------------
1 | package org.fife.ui.hex.swing;
2 |
3 | public class HexSearchParseException extends RuntimeException {
4 | public HexSearchParseException(String exceptionMessage) {
5 | super(exceptionMessage);
6 | }
7 |
8 | public String getName() {
9 | return "HexSearch parse error";
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/decompilerview/dummycompiler/providers/UploadProvider.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main.decompilerview.dummycompiler.providers;
2 |
3 | public interface UploadProvider {
4 |
5 | ClasspathProvider getTarget();
6 |
7 | boolean isUploadEnabled();
8 |
9 | void resetUpload();
10 |
11 | boolean isBoot();
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/ModelProvider.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main;
2 |
3 | import org.jrd.backend.data.VmInfo;
4 | import org.jrd.backend.data.VmManager;
5 |
6 | import io.github.mkoncek.classpathless.api.ClassesProvider;
7 |
8 | public interface ModelProvider {
9 |
10 | VmInfo getVmInfo();
11 |
12 | VmManager getVmManager();
13 |
14 | ClassesProvider getClassesProvider();
15 | }
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #image creation output
2 | build.log
3 | images/build.log
4 |
5 | # Compiled class file
6 | *.class
7 |
8 | # Log file
9 | *.log
10 |
11 | # BlueJ files
12 | *.ctxt
13 |
14 | # Mobile Tools for Java (J2ME)
15 | .mtj.tmp/
16 |
17 | #IDEA
18 | .idea/
19 | *.iml
20 | target/
21 |
22 | # Package Files #
23 | *.jar
24 | *.war
25 | *.ear
26 | *.zip
27 | *.tar.gz
28 | *.rar
29 |
30 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
31 | hs_err_pid*
32 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/popup/SingleFilePatch.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main.popup;
2 |
3 | public class SingleFilePatch {
4 | private final int start;
5 | private final int end;
6 |
7 | public SingleFilePatch(int start, int end) {
8 | this.start = start;
9 | this.end = end;
10 | }
11 |
12 | public int getStart() {
13 | return start;
14 | }
15 |
16 | public int getEnd() {
17 | return end;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/data/cli/utils/FqnAndClassToJar.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data.cli.utils;
2 |
3 | import java.io.File;
4 |
5 | public class FqnAndClassToJar {
6 | private final String fqn;
7 | private final File file;
8 |
9 | public FqnAndClassToJar(String fqn, File file) {
10 | this.fqn = fqn;
11 | this.file = file;
12 | }
13 |
14 | public String getFqn() {
15 | return fqn;
16 | }
17 |
18 | public File getFile() {
19 | return file;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/plugins/FernflowerDecompilerWrapper.json:
--------------------------------------------------------------------------------
1 | {
2 | "Name": "Fernflower",
3 | "WrapperURL": "file://${XDG_CONFIG_HOME}/plugins/FernflowerDecompilerWrapper.java",
4 | "DependencyURL": [
5 | "file://${HOME}/.m2/repository/org/jboss/windup/decompiler/decompiler-fernflower/6.3.9.Final/decompiler-fernflower-6.3.9.Final.jar",
6 | "file://${HOME}/.m2/repository/org/jboss/windup/decompiler/fernflower/windup-fernflower/1.0.0.20171018/windup-fernflower-1.0.0.20171018.jar"
7 | ],
8 | "DecompilerDownloadURL": "https://github.com/JetBrains/intellij-community/tree/master/plugins/java-decompiler/engine"
9 | }
10 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/decompilerview/dummycompiler/AbstractCompileAction.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main.decompilerview.dummycompiler;
2 |
3 | import javax.swing.JMenuItem;
4 |
5 | public abstract class AbstractCompileAction extends JMenuItem {
6 |
7 | private final String stub;
8 |
9 | public AbstractCompileAction(String stub) {
10 | this.stub = stub;
11 | }
12 |
13 | @Override
14 | public String getText() {
15 | return "" + stub + "";
16 | }
17 |
18 | public Object getStub() {
19 | return stub;
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/fife/ui/hex/swing/SearchState.java:
--------------------------------------------------------------------------------
1 | package org.fife.ui.hex.swing;
2 |
3 | public final class SearchState {
4 | private final int start;
5 | private final int end;
6 | private final boolean found;
7 |
8 | public SearchState(int start, int end, boolean found) {
9 | this.start = start;
10 | this.end = end;
11 | this.found = found;
12 | }
13 |
14 | public int getStart() {
15 | return start;
16 | }
17 |
18 | public int getEnd() {
19 | return end;
20 | }
21 |
22 | public boolean isFound() {
23 | return found;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/data/cli/utils/PluginWrapperWithMetaInfo.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data.cli.utils;
2 |
3 | public class PluginWrapperWithMetaInfo {
4 | private final PluginWithOptions wrapper;
5 | private final boolean haveCompiler;
6 |
7 | public PluginWrapperWithMetaInfo(PluginWithOptions wrapper, boolean haveCompiler) {
8 | this.wrapper = wrapper;
9 | this.haveCompiler = haveCompiler;
10 | }
11 |
12 | public PluginWithOptions getWrapper() {
13 | return wrapper;
14 | }
15 |
16 | public boolean haveCompiler() {
17 | return haveCompiler;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/decompiler_agent/src/main/java/org/jrd/backend/data/package-info.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data;
2 |
3 | /**
4 | * This package contains copypasted code from runtime-decompiler
5 | * This should remain as it is without excuses. Any developmen should happen in runtime-decompiler and then copypasted here.
6 | *
7 | * Thsi duplication have to remain minimal. Currently the only one file here should be
8 | * - MetadataProperties.java
9 | * - metadata.prop
10 | * which ensures handshake between runtime-decompiler and agent
11 | * Both should remain identical for ever.
12 | *
13 | * Once windows support symlinks, just link them and we are done...
14 | */
15 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/data/Model.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data;
2 |
3 | import org.jrd.backend.decompiling.PluginManager;
4 |
5 | public final class Model {
6 |
7 | private VmManager vmManager = new VmManager();
8 | private PluginManager pluginManager = new PluginManager();
9 |
10 | private static final Model MODEL = new Model();
11 |
12 | private Model() {
13 | }
14 |
15 | public VmManager getVmManager() {
16 | return vmManager;
17 | }
18 |
19 | public PluginManager getPluginManager() {
20 | return pluginManager;
21 | }
22 |
23 | public static Model getModel() {
24 | return MODEL;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/decompilerview/verifiers/GetSetText.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main.decompilerview.verifiers;
2 |
3 | public interface GetSetText {
4 |
5 | String getText();
6 |
7 | void setText(String s);
8 |
9 | class DummyGetSet implements GetSetText {
10 | private String text;
11 |
12 | public DummyGetSet(String text) {
13 | this.text = text;
14 | }
15 |
16 | @Override
17 | public String getText() {
18 | return text;
19 | }
20 |
21 | @Override
22 | public void setText(String s) {
23 | text = s;
24 | }
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/plugins/ProcyonDecompilerWrapper.json:
--------------------------------------------------------------------------------
1 | {
2 | "Name": "Procyon",
3 | "WrapperURL": "file://${XDG_CONFIG_HOME}/plugins/ProcyonDecompilerWrapper.java",
4 | "DependencyURL": [
5 | "file://${HOME}/.m2/repository/com/github/mstrobel/procyon-core/1.0-SNAPSHOT/procyon-core-1.0-SNAPSHOT.jar",
6 | "file://${HOME}/.m2/repository/com/github/mstrobel/procyon-compilertools/1.0-SNAPSHOT/procyon-compilertools-1.0-SNAPSHOT.jar",
7 | "file://${HOME}/.m2/repository/com/github/mstrobel/procyon-decompiler/1.0-SNAPSHOT/procyon-decompiler-1.0-SNAPSHOT.jar",
8 | "file://${HOME}/.m2/repository/com/beust/jcommander/1.82/jcommander-1.82.jar"
9 | ],
10 | "DecompilerDownloadURL": "https://github.com/mstrobel/procyon/"
11 | }
12 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/plugins/ProcyonAssemblerDecompilerWrapper.json:
--------------------------------------------------------------------------------
1 | {
2 | "Name": "Procyon-Assembler",
3 | "WrapperURL": "file://${XDG_CONFIG_HOME}/plugins/ProcyonAssemblerDecompilerWrapper.java",
4 | "DependencyURL": [
5 | "file://${HOME}/.m2/repository/com/github/mstrobel/procyon-core/1.0-SNAPSHOT/procyon-core-1.0-SNAPSHOT.jar",
6 | "file://${HOME}/.m2/repository/com/github/mstrobel/procyon-compilertools/1.0-SNAPSHOT/procyon-compilertools-1.0-SNAPSHOT.jar",
7 | "file://${HOME}/.m2/repository/com/github/mstrobel/procyon-decompiler/1.0-SNAPSHOT/procyon-decompiler-1.0-SNAPSHOT.jar",
8 | "file://${HOME}/.m2/repository/com/beust/jcommander/1.82/jcommander-1.82.jar"
9 | ],
10 | "DecompilerDownloadURL": "https://github.com/mstrobel/procyon/"
11 | }
12 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/communication/TopLevelErrorCandidate.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.communication;
2 |
3 | public class TopLevelErrorCandidate extends ErrorCandidate {
4 | private static final String ERROR_RESPONSE = "error";
5 |
6 | public TopLevelErrorCandidate(String line) {
7 | super(line);
8 | }
9 |
10 | public static String topLevelErrorCandidateToError(String message) {
11 | return ERROR_RESPONSE + " " + message;
12 | }
13 |
14 | public static String topLevelErrorCandidateToError(Exception ex) {
15 | return topLevelErrorCandidateToError(ex.toString());
16 | }
17 |
18 | @Override
19 | protected String getIdentifier() {
20 | return ERROR_RESPONSE;
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/data/cli/utils/ObtainedCodeWithNameAndBytecode.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data.cli.utils;
2 |
3 | public class ObtainedCodeWithNameAndBytecode {
4 | private final String name;
5 | private final String base64Body;
6 | private final Integer bytecodeLevel;
7 |
8 | public ObtainedCodeWithNameAndBytecode(String name, String base64Body, Integer bytecodeLevel) {
9 | this.name = name;
10 | this.base64Body = base64Body;
11 | this.bytecodeLevel = bytecodeLevel;
12 | }
13 |
14 | public String getName() {
15 | return name;
16 | }
17 |
18 | public String getBase64Body() {
19 | return base64Body;
20 | }
21 |
22 | public Integer getBytecodeLevel() {
23 | return bytecodeLevel;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/images/hex.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | ## resolve folder of this script, following all symlinks:
4 | ## http://stackoverflow.com/questions/59895/can-a-bash-script-tell-what-directory-its-stored-in
5 | SCRIPT_SOURCE="${BASH_SOURCE[0]}"
6 | while [ -h "$SCRIPT_SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
7 | SCRIPT_DIR="$( cd -P "$( dirname "$SCRIPT_SOURCE" )" && pwd )"
8 | SCRIPT_SOURCE="$(readlink "$SCRIPT_SOURCE")"
9 | # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
10 | [[ $SCRIPT_SOURCE != /* ]] && SCRIPT_SOURCE="$SCRIPT_DIR/$SCRIPT_SOURCE"
11 | done
12 | readonly THIS_SCRIPT_DIR="$( cd -P "$( dirname "$SCRIPT_SOURCE" )" && pwd )"
13 | readonly SCRIPT_DIR=`readlink -f "$THIS_SCRIPT_DIR/../"`
14 |
15 | sh $THIS_SCRIPT_DIR/start.sh -hex "$@"
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/decompilerview/dummycompiler/NullClassesProvider.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main.decompilerview.dummycompiler;
2 |
3 | import io.github.mkoncek.classpathless.api.ClassIdentifier;
4 | import io.github.mkoncek.classpathless.api.ClassesProvider;
5 | import io.github.mkoncek.classpathless.api.IdentifiedBytecode;
6 |
7 | import java.util.ArrayList;
8 | import java.util.Collection;
9 | import java.util.List;
10 |
11 | class NullClassesProvider implements ClassesProvider {
12 | @Override
13 | public Collection getClass(ClassIdentifier... classIdentifiers) {
14 | return new ArrayList<>(0);
15 | }
16 |
17 | @Override
18 | public List getClassPathListing() {
19 | return new ArrayList(0);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/data/cli/utils/PluginWithOptions.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data.cli.utils;
2 |
3 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
4 | import org.jrd.backend.decompiling.DecompilerWrapper;
5 |
6 | public class PluginWithOptions {
7 |
8 | private final DecompilerWrapper decompiler;
9 | private final String[] options;
10 |
11 | public PluginWithOptions(DecompilerWrapper decompiler, String[] options) {
12 | this.decompiler = decompiler;
13 | this.options = options;
14 | }
15 |
16 | @SuppressFBWarnings("EI_EXPOSE_REP")
17 | public DecompilerWrapper getDecompiler() {
18 | return decompiler;
19 | }
20 |
21 | @SuppressFBWarnings("EI_EXPOSE_REP")
22 | public String[] getOptions() {
23 | return options;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/plugins/MessagePanel.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.plugins;
2 |
3 | import javax.swing.JLabel;
4 | import javax.swing.JPanel;
5 | import java.awt.BorderLayout;
6 | import java.awt.Color;
7 | import java.awt.Dimension;
8 |
9 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
10 |
11 | @SuppressFBWarnings(value = "CT_CONSTRUCTOR_THROW", justification = "be aware, this constrctor throws")
12 | public class MessagePanel extends JPanel {
13 |
14 | private final JLabel jLabel;
15 |
16 | MessagePanel(String message) {
17 | this.setLayout(new BorderLayout());
18 | this.setBackground(Color.decode("#14b7e0"));
19 | this.setPreferredSize(new Dimension(0, 40));
20 |
21 | jLabel = new JLabel();
22 | jLabel.setText(message);
23 | this.add(jLabel);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/test/java/org/jrd/backend/data/cli/TestingDummyHelper.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data.cli;
2 |
3 | class TestingDummyHelper extends AbstractSourceTestClass {
4 |
5 | @Override
6 | protected String getClassName() {
7 | return "TestingDummy";
8 | }
9 |
10 | @Override
11 | protected String getPackageName() {
12 | return "testing.dummy";
13 | }
14 |
15 | @Override
16 | String getContentWithoutPackage(String nwHello) {
17 | return "public class " + getClassName() + " {\n" + " public static void main(String[] args) throws InterruptedException {\n" +
18 | " while(true) {\n" + " System.out.println(\"" + nwHello + "\");\n" + " Thread.sleep(100);\n" +
19 | " }\n" + " }\n" + "}\n";
20 | }
21 |
22 | @Override
23 | String getGreetings() {
24 | return "Hello";
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/decompilerview/LinesProvider.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main.decompilerview;
2 |
3 | import javax.swing.JComponent;
4 | import java.io.File;
5 | import java.io.IOException;
6 | import java.util.List;
7 |
8 | public interface LinesProvider {
9 |
10 | enum LinesFormat {
11 | CHARS,
12 | HEX
13 | }
14 |
15 | List getLines(LinesFormat type);
16 |
17 | String getName();
18 |
19 | void setLines(LinesFormat type, List nwContent) throws Exception;
20 |
21 | boolean isBin();
22 |
23 | default boolean isText() {
24 | return !isBin();
25 | }
26 |
27 | File getFile();
28 |
29 | void setFile(File f);
30 |
31 | void open(File f) throws IOException;
32 |
33 | void save(File f) throws IOException;
34 |
35 | JComponent asComponent();
36 |
37 | void undo();
38 |
39 | void redo();
40 |
41 | void resetUndoRedo();
42 |
43 | void close();
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/decompilerview/dummycompiler/providers/ClasspathProvider.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main.decompilerview.dummycompiler.providers;
2 |
3 | import org.jrd.backend.completion.ClassesAndMethodsProvider;
4 | import org.jrd.backend.data.VmInfo;
5 | import org.jrd.backend.data.VmManager;
6 |
7 | public interface ClasspathProvider {
8 |
9 | ClassesAndMethodsProvider getClasspath();
10 |
11 | VmInfo getVmInfo();
12 |
13 | VmManager getVmManager();
14 |
15 | class SettingsClasspathProvider implements ClasspathProvider {
16 |
17 | @Override
18 | public ClassesAndMethodsProvider getClasspath() {
19 | return new ClassesAndMethodsProvider.SettingsClassesAndMethodsProvider();
20 | }
21 |
22 | @Override
23 | public VmInfo getVmInfo() {
24 | return null;
25 | }
26 |
27 | @Override
28 | public VmManager getVmManager() {
29 | return null;
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/test/java/org/jrd/backend/data/cli/ModifiableDummyTestingHelper.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data.cli;
2 |
3 | class ModifiableDummyTestingHelper extends AbstractSourceTestClass {
4 |
5 | @Override
6 | protected String getClassName() {
7 | return "TestingModifiableDummy";
8 | }
9 |
10 | @Override
11 | protected String getPackageName() {
12 | return "testing.modifiabledummy";
13 | }
14 |
15 | @Override
16 | String getContentWithoutPackage(String nwHello) {
17 | return "public class " + getClassName() + " {\n" + " public static void main(String[] args) throws InterruptedException {\n" +
18 | " while(true) {\n" + " new " + getClassName() + "().print();\n" + " Thread.sleep(100);\n" +
19 | " }\n" + " }\n" + " private void print(){\n/*API_PLACEHOLDER*/\nSystem.out.println(\"" + nwHello + "\");}\n" +
20 | "}\n";
21 | }
22 |
23 | @Override
24 | String getGreetings() {
25 | return "Hello";
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/data/cli/workers/InitClass.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data.cli.workers;
2 |
3 | import org.jrd.backend.data.VmInfo;
4 | import org.jrd.backend.data.VmManager;
5 | import org.jrd.backend.data.cli.CliUtils;
6 | import org.jrd.backend.data.cli.Help;
7 | import org.jrd.backend.data.cli.Lib;
8 |
9 | import java.util.List;
10 |
11 | public class InitClass {
12 |
13 | private final List filteredArgs;
14 | private final VmManager vmManager;
15 |
16 | public InitClass(List filteredArgs, VmManager vmManager) {
17 | this.filteredArgs = filteredArgs;
18 | this.vmManager = vmManager;
19 | }
20 |
21 | public VmInfo init() throws Exception {
22 | if (filteredArgs.size() != 3) {
23 | throw new IllegalArgumentException("Incorrect argument count! Please use '" + Help.INIT_FORMAT + "'.");
24 | }
25 | String fqn = filteredArgs.get(2);
26 | VmInfo vmInfo = CliUtils.getVmInfo(filteredArgs.get(1), vmManager);
27 | Lib.initClass(vmInfo, vmManager, fqn, System.out);
28 | return vmInfo;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/decompilerview/dummycompiler/JustBearerAction.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main.decompilerview.dummycompiler;
2 |
3 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
4 |
5 | public class JustBearerAction extends AbstractCompileAction {
6 |
7 | private final String append;
8 | private AbstractCompileAction original;
9 |
10 | public JustBearerAction(String placeholder, String append) {
11 | super(placeholder + " - " + append);
12 | this.append = append;
13 | }
14 |
15 | @Override
16 | public String getText() {
17 | if (original == null) {
18 | return super.getText() + "
";
19 | } else {
20 | return super.getText() + "
" + original.getText();
21 | }
22 | }
23 |
24 | @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "looks good")
25 | public void setOriginal(AbstractCompileAction original) {
26 | this.original = original;
27 | this.setEnabled(true);
28 | this.setText("last used - " + original.getText() + " " + append);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/.plugin_config/codestyle_suppressions.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
15 |
16 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/fife/ui/hex/event/HexEditorEvent.java:
--------------------------------------------------------------------------------
1 | //
2 | // Decompiled by Procyon v0.5.36
3 | //
4 |
5 | package org.fife.ui.hex.event;
6 |
7 | import org.fife.ui.hex.swing.HexEditor;
8 |
9 | import java.util.EventObject;
10 |
11 | public class HexEditorEvent extends EventObject {
12 | private static final long serialVersionUID = 1L;
13 | private int offset;
14 | private int added;
15 | private int removed;
16 |
17 | public HexEditorEvent(final HexEditor editor, final int offs, final int added, final int removed) {
18 | super(editor);
19 | this.offset = offs;
20 | this.added = added;
21 | this.removed = removed;
22 | }
23 |
24 | public int getAddedCount() {
25 | return this.added;
26 | }
27 |
28 | public HexEditor getHexEditor() {
29 | return (HexEditor) this.getSource();
30 | }
31 |
32 | public int getOffset() {
33 | return this.offset;
34 | }
35 |
36 | public int getRemovedCount() {
37 | return this.removed;
38 | }
39 |
40 | public boolean isModification() {
41 | return this.getAddedCount() == this.getRemovedCount();
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/decompilerview/dummycompiler/providers/MainProviders.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main.decompilerview.dummycompiler.providers;
2 |
3 | public class MainProviders {
4 |
5 | private final ClasspathProvider classpathProvider;
6 | private final ExecuteMethodProvider execute;
7 | private final SaveProvider save;
8 | private final UploadProvider uploadProvider;
9 |
10 | public MainProviders(
11 | ClasspathProvider classpathProvider, ExecuteMethodProvider execute, SaveProvider save, UploadProvider uploadProvider
12 | ) {
13 | this.classpathProvider = classpathProvider;
14 | this.execute = execute;
15 | this.save = save;
16 | this.uploadProvider = uploadProvider;
17 | }
18 |
19 | public ClasspathProvider getClasspathProvider() {
20 | return classpathProvider;
21 | }
22 |
23 | public ExecuteMethodProvider getExecute() {
24 | return execute;
25 | }
26 |
27 | public SaveProvider getSave() {
28 | return save;
29 | }
30 |
31 | public UploadProvider getUploadProvider() {
32 | return uploadProvider;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/plugins/FileSelectorArrayAddRow.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.plugins;
2 |
3 | import org.jrd.frontend.utility.ImageButtonFactory;
4 |
5 | import javax.swing.Box;
6 | import javax.swing.JButton;
7 | import javax.swing.JPanel;
8 | import java.awt.GridBagConstraints;
9 | import java.awt.GridBagLayout;
10 |
11 | public class FileSelectorArrayAddRow extends JPanel {
12 |
13 | private JButton addButton;
14 |
15 | FileSelectorArrayAddRow(int rightMargin) {
16 | this.setLayout(new GridBagLayout());
17 | GridBagConstraints gbc = new GridBagConstraints();
18 | gbc.anchor = GridBagConstraints.NORTHWEST;
19 | gbc.fill = GridBagConstraints.BOTH;
20 |
21 | addButton = ImageButtonFactory.createAddButton();
22 |
23 | gbc.weightx = 1;
24 | this.add(Box.createHorizontalGlue(), gbc);
25 |
26 | gbc.weightx = 0;
27 | gbc.gridx = 1;
28 | this.add(addButton, gbc);
29 |
30 | gbc.gridx = 2;
31 | this.add(Box.createHorizontalStrut(rightMargin), gbc);
32 | }
33 |
34 | public JButton getAddButton() {
35 | return addButton;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/decompilerview/UndoRedoKeyAdapter.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main.decompilerview;
2 |
3 | import java.awt.event.KeyAdapter;
4 | import java.awt.event.KeyEvent;
5 |
6 | import javax.swing.undo.UndoManager;
7 |
8 | class UndoRedoKeyAdapter extends KeyAdapter {
9 | private final SearchControlsPanel searchControlsPanel;
10 | private UndoManager undoManager = new UndoManager();
11 |
12 | UndoRedoKeyAdapter(SearchControlsPanel searchControlsPanel) {
13 | this.searchControlsPanel = searchControlsPanel;
14 | }
15 |
16 | @Override
17 | public void keyReleased(KeyEvent e) {
18 | if (e.getKeyCode() == KeyEvent.VK_F3) {
19 | searchControlsPanel.clickNextButton();
20 | }
21 | if (e.getModifiersEx() == KeyEvent.CTRL_DOWN_MASK) {
22 | if (e.getKeyCode() == KeyEvent.VK_Z && undoManager.canUndo()) {
23 | undoManager.undo();
24 | } else if (e.getKeyCode() == KeyEvent.VK_Y && undoManager.canRedo()) {
25 | undoManager.redo();
26 | }
27 | }
28 | }
29 |
30 | public UndoManager getUndoManager() {
31 | return undoManager;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/plugins/TextInputPanel.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.plugins;
2 |
3 | import javax.swing.JLabel;
4 | import javax.swing.JPanel;
5 | import javax.swing.JTextField;
6 | import java.awt.Dimension;
7 | import java.awt.GridBagConstraints;
8 | import java.awt.GridBagLayout;
9 |
10 | public class TextInputPanel extends JPanel {
11 |
12 | private final JTextField textField;
13 | private final JLabel jLabel;
14 |
15 | TextInputPanel(String label) {
16 | this();
17 | jLabel.setText(label);
18 | }
19 |
20 | TextInputPanel() {
21 | this.setPreferredSize(new Dimension(0, 80));
22 | this.setLayout(new GridBagLayout());
23 |
24 | textField = new JTextField();
25 | textField.setPreferredSize(new Dimension(0, 32));
26 | jLabel = new JLabel();
27 |
28 | GridBagConstraints gbc = new GridBagConstraints();
29 | gbc.anchor = GridBagConstraints.WEST;
30 | gbc.fill = GridBagConstraints.BOTH;
31 | this.add(jLabel, gbc);
32 | gbc.gridy = 1;
33 | gbc.weightx = 1;
34 | this.add(textField, gbc);
35 | }
36 |
37 | public JTextField getTextField() {
38 | return textField;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/decompilerview/dummycompiler/templates/BytemanTemplateMenuItem.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main.decompilerview.dummycompiler.templates;
2 |
3 | import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
4 |
5 | import javax.swing.JMenuItem;
6 | import java.awt.event.ActionEvent;
7 | import java.awt.event.ActionListener;
8 |
9 | public class BytemanTemplateMenuItem extends JMenuItem {
10 |
11 | private static final String STATIC_OBJECTFINALIZE =
12 | "\n" + "# Warning! If you change name of the rule, the automatic unloads/updates/deletes may stop to work.\n" +
13 | "# use final name before first submit to remote vm\n" + "RULE trace Object.finalize\n" + " CLASS ^java.lang.Object\n" +
14 | " METHOD " + "finalize\n" + " IF TRUE\n" + " DO System.out.println(\"Finalizing \" + $0)\n" + " ENDRULE";
15 |
16 | public BytemanTemplateMenuItem(final RSyntaxTextArea source) {
17 | super("byteman all finalizers");
18 | this.addActionListener(new ActionListener() {
19 | @Override
20 | public void actionPerformed(ActionEvent actionEvent) {
21 | source.append(STATIC_OBJECTFINALIZE);
22 | }
23 | });
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/plugins/PluginListPanel.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.plugins;
2 |
3 | import javax.swing.JButton;
4 | import javax.swing.JList;
5 | import javax.swing.JPanel;
6 | import javax.swing.ListSelectionModel;
7 | import java.awt.BorderLayout;
8 | import java.awt.Dimension;
9 | import org.jrd.backend.decompiling.DecompilerWrapper;
10 |
11 | public class PluginListPanel extends JPanel {
12 |
13 | private final JList wrapperJList;
14 | private final JButton addWrapperButton;
15 |
16 | PluginListPanel() {
17 | this.setLayout(new BorderLayout());
18 | this.setPreferredSize(new Dimension(180, 0));
19 |
20 | wrapperJList = new JList<>();
21 | wrapperJList.setFixedCellHeight(32);
22 | wrapperJList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
23 | addWrapperButton = new JButton("New");
24 | addWrapperButton.setPreferredSize(new Dimension(0, 28));
25 |
26 | this.add(wrapperJList, BorderLayout.CENTER);
27 | this.add(addWrapperButton, BorderLayout.NORTH);
28 | }
29 |
30 | public JList getWrapperJList() {
31 | return wrapperJList;
32 | }
33 |
34 | public JButton getAddWrapperButton() {
35 | return addWrapperButton;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/utility/TeeOutputStream.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.utility;
2 |
3 | import java.io.ByteArrayOutputStream;
4 | import java.io.PrintStream;
5 | import java.nio.charset.StandardCharsets;
6 |
7 | /**
8 | * Behaves like the 'tee' command, sends output to both actual std stream and a
9 | * log
10 | */
11 | public final class TeeOutputStream extends PrintStream {
12 |
13 | // Everything written to TeeOutputStream is written to this buffer too
14 | private final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
15 |
16 | public TeeOutputStream(PrintStream stdStream) {
17 | super(stdStream, false, StandardCharsets.UTF_8);
18 | }
19 |
20 | /*
21 | * The big ones: these do the actual writing
22 | */
23 |
24 | @Override
25 | public synchronized void write(byte[] b, int off, int len) {
26 | if (len == 0) {
27 | return;
28 | }
29 | byteArrayOutputStream.write(b, off, len);
30 | super.write(b, off, len);
31 | }
32 |
33 | @Override
34 | public synchronized void write(int b) {
35 | byteArrayOutputStream.write(b);
36 | super.write(b);
37 | }
38 |
39 | public byte[] getByteArray() {
40 | return byteArrayOutputStream.toByteArray();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/data/cli/utils/BytecodeSorter.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data.cli.utils;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 | import java.util.Set;
6 |
7 | //todo, somehow reuse also for both compilations in patch and compile
8 | public interface BytecodeSorter {
9 |
10 | Map> sort();
11 |
12 | Integer decide();
13 |
14 | class HexDummySorter implements BytecodeSorter {
15 |
16 | private final Set> entrySet;
17 |
18 | public HexDummySorter(Set> entrySet) {
19 | this.entrySet = entrySet;
20 | }
21 |
22 | @Override
23 | public Map> sort() {
24 | Map> binariesToUpload = new HashMap();
25 | Map defaultByteCodeMap = new HashMap<>();
26 | for (Map.Entry singlePatched : entrySet) {
27 | defaultByteCodeMap.put(singlePatched.getKey(), singlePatched.getValue());
28 | }
29 | binariesToUpload.put(null, defaultByteCodeMap);
30 | return binariesToUpload;
31 | }
32 |
33 | @Override
34 | public Integer decide() {
35 | return null;
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/decompiling/DecompilerWrapperDeserializer.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.decompiling;
2 |
3 | import com.google.gson.JsonDeserializationContext;
4 | import com.google.gson.JsonDeserializer;
5 | import com.google.gson.JsonElement;
6 | import com.google.gson.JsonObject;
7 | import com.google.gson.JsonParseException;
8 |
9 | import java.lang.reflect.Type;
10 | import java.util.LinkedList;
11 | import java.util.List;
12 |
13 | public class DecompilerWrapperDeserializer implements JsonDeserializer {
14 |
15 | @Override
16 | public DecompilerWrapper deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext)
17 | throws JsonParseException {
18 | final JsonObject json = jsonElement.getAsJsonObject();
19 |
20 | final String name = json.get("Name").getAsString();
21 | final String wrapperURL = json.get("WrapperURL").getAsString();
22 |
23 | final List dependencyURLs = new LinkedList<>();
24 | json.get("DependencyURL").getAsJsonArray().forEach(dependency -> dependencyURLs.add(dependency.getAsString()));
25 |
26 | final String decompilerURL = json.get("DecompilerDownloadURL").getAsString();
27 |
28 | return new DecompilerWrapper(name, wrapperURL, dependencyURLs, decompilerURL);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/data/BytemanCompanion.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data;
2 |
3 | import java.io.Serializable;
4 |
5 | public class BytemanCompanion implements Serializable {
6 | private final int bytemanPort;
7 | private final String bytemanHost;
8 | private final int postBytemanAgentPort;
9 | private final String postBytemanAgentHost;
10 |
11 | public BytemanCompanion(String bytemanHost, int bytemanPort, String postBytemanAgentHost, int postBytemanAgentPort) {
12 | this.bytemanHost = bytemanHost;
13 | this.bytemanPort = bytemanPort;
14 | this.postBytemanAgentHost = postBytemanAgentHost;
15 | this.postBytemanAgentPort = postBytemanAgentPort;
16 | }
17 |
18 | public BytemanCompanion(String byteman, String companion) {
19 | this(
20 | byteman.split(":")[0], Integer.parseInt(byteman.split(":")[1]), companion.split(":")[0],
21 | Integer.parseInt(companion.split(":")[1])
22 | );
23 | }
24 |
25 | public int getBytemanPort() {
26 | return bytemanPort;
27 | }
28 |
29 | public int getPostBytemanAgentPort() {
30 | return postBytemanAgentPort;
31 | }
32 |
33 | public String getBytemanHost() {
34 | return bytemanHost;
35 | }
36 |
37 | public String getPostBytemanAgentHost() {
38 | return postBytemanAgentHost;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/decompiling/DecompilerWrapperSerializer.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.decompiling;
2 |
3 | import com.google.gson.JsonArray;
4 | import com.google.gson.JsonElement;
5 | import com.google.gson.JsonObject;
6 | import com.google.gson.JsonSerializationContext;
7 | import com.google.gson.JsonSerializer;
8 |
9 | import java.lang.reflect.Type;
10 |
11 | public class DecompilerWrapperSerializer implements JsonSerializer {
12 |
13 | @Override
14 | public JsonElement serialize(DecompilerWrapper decompilerWrapper, Type type, JsonSerializationContext jsonSerializationContext) {
15 | final JsonObject jsonObject = new JsonObject();
16 |
17 | jsonObject.addProperty("Name", decompilerWrapper.getName());
18 | jsonObject.addProperty("WrapperURL", decompilerWrapper.getWrapperUrl().getRawUrl());
19 |
20 | final JsonArray jsonArray = new JsonArray();
21 | decompilerWrapper.getDependencyUrls().forEach(url -> {
22 | jsonArray.add(url.getRawUrl());
23 | });
24 |
25 | jsonObject.add("DependencyURL", jsonArray);
26 | if (decompilerWrapper.getDecompilerDownloadUrl() == null) {
27 | jsonObject.addProperty("DecompilerDownloadURL", "");
28 | } else {
29 | jsonObject.addProperty("DecompilerDownloadURL", decompilerWrapper.getDecompilerDownloadUrl().toString());
30 | }
31 |
32 | return jsonObject;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/test/java/org/jrd/backend/data/cli/ArchiveManagerOptionsTest.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data.cli;
2 |
3 | import org.jrd.backend.data.ArchiveManagerOptions;
4 | import org.junit.jupiter.api.Assertions;
5 | import org.junit.jupiter.api.Test;
6 |
7 | import java.util.List;
8 |
9 | class ArchiveManagerOptionsTest {
10 |
11 | @Test
12 | void isInnerDefault() {
13 | ArchiveManagerOptions a1 = new ArchiveManagerOptions();
14 | Assertions.assertTrue(a1.isInner("some/file/filer.zip"));
15 | Assertions.assertTrue(a1.isInner("filer.WAR"));
16 | }
17 |
18 | @Test
19 | void isNotInnerDefault() {
20 | ArchiveManagerOptions a1 = new ArchiveManagerOptions();
21 | Assertions.assertFalse(a1.isInner("some/file/filerzip"));
22 | Assertions.assertFalse(a1.isInner("filerWAR"));
23 | }
24 |
25 | @Test
26 | void isInnerCustom() {
27 | ArchiveManagerOptions a1 = new ArchiveManagerOptions();
28 | a1.setExtensions(List.of("ZIP", "WAR"));
29 | Assertions.assertTrue(a1.isInner("some/file/filer.zip"));
30 | Assertions.assertTrue(a1.isInner("filer.WAR"));
31 | }
32 |
33 | @Test
34 | void isNotInnerCustom() {
35 | ArchiveManagerOptions a1 = new ArchiveManagerOptions();
36 | a1.setExtensions(List.of("Xzip", "xWAR"));
37 | Assertions.assertFalse(a1.isInner("some/file/filerzip"));
38 | Assertions.assertFalse(a1.isInner("filerWAR"));
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/decompilerview/verifiers/FileVerifier.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main.decompilerview.verifiers;
2 |
3 | import javax.swing.event.DocumentEvent;
4 | import javax.swing.event.DocumentListener;
5 | import java.io.File;
6 |
7 | public class FileVerifier implements DocumentListener {
8 |
9 | protected final GetSetText source;
10 | protected final GetSetText target;
11 |
12 | public FileVerifier(GetSetText source, GetSetText target) {
13 | this.source = source;
14 | this.target = target;
15 | }
16 |
17 | @Override
18 | public void insertUpdate(DocumentEvent documentEvent) {
19 | verifySource(documentEvent);
20 | }
21 |
22 | @Override
23 | public void removeUpdate(DocumentEvent documentEvent) {
24 | verifySource(documentEvent);
25 | }
26 |
27 | @Override
28 | public void changedUpdate(DocumentEvent documentEvent) {
29 | verifySource(documentEvent);
30 | }
31 |
32 | public boolean verifySource(DocumentEvent documentEvent) {
33 | File f = new File(source.getText());
34 | if (!f.exists()) {
35 | target.setText("file do not exists");
36 | return false;
37 | } else {
38 | if (f.isDirectory()) {
39 | target.setText("is directory");
40 | return false;
41 | }
42 | target.setText("ok");
43 | return true;
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/decompiler_agent/src/main/java/org/jrd/agent/AgentLogger.java:
--------------------------------------------------------------------------------
1 | package org.jrd.agent;
2 |
3 | /**
4 | * Class for logging exceptions in the Agent.
5 | */
6 | public class AgentLogger {
7 |
8 | private static final String NULL_OBJECT_MESSAGE = "Trying to log null object";
9 |
10 | private static final class AgentLoggerHolder {
11 | // https://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom
12 | // https://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java
13 | private static final AgentLogger INSTANCE = new AgentLogger();
14 | }
15 |
16 | public static AgentLogger getLogger() {
17 | return AgentLoggerHolder.INSTANCE;
18 | }
19 |
20 | public void log(Object o) {
21 | String s = "";
22 |
23 | if (o == null) {
24 | s = NULL_OBJECT_MESSAGE;
25 | } else if (o instanceof Throwable) {
26 | ((Throwable) o).printStackTrace();
27 | return;
28 | } else {
29 | s = o.toString();
30 | }
31 |
32 | System.err.println(s);
33 | }
34 |
35 | public static String classLoaderId(ClassLoader cl) {
36 | if (cl == null) {
37 | return "unknown";
38 | } else {
39 | return cl.toString();
40 | }
41 | }
42 |
43 | public static String moduleId(Module cl) {
44 | if (cl == null) {
45 | return "unknown";
46 | } else {
47 | return cl.getName();
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/communication/ErrorCandidate.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.communication;
2 |
3 | public class ErrorCandidate {
4 |
5 | private static final String ERROR_ID = "ERROR";
6 | private final String line;
7 |
8 | public ErrorCandidate(String line) {
9 | this.line = line;
10 | }
11 |
12 | protected String getIdentifier() {
13 | return ERROR_ID;
14 | }
15 |
16 | public String getLine() {
17 | return line;
18 | }
19 |
20 | public boolean isError() {
21 | return isErrorImpl(getLine()) != null;
22 | }
23 |
24 | public String getErrorMessage() {
25 | if (isError()) {
26 | return isErrorImpl(getLine());
27 | } else {
28 | return "This was not error - " + getLine();
29 | }
30 | }
31 |
32 | public static String errorCandidateToError(String message) {
33 | return ERROR_ID + " " + message;
34 | }
35 |
36 | public static String errorCandidateToError(Exception ex) {
37 | return errorCandidateToError(ex.toString());
38 | }
39 |
40 | /**
41 | * @return null if line is not error, empty string or message otherwise
42 | */
43 | private String isErrorImpl(String linex) {
44 | if (linex.startsWith(getIdentifier())) {
45 | String message = linex.replaceAll("^" + getIdentifier(), "").trim();
46 | return message;
47 | } else {
48 | return null;
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/decompilerview/verifiers/ClassVerifier.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main.decompilerview.verifiers;
2 |
3 | import org.jrd.backend.core.Logger;
4 | import org.jrd.backend.data.cli.Lib;
5 |
6 | import javax.swing.event.DocumentEvent;
7 | import java.io.File;
8 | import java.nio.file.Files;
9 |
10 | public class ClassVerifier extends FileVerifier {
11 |
12 | public ClassVerifier(GetSetText source, GetSetText target) {
13 | super(source, target);
14 | }
15 |
16 | public boolean verifySource(DocumentEvent documentEvent) {
17 | boolean intermezo = super.verifySource(documentEvent);
18 | if (intermezo) {
19 | File f = new File(source.getText());
20 | byte[] b = null;
21 | try {
22 | b = Files.readAllBytes(f.toPath());
23 | } catch (Exception ex) {
24 | target.setText(ex.getMessage());
25 | Logger.getLogger().log(ex);
26 | }
27 | if (b == null || b.length == 0) {
28 | target.setText("is empty");
29 | } else {
30 | try {
31 | target.setText(Lib.readClassNameFromClass(b));
32 | return true;
33 | } catch (Exception ex) {
34 | target.setText(ex.getMessage());
35 | Logger.getLogger().log(ex);
36 | }
37 | }
38 | }
39 | return false;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/popup/ClassListPopupMenu.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main.popup;
2 |
3 | import org.jrd.backend.data.DependenciesReader;
4 |
5 | import javax.swing.JList;
6 | import javax.swing.ListSelectionModel;
7 | import javax.swing.event.PopupMenuEvent;
8 | import javax.swing.event.PopupMenuListener;
9 | import java.util.Optional;
10 |
11 | public class ClassListPopupMenu extends JListPopupMenu {
12 |
13 | public ClassListPopupMenu(
14 | JList parentJList, int originallySelected, boolean showCheckboxes, DependenciesReader dr, Optional classloader
15 | ) {
16 | super(parentJList, showCheckboxes, dr, classloader);
17 |
18 | addPopupMenuListener(new PopupMenuListener() {
19 | @Override
20 | public void popupMenuWillBecomeVisible(PopupMenuEvent popupMenuEvent) {
21 | }
22 |
23 | @Override
24 | public void popupMenuWillBecomeInvisible(PopupMenuEvent popupMenuEvent) {
25 | parentJList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
26 | parentJList.setSelectedIndex(originallySelected);
27 | parentJList.requestFocusInWindow();
28 | }
29 |
30 | @Override
31 | public void popupMenuCanceled(PopupMenuEvent popupMenuEvent) {
32 | // ...Canceled is called only when it gets dismissed, whereas ...WillBecomeInvisible is called everytime the menu disappears
33 | }
34 | });
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/data/cli/workers/ListJvms.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data.cli.workers;
2 |
3 | import org.jrd.backend.data.VmInfo;
4 | import org.jrd.backend.data.VmManager;
5 | import org.jrd.backend.data.cli.utils.Saving;
6 |
7 | import java.io.IOException;
8 | import java.io.PrintStream;
9 | import java.util.List;
10 |
11 | import static org.jrd.backend.data.cli.CliSwitches.LIST_JVMS;
12 |
13 | public class ListJvms {
14 |
15 | private final List filteredArgs;
16 | private final Saving saving;
17 | private final VmManager vmManager;
18 |
19 | public ListJvms(List filteredArgs, Saving saving, VmManager vmManager) {
20 | this.filteredArgs = filteredArgs;
21 | this.saving = saving;
22 | this.vmManager = vmManager;
23 | }
24 |
25 | public void listJvms() throws IOException {
26 | if (filteredArgs.size() != 1) {
27 | throw new RuntimeException(LIST_JVMS + " does not expect arguments.");
28 | }
29 |
30 | PrintStream out = System.out;
31 | try {
32 | if (saving != null && saving.getAs() != null) {
33 | out = saving.openPrintStream();
34 | }
35 |
36 | for (VmInfo vmInfo : vmManager.getVmInfoSet()) {
37 | out.println(vmInfo.getVmPid() + " " + vmInfo.getVmName());
38 | }
39 |
40 | out.flush();
41 | } finally {
42 | if (saving != null && saving.getAs() != null) {
43 | out.close();
44 | }
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/data/DependenciesReader.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data;
2 |
3 | import org.jrd.frontend.frame.main.LoadingDialogProvider;
4 | import org.jrd.frontend.frame.main.ModelProvider;
5 |
6 | import java.util.Base64;
7 | import java.util.Collection;
8 |
9 | import io.github.mkoncek.classpathless.api.ClassIdentifier;
10 | import io.github.mkoncek.classpathless.api.ClassesProvider;
11 | import io.github.mkoncek.classpathless.api.IdentifiedBytecode;
12 |
13 | public class DependenciesReader {
14 |
15 | private final ModelProvider provider;
16 | private final LoadingDialogProvider gui;
17 |
18 | public DependenciesReader(ModelProvider model, LoadingDialogProvider gui) {
19 | this.provider = model;
20 | this.gui = gui;
21 | }
22 |
23 | public Collection resolve(String clazz, String base64body) {
24 | byte[] bbytes = Base64.getDecoder().decode(base64body);
25 | Collection deps = io.github.mkoncek.classpathless.util.BytecodeExtractor
26 | .extractDependencies(new IdentifiedBytecode(new ClassIdentifier(clazz), bbytes), getClassesProvider());
27 | return deps;
28 | }
29 |
30 | public VmInfo getVmInfo() {
31 | return provider.getVmInfo();
32 | }
33 |
34 | public VmManager getVmManager() {
35 | return provider.getVmManager();
36 | }
37 |
38 | public ClassesProvider getClassesProvider() {
39 | return provider.getClassesProvider();
40 | }
41 |
42 | public LoadingDialogProvider getGui() {
43 | return gui;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/data/cli/workers/Shared.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data.cli.workers;
2 |
3 | import org.jrd.backend.data.cli.utils.Saving;
4 | import org.jrd.frontend.frame.main.decompilerview.HexWithControls;
5 | import org.jrd.frontend.utility.CommonUtils;
6 |
7 | import java.io.IOException;
8 | import java.nio.charset.StandardCharsets;
9 | import java.util.stream.Collectors;
10 |
11 | public class Shared {
12 |
13 | private final Saving saving;
14 | private final boolean isHex;
15 |
16 | public Shared(boolean isHex, Saving saving) {
17 | this.isHex = isHex;
18 | this.saving = saving;
19 | }
20 |
21 | public boolean outOrSave(String name, String extension, String s) throws IOException {
22 | return outOrSave(name, extension, s.getBytes(StandardCharsets.UTF_8), false);
23 | }
24 |
25 | public boolean outOrSave(String name, String extension, byte[] body, boolean forceBytes) throws IOException {
26 | if (saving.shouldSave()) {
27 | return CommonUtils.saveByGui(saving.getAs(), saving.toInt(extension), extension, saving, name, body);
28 | } else {
29 | if (forceBytes) {
30 | if (isHex) {
31 | System.out.println(HexWithControls.bytesToStrings(body).stream().collect(Collectors.joining("\n")));
32 | } else {
33 | System.out.write(body);
34 | }
35 | } else {
36 | System.out.println(new String(body, StandardCharsets.UTF_8));
37 | }
38 | return true;
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/communication/DelegatingJrdAgent.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.communication;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public interface DelegatingJrdAgent extends JrdAgent {
7 |
8 | enum CommandDelegationOptions {
9 | FIRST_OK /*eg getBytecode*/,
10 | ALL /*eg init, and most likely also get classes, but that needs set form all without duplications*/,
11 | MAIN_ONLY /*eg overwrite */
12 | }
13 |
14 | String submitRequest(String request);
15 |
16 | JrdAgent addDelegatingAgent(JrdAgent agent);
17 |
18 | JrdAgent removeDelegatingAgent(JrdAgent agent);
19 |
20 | int cleanDelegatingAgents();
21 |
22 | class DelegatingHelper {
23 | private final List delegationCandidates = new ArrayList<>(1);
24 |
25 | public JrdAgent addDelegatingAgent(JrdAgent agent) {
26 | if (!delegationCandidates.contains(agent)) {
27 | delegationCandidates.add(agent);
28 | return agent;
29 | } else {
30 | return null;
31 | }
32 | }
33 |
34 | public JrdAgent removeDelegatingAgent(JrdAgent agent) {
35 | if (delegationCandidates.contains(agent)) {
36 | delegationCandidates.remove(agent);
37 | return agent;
38 | } else {
39 | return null;
40 | }
41 | }
42 |
43 | public int cleanDelegatingAgents() {
44 | int r = delegationCandidates.size();
45 | delegationCandidates.clear();
46 | return r;
47 | }
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/decompilerview/dummycompiler/templates/BytemanSkeletonTemplateMenuItem.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main.decompilerview.dummycompiler.templates;
2 |
3 | import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
4 |
5 | import java.awt.event.ActionEvent;
6 | import java.awt.event.ActionListener;
7 |
8 | import javax.swing.JMenuItem;
9 |
10 | public class BytemanSkeletonTemplateMenuItem extends JMenuItem {
11 |
12 | private static final String DYNAMIC_SKELETON =
13 | "\n" + "# Warning! If you change name of the rule, the automatic unloads/updates/deletes may stop to work.\n" +
14 | "# use final name before first submit to remote vm\n" + "\n" + "# rule skeleton\n" + "RULE \n" +
15 | " CLASS \n" + " METHOD \n" + " BIND \n" + " IF \n" +
16 | " DO \n" + " ENDRULE";
17 |
18 | public BytemanSkeletonTemplateMenuItem(final RSyntaxTextArea source) {
19 | super("byteman skeleton");
20 | this.addActionListener(new ActionListener() {
21 | @Override
22 | public void actionPerformed(ActionEvent actionEvent) {
23 | source.append(getDynamicSkeleton(null));
24 | }
25 | });
26 | }
27 |
28 | public static String getDynamicSkeleton(String clazz) {
29 | if (clazz == null) {
30 | return DYNAMIC_SKELETON;
31 | } else {
32 | return DYNAMIC_SKELETON.replace("", clazz).replace("", clazz + ".unique.rule.name");
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/core/agentstore/AgentLiveliness.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.core.agentstore;
2 |
3 | import java.util.Arrays;
4 |
5 | public enum AgentLiveliness {
6 | ONE_SHOT,
7 | SESSION,
8 | PERMANENT;
9 |
10 | @Override
11 | public String toString() {
12 | return super.toString();
13 | }
14 |
15 | public String toHelp() {
16 | switch (this) {
17 | case ONE_SHOT:
18 | return "Agent will connect, do its job and disconnect.";
19 | case SESSION:
20 | return "Agent will connect and will remain connected untill end of session.";
21 | case PERMANENT:
22 | return "Agent will attach, and will disconnect only manually or on death of target process";
23 | default:
24 | throw new RuntimeException("Unknown " + AgentLiveliness.class.getSimpleName() + " value " + this);
25 | }
26 | }
27 |
28 | public String toButton() {
29 | switch (this) {
30 | case ONE_SHOT:
31 | return "1";
32 | case SESSION:
33 | return "S";
34 | case PERMANENT:
35 | return "P";
36 | default:
37 | throw new RuntimeException("Unknown " + AgentLiveliness.class.getSimpleName() + " value " + this);
38 | }
39 | }
40 |
41 | public static AgentLiveliness fromString(String s) throws IllegalArgumentException {
42 | return Arrays.stream(AgentLiveliness.values()).filter(v -> v.toString().equals(s)).findFirst()
43 | .orElseThrow(() -> new IllegalArgumentException("unknown value: " + s));
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/decompilerview/verifiers/JarVerifier.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main.decompilerview.verifiers;
2 |
3 | import org.jrd.backend.core.Logger;
4 |
5 | import javax.swing.event.DocumentEvent;
6 | import java.io.File;
7 | import java.util.Enumeration;
8 | import java.util.jar.JarFile;
9 | import java.util.zip.ZipEntry;
10 |
11 | public class JarVerifier extends FileVerifier {
12 |
13 | public JarVerifier(GetSetText source, GetSetText target) {
14 | super(source, target);
15 | }
16 |
17 | public boolean verifySource(DocumentEvent documentEvent) {
18 | boolean intermezo = super.verifySource(documentEvent);
19 | if (intermezo) {
20 | File f = new File(source.getText());
21 | try {
22 | JarFile jf = new JarFile(f);
23 | int manfest = 0;
24 | int others = 0;
25 | for (Enumeration list = jf.entries(); list.hasMoreElements();) {
26 | ZipEntry entry = (ZipEntry) list.nextElement();
27 | if (entry.getName().contains("META-INF")) {
28 | manfest++;
29 | } else {
30 | others++;
31 | }
32 | }
33 | target.setText("contains " + others + " classes and " + manfest + " manifest items");
34 | jf.close();
35 | return true;
36 | } catch (Exception ex) {
37 | target.setText(ex.getMessage());
38 | Logger.getLogger().log(ex);
39 | return false;
40 | }
41 | } else {
42 | return false;
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/fife/ui/hex/event/HexSearchActionListener.java:
--------------------------------------------------------------------------------
1 | package org.fife.ui.hex.event;
2 |
3 | import org.fife.ui.hex.swing.HexSearch;
4 | import org.jrd.backend.core.Logger;
5 |
6 | import javax.swing.JComboBox;
7 | import javax.swing.JTextField;
8 | import java.awt.event.ActionEvent;
9 | import java.awt.event.ActionListener;
10 |
11 | public class HexSearchActionListener implements ActionListener {
12 |
13 | private final HexSearch hexSearchEngine;
14 | private final JTextField hexSearch;
15 | private final JComboBox hexSearchType;
16 | private final Method method;
17 |
18 | public enum Method {
19 | NEXT,
20 | PREV
21 | }
22 |
23 | public HexSearchActionListener(
24 | HexSearch hexSearchEngine, JTextField hexSearch, JComboBox hexSearchType, Method method
25 | ) {
26 | this.hexSearchEngine = hexSearchEngine;
27 | this.hexSearch = hexSearch;
28 | this.hexSearchType = hexSearchType;
29 | this.method = method;
30 | }
31 |
32 | @Override
33 | public void actionPerformed(ActionEvent actionEvent) {
34 | try {
35 | switch (method) {
36 | case NEXT:
37 | hexSearchEngine.next(hexSearch.getText(), (HexSearch.HexSearchOptions) hexSearchType.getSelectedItem());
38 | break;
39 | case PREV:
40 | hexSearchEngine.previous(hexSearch.getText(), (HexSearch.HexSearchOptions) hexSearchType.getSelectedItem());
41 | break;
42 | default:
43 | break;
44 | }
45 | } catch (Exception e) {
46 | Logger.getLogger().log(e);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/bumpVersion.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | ## resolve folder of this script, following all symlinks,
4 | ## http://stackoverflow.com/questions/59895/can-a-bash-script-tell-what-directory-its-stored-in
5 | SCRIPT_SOURCE="${BASH_SOURCE[0]}"
6 | while [ -h "$SCRIPT_SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
7 | SCRIPT_DIR="$( cd -P "$( dirname "$SCRIPT_SOURCE" )" && pwd )"
8 | SCRIPT_SOURCE="$(readlink "$SCRIPT_SOURCE")"
9 | # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
10 | [[ $SCRIPT_SOURCE != /* ]] && SCRIPT_SOURCE="$SCRIPT_DIR/$SCRIPT_SOURCE"
11 | done
12 | readonly SCRIPT_DIR="$( cd -P "$( dirname "$SCRIPT_SOURCE" )" && pwd )"
13 |
14 | set -e
15 |
16 | current=`head ${SCRIPT_DIR}/pom.xml -n 20 | grep "" | sed "s;./\?version.;;g" | sed "s/\s\+//g"`
17 | echo "current version: $current"
18 | echo -n "type future one: "
19 | read future
20 | echo $current "->" $future
21 | echo "ok? y/n"
22 | read yn
23 | if [ ! $yn == y ] ; then
24 | echo aborted
25 | exit 0
26 | fi
27 | poms=`find ${SCRIPT_DIR}| grep "/pom.xml"`
28 | for pom in $poms ; do
29 | echo " * $pom * "
30 | cat $pom | grep --color "$current" -A 1 -B 3
31 | done
32 |
33 | echo "ok? y/n"
34 | read yn
35 | if [ ! $yn == y ] ; then
36 | echo aborted
37 | exit 0
38 | fi
39 |
40 | poms=`find ${SCRIPT_DIR}| grep "/pom.xml"`
41 | for pom in $poms ; do
42 | echo " * $pom * "
43 | sed -i "s;$current;$future;g" ${pom}
44 | cat $pom | grep --color "$future" -A 1 -B 3
45 | done
46 |
47 | echo "ok? y/n"
48 | read yn
49 | if [ ! $yn == y ] ; then
50 | echo "run 'git reset --hard' in ${SCRIPT_DIR}"
51 | exit 0
52 | fi
53 | pushd ${SCRIPT_DIR}
54 | git diff
55 | popd
56 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/decompilerview/InitAddClassJar.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main.decompilerview;
2 |
3 | import org.jrd.backend.core.Logger;
4 |
5 | import javax.swing.JOptionPane;
6 | import java.awt.event.ActionEvent;
7 | import java.awt.event.ActionListener;
8 | import java.util.Arrays;
9 |
10 | class InitAddClassJar implements ActionListener {
11 | private final BytecodeDecompilerView bytecodeDecompilerView;
12 |
13 | InitAddClassJar(BytecodeDecompilerView bytecodeDecompilerView) {
14 | this.bytecodeDecompilerView = bytecodeDecompilerView;
15 | }
16 |
17 | @Override
18 | public void actionPerformed(ActionEvent actionEvent) {
19 | try {
20 | String[] fqn = new InitAddClassDialog(
21 | bytecodeDecompilerView.getLastFqn(), bytecodeDecompilerView.getLastAddedFqn(), bytecodeDecompilerView.getLastAddedFile()
22 | ).showAndGet();
23 |
24 | if (fqn != null && fqn.length > 0) {
25 | if (fqn.length == 1) {
26 | bytecodeDecompilerView.initGui(fqn[0]);
27 | } else if (fqn.length == 2) {
28 | bytecodeDecompilerView.addClassGui(fqn[0], fqn[1]);
29 | } else if (fqn.length == 3) {
30 | bytecodeDecompilerView.addJar(Boolean.parseBoolean(fqn[0]), fqn[2], fqn[1]);
31 | } else {
32 | bytecodeDecompilerView.addClassesGui(Boolean.parseBoolean(fqn[0]), Arrays.copyOfRange(fqn, 4, fqn.length));
33 | }
34 | }
35 | } catch (Exception ex) {
36 | Logger.getLogger().log(Logger.Level.ALL, ex);
37 | JOptionPane.showMessageDialog(bytecodeDecompilerView.getBuffers(), ex.getMessage());
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/decompilerview/dummycompiler/ClassesAndMethodsProviderBasedClassesProvider.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main.decompilerview.dummycompiler;
2 |
3 | import io.github.mkoncek.classpathless.api.ClassIdentifier;
4 | import io.github.mkoncek.classpathless.api.ClassesProvider;
5 | import io.github.mkoncek.classpathless.api.IdentifiedBytecode;
6 | import org.jrd.backend.completion.ClassesAndMethodsProvider;
7 | import org.jrd.backend.core.Logger;
8 |
9 | import java.util.ArrayList;
10 | import java.util.Arrays;
11 | import java.util.Collection;
12 | import java.util.List;
13 | import java.util.stream.Collectors;
14 |
15 | public class ClassesAndMethodsProviderBasedClassesProvider implements ClassesProvider {
16 | private final ClassesAndMethodsProvider classesAndMethodsProvider;
17 |
18 | public ClassesAndMethodsProviderBasedClassesProvider(ClassesAndMethodsProvider classesAndMethodsProvider) {
19 | this.classesAndMethodsProvider = classesAndMethodsProvider;
20 | }
21 |
22 | @Override
23 | public Collection getClass(ClassIdentifier... classIdentifiers) {
24 | List result = new ArrayList<>(classIdentifiers.length);
25 | for (ClassIdentifier ci : classIdentifiers) {
26 | try {
27 | byte[] b = classesAndMethodsProvider.getClassItself(null, classIdentifiers[0].getFullName());
28 | result.add(new IdentifiedBytecode(ci, b));
29 | } catch (Exception ex) {
30 | Logger.getLogger().log(ex);
31 | }
32 | }
33 | return result;
34 | }
35 |
36 | @Override
37 | public List getClassPathListing() {
38 | return Arrays.stream(classesAndMethodsProvider.getClasses(null)).collect(Collectors.toList());
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/data/cli/workers/ListPlugins.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data.cli.workers;
2 |
3 | import org.jrd.backend.data.cli.CliUtils;
4 | import org.jrd.backend.data.cli.utils.Saving;
5 | import org.jrd.backend.decompiling.DecompilerWrapper;
6 | import org.jrd.backend.decompiling.PluginManager;
7 |
8 | import java.io.IOException;
9 | import java.io.PrintStream;
10 | import java.util.List;
11 |
12 | import static org.jrd.backend.data.cli.CliSwitches.LIST_PLUGINS;
13 |
14 | public class ListPlugins {
15 |
16 | private final List filteredArgs;
17 | private final Saving saving;
18 | private final PluginManager pluginManager;
19 |
20 | public ListPlugins(List filteredArgs, Saving saving, PluginManager pluginManager) {
21 | this.filteredArgs = filteredArgs;
22 | this.saving = saving;
23 | this.pluginManager = pluginManager;
24 | }
25 |
26 | public void listPlugins() throws IOException {
27 | if (filteredArgs.size() != 1) {
28 | throw new RuntimeException(LIST_PLUGINS + " does not expect arguments.");
29 | }
30 |
31 | PrintStream out = System.out;
32 | try {
33 | if (saving != null && saving.getAs() != null) {
34 | out = saving.openPrintStream();
35 | }
36 |
37 | for (DecompilerWrapper dw : pluginManager.getWrappers()) {
38 | out.printf(
39 | "%s %s/%s - %s%n", dw.getName(), dw.getScope(), CliUtils.invalidityToString(dw.isInvalidWrapper()),
40 | dw.getFileLocation()
41 | );
42 | }
43 |
44 | out.flush();
45 | } finally {
46 | if (saving != null && saving.getAs() != null) {
47 | out.close();
48 | }
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/data/cli/workers/Api.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data.cli.workers;
2 |
3 | import org.jrd.backend.data.VmInfo;
4 | import org.jrd.backend.data.VmManager;
5 | import org.jrd.backend.data.cli.CliUtils;
6 | import org.jrd.backend.data.cli.Help;
7 | import org.jrd.backend.data.cli.utils.Saving;
8 | import org.jrd.backend.decompiling.PluginManager;
9 | import org.jrd.frontend.utility.AgentApiGenerator;
10 |
11 | import java.io.PrintStream;
12 | import java.util.List;
13 |
14 | public class Api {
15 |
16 | private final List filteredArgs;
17 | private final Saving saving;
18 | private final VmManager vmManager;
19 | private final PluginManager pluginManager;
20 |
21 | public Api(List filteredArgs, Saving saving, VmManager vmManager, PluginManager pluginManager) {
22 | this.filteredArgs = filteredArgs;
23 | this.saving = saving;
24 | this.vmManager = vmManager;
25 | this.pluginManager = pluginManager;
26 | }
27 |
28 | public VmInfo api() throws Exception {
29 | PrintStream out = System.out;
30 | try {
31 | if (saving != null && saving.getAs() != null) {
32 | out = saving.openPrintStream();
33 | }
34 |
35 | if (filteredArgs.size() != 2) {
36 | throw new IllegalArgumentException("Incorrect argument count! Please use '" + Help.API_FORMAT + "'.");
37 | }
38 |
39 | VmInfo vmInfo = CliUtils.getVmInfo(filteredArgs.get(1), vmManager);
40 | AgentApiGenerator.initItems(vmInfo, vmManager, pluginManager);
41 | out.println(AgentApiGenerator.getInterestingHelp());
42 | out.flush();
43 | return vmInfo;
44 | } finally {
45 | if (saving != null && saving.getAs() != null) {
46 | out.close();
47 | }
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/data/cli/workers/Overrides.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data.cli.workers;
2 |
3 | import org.jrd.backend.data.VmInfo;
4 | import org.jrd.backend.data.VmManager;
5 | import org.jrd.backend.data.cli.CliUtils;
6 | import org.jrd.backend.data.cli.Help;
7 | import org.jrd.backend.data.cli.Lib;
8 |
9 | import java.util.List;
10 |
11 | public class Overrides {
12 |
13 | private final List filteredArgs;
14 | private final VmManager vmManager;
15 |
16 | public Overrides(List filteredArgs, VmManager vmManager) {
17 | this.filteredArgs = filteredArgs;
18 | this.vmManager = vmManager;
19 | }
20 |
21 | public VmInfo removeOverrides() {
22 | if (filteredArgs.size() != 3) {
23 | throw new RuntimeException("expected two params: " + Help.REMOVE_OVERRIDES_FORMAT);
24 | }
25 | VmInfo vmInfo = CliUtils.getVmInfo(filteredArgs.get(1), vmManager);
26 | String regex = filteredArgs.get(2);
27 | String[] was = Lib.obtainOverrides(vmInfo, vmManager);
28 | Lib.removeOverrides(vmInfo, vmManager, regex);
29 | String[] is = Lib.obtainOverrides(vmInfo, vmManager);
30 | System.out.println("Removed: " + (was.length - is.length) + " (was: " + was.length + ", is: " + is.length + ")");
31 | return vmInfo;
32 | }
33 |
34 | public VmInfo listOverrides() {
35 | if (filteredArgs.size() != 2) {
36 | throw new RuntimeException("expected two params: " + Help.LIST_OVERRIDES_FORMAT);
37 | }
38 | VmInfo vmInfo = CliUtils.getVmInfo(filteredArgs.get(1), vmManager);
39 | String[] overrides = Lib.obtainOverrides(vmInfo, vmManager);
40 | for (String override : overrides) {
41 | System.out.println(override);
42 | }
43 | System.out.println("Total: " + overrides.length);
44 | return vmInfo;
45 |
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/test/resources/org/jrd/frontend/frame/main/popup/testPatch2:
--------------------------------------------------------------------------------
1 | diff --git a/jenkins/job_dsl/tests/Constants.groovy b/jenkins/job_dsl/tests/Constants.groovy
2 | index e7e1dffc70b26720c8dba133c49fa921bedd8e8b..25312af810b0298c855a760e3741b8824af6a1eb 100644
3 | --- a/jenkins/job_dsl/tests/Constants.groovy
4 | +++ b/jenkins/job_dsl/tests/Constants.groovy
5 | @@ -2,21 +2,21 @@ class Constants {
6 |
7 | static final ArrayList QUARKUS_VERSION_LATEST =
8 | [
9 | - '2.13.0.Final',
10 | + '2.13.2.Final',
11 | 'main'
12 | ]
13 |
14 | static final ArrayList QUARKUS_VERSION_RELEASED =
15 | [
16 | '2.7.6.Final',
17 | - '2.13.0.Final'
18 | + '2.13.2.Final'
19 | ]
20 |
21 | static final ArrayList QUARKUS_VERSION_ALL =
22 | [
23 | '2.7.6.Final',
24 | '2.12.2.Final',
25 | - '2.13.0.Final'
26 | + '2.13.2.Final'
27 | ]
28 |
29 | static final String QUARKUS_MODULES_AWT_TESTS = '' +
30 | diff --git a/jenkins/job_dsl/tests/mandrel_linux_amd64_perfcheck_tests.groovy b/jenkins/job_dsl/tests/mandrel_linux_amd64_perfcheck_tests.groovy
31 | index 036e583d02a27d2d30de691b959113cfa5ffd650..f7b21022a74354a14ddfe5ca18c5e2fd5ffefe56 100644
32 | --- a/jenkins/job_dsl/tests/mandrel_linux_amd64_perfcheck_tests.groovy
33 | +++ b/jenkins/job_dsl/tests/mandrel_linux_amd64_perfcheck_tests.groovy
34 | @@ -7,7 +7,7 @@ matrixJob('mandrel-linux-amd64-perfcheck-tests') {
35 | '22.0.0.2-Final'
36 | )
37 | text('QUARKUS_VERSION',
38 | - '2.13.0.Final',
39 | + '2.13.2.Final',
40 | '2.8.3.Final',
41 | '2.8.2.Final',
42 | '2.7.1.Final'
43 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/data/ArchiveManagerOptions.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Collections;
5 | import java.util.List;
6 |
7 | public class ArchiveManagerOptions {
8 |
9 | private static final class ArchiveManagerOptionsHolder {
10 | private static final ArchiveManagerOptions INSTANCE = new ArchiveManagerOptions();
11 | }
12 |
13 | public static ArchiveManagerOptions getInstance() {
14 | ArchiveManagerOptionsHolder.INSTANCE.setExtensions(Config.getConfig().getNestedJarExtensions());
15 | return ArchiveManagerOptionsHolder.INSTANCE;
16 | }
17 |
18 | private List extensions = new ArrayList<>();
19 | public static final List DEFAULTS = List.of(".zip", ".jar", ".war", ".ear");
20 |
21 | public void setExtensions(List s) {
22 | extensions = Collections.unmodifiableList(s);
23 | }
24 |
25 | public List getExtensions() {
26 | return Collections.unmodifiableList(extensions);
27 | }
28 |
29 | public static String getExtensionString(String delimiter) {
30 | return String.join(delimiter, DEFAULTS);
31 | }
32 |
33 | public boolean isInner(String n) {
34 | String name = n.toLowerCase();
35 |
36 | if (areExtensionsEmpty()) {
37 | return oneEnds(DEFAULTS, name);
38 | } else {
39 | return oneEnds(extensions, name);
40 | }
41 | }
42 |
43 | public boolean areExtensionsEmpty() {
44 | return extensions == null || extensions.isEmpty() || extensions.size() == 1 && extensions.get(0).trim().isEmpty();
45 | }
46 |
47 | private boolean oneEnds(List suffixes, String name) {
48 | for (String suffix : suffixes) {
49 | if (name.endsWith(suffix.toLowerCase())) {
50 | return true;
51 | }
52 | }
53 |
54 | return false;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/decompilerview/dummycompiler/templates/JasmTemplateMenuItem.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main.decompilerview.dummycompiler.templates;
2 |
3 | import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
4 |
5 | import java.awt.event.ActionEvent;
6 | import java.awt.event.ActionListener;
7 |
8 | import javax.swing.JMenuItem;
9 |
10 | public class JasmTemplateMenuItem extends JMenuItem {
11 | public JasmTemplateMenuItem(final RSyntaxTextArea source) {
12 | super("jasm hello world");
13 | this.addActionListener(new ActionListener() {
14 | @Override
15 | public void actionPerformed(ActionEvent actionEvent) {
16 | source.append(
17 | "\npackage jrd/template;\n" + "\n" + "super public class HelloJasm\n" + "\tversion 52:0\n" + "{\n" +
18 | " public Method \"\":\"()V\"\n" + "\tstack 1 locals 1\n" + " {\n" + "\t\taload_0;\n" +
19 | "\t\tinvokespecial\tMethod java/lang/Object.\"\":\"()V\";\n" + "\t\treturn;\n" + " }\n" +
20 | " public static Method start:\"()V\"\n" + "\tstack 2 locals 0\n" + " {\n" +
21 | "\t\tgetstatic\tField java/lang/System.out:\"Ljava/io/PrintStream;\";\n" +
22 | "\t\tldc\tString \"hello on stdout. See terminal!\";\n" +
23 | "\t\tinvokevirtual\tMethod java/io/PrintStream.println:\"(Ljava/lang/String;)V\";\n" + "\t\treturn;\n" +
24 | " }\n" + " public static Method main:\"([Ljava/lang/String;)V\"\n" + "\tstack 0 locals 1\n" + " {\n" +
25 | "\t\tinvokestatic\tMethod start:\"()V\";\n" + "\t\treturn;\n" + " }\n" + "\n" +
26 | "} // end Class HelloJasm\n"
27 | );
28 | }
29 | });
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/LoadingDialog.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main;
2 |
3 | import javax.swing.JButton;
4 | import javax.swing.JDialog;
5 | import javax.swing.JLabel;
6 | import javax.swing.JProgressBar;
7 | import javax.swing.SwingConstants;
8 | import java.awt.BorderLayout;
9 | import java.awt.Dimension;
10 | import java.awt.event.ActionEvent;
11 | import java.awt.event.ActionListener;
12 | import java.awt.event.WindowAdapter;
13 | import java.awt.event.WindowEvent;
14 |
15 | public class LoadingDialog extends JDialog {
16 |
17 | private JProgressBar progressBar = new JProgressBar();
18 | private JButton abortButton = new JButton("Abort");
19 |
20 | private ActionListener abortActionListener;
21 |
22 | public LoadingDialog(String title) {
23 | this.setTitle("Connecting");
24 | this.setSize(new Dimension(256, 144));
25 | this.setResizable(false);
26 | this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
27 | this.setModalityType(ModalityType.APPLICATION_MODAL);
28 | this.setLayout(new BorderLayout());
29 | this.setLocationRelativeTo(null);
30 |
31 | JLabel infoLabel = new JLabel(title);
32 | infoLabel.setHorizontalAlignment(SwingConstants.CENTER);
33 | this.add(infoLabel, BorderLayout.NORTH);
34 | this.add(progressBar, BorderLayout.CENTER);
35 | progressBar.setIndeterminate(true);
36 | this.add(abortButton, BorderLayout.SOUTH);
37 |
38 | this.addWindowListener(new WindowAdapter() {
39 | @Override
40 | public void windowClosing(WindowEvent e) {
41 | abort();
42 | }
43 | });
44 |
45 | abortButton.addActionListener(event -> abort());
46 | }
47 |
48 | private void abort() {
49 | ActionEvent abortEvent = new ActionEvent(this, 0, null);
50 | abortActionListener.actionPerformed(abortEvent);
51 | }
52 |
53 | public void setAbortActionListener(ActionListener listener) {
54 | abortActionListener = listener;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/test/java/org/jrd/frontend/utility/AgentApiGeneratorTest.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.utility;
2 |
3 | import org.junit.jupiter.api.Assertions;
4 | import org.junit.jupiter.api.Test;
5 |
6 | class AgentApiGeneratorTest {
7 |
8 | @Test
9 | void containsAllInOrderEmptyes() {
10 | Assertions.assertTrue(AgentApiGenerator.containsAllInOrder(null, "blah"));
11 | Assertions.assertTrue(AgentApiGenerator.containsAllInOrder("", "blah"));
12 | Assertions.assertTrue(AgentApiGenerator.containsAllInOrder(" ", "blah"));
13 | Assertions.assertFalse(AgentApiGenerator.containsAllInOrder("blah", null));
14 | Assertions.assertFalse(AgentApiGenerator.containsAllInOrder("blah", ""));
15 | Assertions.assertFalse(AgentApiGenerator.containsAllInOrder("blah", " "));
16 | }
17 |
18 | @Test
19 | void containsAllInOrder() {
20 | Assertions.assertTrue(AgentApiGenerator.containsAllInOrder("abc", "xxxayyyyaaadddbbbuuuceee"));
21 | Assertions.assertTrue(AgentApiGenerator.containsAllInOrder("abbc", "xxxayyyyaaadddbbbuuuceee"));
22 | Assertions.assertFalse(AgentApiGenerator.containsAllInOrder("abbc", "xxxayyyyaaadddbuuuceee"));
23 | Assertions.assertTrue(AgentApiGenerator.containsAllInOrder("blah", "blah"));
24 | Assertions.assertTrue(AgentApiGenerator.containsAllInOrder("bh", "blah "));
25 | Assertions.assertTrue(AgentApiGenerator.containsAllInOrder(" l ", "blah"));
26 | Assertions.assertFalse(AgentApiGenerator.containsAllInOrder("hlab", "blah"));
27 | Assertions.assertFalse(AgentApiGenerator.containsAllInOrder("x", "blah"));
28 | Assertions.assertFalse(AgentApiGenerator.containsAllInOrder("bha", "blah"));
29 | Assertions.assertFalse(AgentApiGenerator.containsAllInOrder("ab", "blah"));
30 | }
31 |
32 | @Test
33 | void containsAllInOrderSplit() {
34 | Assertions.assertTrue(AgentApiGenerator.containsAllInOrder("ab", "xxxayy.yyb"));
35 | Assertions.assertFalse(AgentApiGenerator.containsAllInOrder("ab", "xxxayy..yyb"));
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/fife/ui/hex/swing/ByteArrayTransferable.java:
--------------------------------------------------------------------------------
1 | //
2 | // Decompiled by Procyon v0.5.36
3 | //
4 |
5 | package org.fife.ui.hex.swing;
6 |
7 | import java.awt.datatransfer.DataFlavor;
8 | import java.awt.datatransfer.Transferable;
9 | import java.awt.datatransfer.UnsupportedFlavorException;
10 | import java.io.IOException;
11 | import java.io.StringReader;
12 | import java.nio.charset.StandardCharsets;
13 |
14 | public class ByteArrayTransferable implements Transferable {
15 | private static final DataFlavor[] FLAVORS;
16 |
17 | static {
18 | FLAVORS = new DataFlavor[]{DataFlavor.stringFlavor, DataFlavor.plainTextFlavor};
19 | }
20 |
21 | private int offset;
22 | private byte[] bytes;
23 |
24 | public ByteArrayTransferable(final int offset, final byte[] bytes) {
25 | this.offset = offset;
26 | if (bytes != null) {
27 | this.bytes = bytes.clone();
28 | } else {
29 | this.bytes = new byte[0];
30 | }
31 | }
32 |
33 | public int getLength() {
34 | return this.bytes.length;
35 | }
36 |
37 | public int getOffset() {
38 | return this.offset;
39 | }
40 |
41 | public Object getTransferData(final DataFlavor flavor) throws UnsupportedFlavorException, IOException {
42 | if (flavor.equals(ByteArrayTransferable.FLAVORS[0])) {
43 | return new String(this.bytes, StandardCharsets.UTF_8);
44 | }
45 | if (flavor.equals(ByteArrayTransferable.FLAVORS[1])) {
46 | return new StringReader(new String(this.bytes, StandardCharsets.UTF_8));
47 | }
48 | throw new UnsupportedFlavorException(flavor);
49 | }
50 |
51 | public DataFlavor[] getTransferDataFlavors() {
52 | return ByteArrayTransferable.FLAVORS.clone();
53 | }
54 |
55 | public boolean isDataFlavorSupported(final DataFlavor flavor) {
56 | for (int i = 0; i < ByteArrayTransferable.FLAVORS.length; ++i) {
57 | if (flavor.equals(ByteArrayTransferable.FLAVORS[i])) {
58 | return true;
59 | }
60 | }
61 | return false;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/remote/NewConnectionController.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.remote;
2 |
3 | import org.jrd.backend.core.Logger;
4 | import org.jrd.backend.data.VmManager;
5 |
6 | import javax.swing.JOptionPane;
7 |
8 | public class NewConnectionController {
9 |
10 | NewConnectionView newConnectionView;
11 | VmManager vmManager;
12 |
13 | public NewConnectionController(NewConnectionView newConnectionView, VmManager vmManager) {
14 | this.newConnectionView = newConnectionView;
15 | this.vmManager = vmManager;
16 |
17 | newConnectionView.setAddButtonListener(e -> addRemoteVmInfo());
18 | }
19 |
20 | private void addRemoteVmInfo() {
21 | String hostname = newConnectionView.getHostname();
22 | String portString = newConnectionView.getPortString();
23 | boolean shouldBeSaved = newConnectionView.shouldBeSaved();
24 |
25 | if (hostname.isEmpty()) {
26 | JOptionPane.showMessageDialog(newConnectionView, "Hostname is Empty.", " ", JOptionPane.WARNING_MESSAGE);
27 | return;
28 | }
29 | if (isValidPort(portString)) {
30 | int port = Integer.parseInt(portString);
31 | newConnectionView.reSetLastHostname();
32 | newConnectionView.reSetLastPort();
33 | vmManager.createRemoteVM(hostname, port, shouldBeSaved, null);
34 | newConnectionView.dispose();
35 | } else {
36 | JOptionPane.showMessageDialog(newConnectionView, "VM port is invalid.", " ", JOptionPane.WARNING_MESSAGE);
37 | }
38 | }
39 |
40 | /**
41 | * Validates a port.
42 | * @param portString string representation of the port number
43 | * @return true if portString is an integer between 0 and 65535
44 | */
45 | boolean isValidPort(String portString) {
46 | try {
47 | int port = Integer.parseInt(portString);
48 | return port > 0 && port <= 65535;
49 | } catch (NumberFormatException e) {
50 | Logger.getLogger().log(Logger.Level.ALL, e);
51 | return false;
52 | }
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/data/cli/workers/ListAgents.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data.cli.workers;
2 |
3 | import org.jrd.backend.core.agentstore.KnownAgent;
4 | import org.jrd.backend.core.agentstore.KnownAgents;
5 | import org.jrd.backend.data.VmInfo;
6 | import org.jrd.backend.data.VmManager;
7 | import org.jrd.backend.data.cli.CliUtils;
8 | import org.jrd.backend.data.cli.Lib;
9 |
10 | import java.util.ArrayList;
11 | import java.util.List;
12 |
13 | import static org.jrd.backend.data.cli.CliSwitches.VERSIONS;
14 |
15 | public class ListAgents {
16 |
17 | private final VmManager vmManager;
18 | private final boolean verbose;
19 |
20 | public ListAgents(boolean verbose, VmManager vmManager) {
21 | this.verbose = verbose;
22 | this.vmManager = vmManager;
23 | }
24 |
25 | public List listAgents(List params) {
26 | boolean versions = false;
27 | if (params.size() > 1) {
28 | String filteredSecondParam = CliUtils.cleanParameter(params.get(1));
29 | versions = filteredSecondParam.equals(VERSIONS);
30 | }
31 | return listAgents(versions);
32 | }
33 |
34 | private List listAgents(boolean versions) {
35 | List connections = new ArrayList<>();
36 | for (KnownAgent agent : KnownAgents.getInstance().getAgents()) {
37 | System.out.println(agent.toPrint());
38 | if (versions) {
39 | try {
40 | Lib.HandhshakeResult vmInfo = Lib.handshakeAgent(agent, vmManager);
41 | System.out.println(" - " + vmInfo.getAgentVersion());
42 | System.out.println(" - " + vmInfo.getDiff());
43 | connections.add(vmInfo.getVmInfo());
44 | } catch (Exception ex) {
45 | if (verbose) {
46 | ex.printStackTrace();
47 | }
48 | System.out.println(" - unknown version. Most likely old agent. Should work for most cases though.");
49 | }
50 | }
51 | }
52 | return connections;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/core/agentstore/AgentLoneliness.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.core.agentstore;
2 |
3 | import java.util.Arrays;
4 |
5 | public enum AgentLoneliness {
6 | SINGLE_INSTANCE,
7 | ANONYMOUS,
8 | FORCING,
9 | AF;
10 |
11 | @Override
12 | public String toString() {
13 | return super.toString();
14 | }
15 |
16 | public String toHelp() {
17 | switch (this) {
18 | case SINGLE_INSTANCE:
19 | return "Agent be allowed to attach to each process only once, unless " + FORCING + " is put to " +
20 | "following attachment (default)";
21 | case ANONYMOUS:
22 | return "Agent will attach, but will not set the flag about its presence. Still, the property will be " + "set. (weird)";
23 | case FORCING:
24 | return "Agent will attach, but will skip the check for single instance (sometimes useful)";
25 | case AF:
26 | return "Agent will attach, but will skip the check for single instance" +
27 | "and will not set the flag about its presence. Still, the property will be set. (super weird)";
28 | default:
29 | throw new RuntimeException("Unknown " + AgentLoneliness.class.getSimpleName() + " value " + this);
30 | }
31 | }
32 |
33 | public String toButton() {
34 | switch (this) {
35 | case SINGLE_INSTANCE:
36 | return "SI";
37 | case ANONYMOUS:
38 | return "A";
39 | case FORCING:
40 | return "F";
41 | case AF:
42 | return "AF";
43 | default:
44 | throw new RuntimeException("Unknown " + AgentLoneliness.class.getSimpleName() + " value " + this);
45 | }
46 | }
47 |
48 | public static AgentLoneliness fromString(String s) throws IllegalArgumentException {
49 | return Arrays.stream(AgentLoneliness.values()).filter(v -> v.toString().equals(s)).findFirst()
50 | .orElseThrow(() -> new IllegalArgumentException("unknown value: " + s));
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/plugins/PluginTopOptionPanel.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.plugins;
2 |
3 | import javax.swing.Box;
4 | import javax.swing.JButton;
5 | import javax.swing.JPanel;
6 | import java.awt.Dimension;
7 | import java.awt.GridBagConstraints;
8 | import java.awt.GridBagLayout;
9 |
10 | public class PluginTopOptionPanel extends JPanel {
11 |
12 | private final JButton cloneButton;
13 | private final JButton deleteButton;
14 | private final JButton openWebsiteButton;
15 | private final JButton importButton;
16 |
17 | public PluginTopOptionPanel() {
18 | final int height = 28;
19 | final int buttonWidth = 84;
20 | Dimension buttonSize = new Dimension(buttonWidth, height);
21 |
22 | this.setLayout(new GridBagLayout());
23 | this.setPreferredSize(new Dimension(0, height));
24 |
25 | cloneButton = new JButton("Clone");
26 | cloneButton.setPreferredSize(buttonSize);
27 | deleteButton = new JButton("Delete");
28 | deleteButton.setPreferredSize(buttonSize);
29 | openWebsiteButton = new JButton("Website");
30 | openWebsiteButton.setPreferredSize(buttonSize);
31 | importButton = new JButton("Import");
32 | importButton.setPreferredSize(buttonSize);
33 |
34 | GridBagConstraints gbc = new GridBagConstraints();
35 | gbc.weightx = 0;
36 | gbc.gridx = 0;
37 | this.add(cloneButton, gbc);
38 | gbc.gridx = 1;
39 | this.add(deleteButton, gbc);
40 | gbc.gridx = 2;
41 | this.add(openWebsiteButton, gbc);
42 | gbc.gridx = 3;
43 | this.add(importButton, gbc);
44 | gbc.gridx = 4;
45 | gbc.weightx = 1;
46 | this.add(Box.createHorizontalGlue(), gbc);
47 | }
48 |
49 | public JButton getCloneButton() {
50 | return cloneButton;
51 | }
52 |
53 | public JButton getDeleteButton() {
54 | return deleteButton;
55 | }
56 |
57 | public JButton getOpenWebsiteButton() {
58 | return openWebsiteButton;
59 | }
60 |
61 | public JButton getImportButton() {
62 | return importButton;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/decompiler_agent/src/main/java/org/jrd/agent/ClassFilter.java:
--------------------------------------------------------------------------------
1 | package org.jrd.agent;
2 |
3 | import java.nio.charset.StandardCharsets;
4 | import java.util.Optional;
5 | import java.util.regex.Pattern;
6 |
7 | public class ClassFilter {
8 |
9 | private final Pattern nameFilter;
10 | private final String bodySubstring;
11 |
12 | public ClassFilter(Optional nameFilter, Optional bodySubstring) {
13 | this.nameFilter = Pattern.compile(nameFilter.orElseGet(() -> ".*"));
14 | this.bodySubstring = bodySubstring.orElseGet(() -> "");
15 | }
16 |
17 | public static Optional create(String substringAndRegexLine) {
18 | if (substringAndRegexLine == null) {
19 | return Optional.empty();
20 | }
21 | final String[] substringAndRegex = substringAndRegexLine.trim().split("\\s+");
22 | if (substringAndRegex.length == 0) {
23 | return Optional.empty();
24 | }
25 | if (substringAndRegex.length == 1) {
26 | return Optional.of(new ClassFilter(Optional.of(substringAndRegex[0]), Optional.empty()));
27 | }
28 | return Optional
29 | .of(new ClassFilter(Optional.of(substringAndRegex[0]), Optional.of(AgentActionWorker.base64toSring(substringAndRegex[1]))));
30 | }
31 |
32 | public boolean match(InstrumentationProvider instrumentationProvider, Class loadedClass, String classLoader) {
33 | try {
34 | if (nameFilter.matcher(loadedClass.getName()).matches()) {
35 | byte[] b = instrumentationProvider.getClassBody(loadedClass, classLoader);
36 | String ascii = new String(b, StandardCharsets.US_ASCII);
37 | if (ascii.contains(bodySubstring)) {
38 | return true;
39 | } else {
40 | String utf8 = new String(b, StandardCharsets.UTF_8);
41 | if (utf8.contains(bodySubstring)) {
42 | return true;
43 | }
44 | }
45 | }
46 | return false;
47 | } catch (Exception ex) {
48 | return false;
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/decompiling/JavapDisassemblerWrapper.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.decompiling;
2 |
3 | import java.io.File;
4 | import java.io.FileOutputStream;
5 | import java.io.IOException;
6 | import java.io.PrintWriter;
7 | import java.io.StringWriter;
8 | import java.nio.charset.StandardCharsets;
9 | import java.nio.file.Files;
10 | import java.nio.file.Paths;
11 |
12 | public class JavapDisassemblerWrapper {
13 |
14 | private final String otherArgs;
15 |
16 | public JavapDisassemblerWrapper(String otherArgs) {
17 | this.otherArgs = otherArgs;
18 | }
19 |
20 | public String decompile(byte[] bytecode, String[] options) {
21 | try {
22 | File tempByteFile = bytesToFile(bytecode);
23 | File tempOutputFile = File.createTempFile("decompile-output", ".java");
24 | PrintWriter printWriter = new PrintWriter(tempOutputFile, StandardCharsets.UTF_8);
25 | StringBuilder optionsString = new StringBuilder();
26 | if (options != null) {
27 | for (String option : options) {
28 | optionsString.append(option);
29 | }
30 | }
31 |
32 | com.sun.tools.javap.Main.run(new String[]{otherArgs + optionsString, tempByteFile.getAbsolutePath()}, printWriter);
33 |
34 | return readStringFromFile(tempOutputFile.getAbsolutePath());
35 | } catch (Exception e) {
36 | StringWriter errors = new StringWriter();
37 | e.printStackTrace(new PrintWriter(errors));
38 | return "Exception while decompiling" + errors;
39 | }
40 | }
41 |
42 | private File bytesToFile(byte[] bytes) throws IOException {
43 | File tempFile = File.createTempFile("temporary-byte-file", ".class");
44 | tempFile.deleteOnExit();
45 |
46 | try (FileOutputStream fos = new FileOutputStream(tempFile.getCanonicalPath())) {
47 | fos.write(bytes);
48 | }
49 |
50 | return tempFile;
51 | }
52 |
53 | private String readStringFromFile(String filePath) throws IOException {
54 | return Files.readString(Paths.get(filePath));
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/overwrite/LatestPaths.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.overwrite;
2 |
3 | public final class LatestPaths {
4 | private String lastManualUpload;
5 | private String lastSaveSrc;
6 | private String lastSaveBin;
7 | private String filesToCompile;
8 | private String outputExternalFilesDir;
9 | private String outputBinaries;
10 |
11 | public LatestPaths() {
12 | lastManualUpload = System.getProperty("user.home");
13 | lastSaveSrc = System.getProperty("user.home");
14 | lastSaveBin = System.getProperty("user.home");
15 | filesToCompile = System.getProperty("user.home");
16 | outputExternalFilesDir = System.getProperty("user.home");
17 | outputBinaries = System.getProperty("user.home");
18 | }
19 |
20 | public String getLastManualUpload() {
21 | return lastManualUpload;
22 | }
23 |
24 | public void setLastManualUpload(String lastManualUpload) {
25 | this.lastManualUpload = lastManualUpload;
26 | }
27 |
28 | public String getLastSaveSrc() {
29 | return lastSaveSrc;
30 | }
31 |
32 | public void setLastSaveSrc(String lastSaveSrc) {
33 | this.lastSaveSrc = lastSaveSrc;
34 | }
35 |
36 | public String getLastSaveBin() {
37 | return lastSaveBin;
38 | }
39 |
40 | public void setLastSaveBin(String lastSaveBin) {
41 | this.lastSaveBin = lastSaveBin;
42 | }
43 |
44 | public String getFilesToCompile() {
45 | return filesToCompile;
46 | }
47 |
48 | public void setFilesToCompile(String filesToCompile) {
49 | this.filesToCompile = filesToCompile;
50 | }
51 |
52 | public String getOutputExternalFilesDir() {
53 | return outputExternalFilesDir;
54 | }
55 |
56 | public void setOutputExternalFilesDir(String outputExternalFilesDir) {
57 | this.outputExternalFilesDir = outputExternalFilesDir;
58 | }
59 |
60 | public String getOutputBinaries() {
61 | return outputBinaries;
62 | }
63 |
64 | public void setOutputBinaries(String outputBinaries) {
65 | this.outputBinaries = outputBinaries;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/fife/ui/hex/event/HexSearchDocumentListener.java:
--------------------------------------------------------------------------------
1 | package org.fife.ui.hex.event;
2 |
3 | import org.fife.ui.hex.swing.HexSearch;
4 | import org.jrd.backend.core.Logger;
5 |
6 | import javax.swing.JComboBox;
7 | import javax.swing.JTextField;
8 | import javax.swing.event.DocumentEvent;
9 | import javax.swing.event.DocumentListener;
10 | import java.awt.event.ActionListener;
11 |
12 | public class HexSearchDocumentListener implements DocumentListener {
13 |
14 | private final HexSearch hexSearchEngine;
15 | private final JTextField hexSearch;
16 | private final JComboBox hexSearchType;
17 | private ActionListener wasNotFoundListener;
18 |
19 | public HexSearchDocumentListener(HexSearch hexSearchEngine, JTextField hexSearch, JComboBox hexSearchType) {
20 | this.hexSearchEngine = hexSearchEngine;
21 | this.hexSearch = hexSearch;
22 | this.hexSearchType = hexSearchType;
23 | }
24 |
25 | public HexSearchDocumentListener(
26 | HexSearch hexSearchEngine, JTextField hexSearch, JComboBox hexSearchType,
27 | ActionListener wasNotFoundListener
28 | ) {
29 | this(hexSearchEngine, hexSearch, hexSearchType);
30 | this.wasNotFoundListener = wasNotFoundListener;
31 | }
32 |
33 | @Override
34 | public void insertUpdate(DocumentEvent documentEvent) {
35 | find();
36 | }
37 |
38 | @Override
39 | public void removeUpdate(DocumentEvent documentEvent) {
40 | find();
41 | }
42 |
43 | @Override
44 | public void changedUpdate(DocumentEvent documentEvent) {
45 | find();
46 | }
47 |
48 | private void find() {
49 | try {
50 | boolean wasFound =
51 | hexSearchEngine.searchHexCode(hexSearch.getText(), (HexSearch.HexSearchOptions) hexSearchType.getSelectedItem());
52 |
53 | if (!wasFound && wasNotFoundListener != null) {
54 | wasNotFoundListener.actionPerformed(null);
55 | }
56 | } catch (Exception e) {
57 | Logger.getLogger().log(e);
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/decompilerview/ClassOverwriter.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main.decompilerview;
2 |
3 | import org.jrd.backend.core.ClassInfo;
4 | import org.jrd.backend.decompiling.DecompilerWrapper;
5 | import org.jrd.frontend.frame.overwrite.LatestPaths;
6 | import org.jrd.frontend.frame.overwrite.OverwriteClassDialog;
7 | import org.jrd.frontend.utility.ScreenFinder;
8 |
9 | class ClassOverwriter {
10 | private final DecompilationController decompilationController;
11 | private LatestPaths lastLoaded = new LatestPaths();
12 |
13 | ClassOverwriter(DecompilationController decompilationController) {
14 | this.decompilationController = decompilationController;
15 | }
16 |
17 | void overwriteClass(DecompilerWrapper selectedDecompiler, ClassInfo name, String buffer, byte[] binBuffer, int tab) {
18 | if (name == null) {
19 | throw new RuntimeException("null name, in overwriteClass");
20 | } else if (name.getName() == null || name.getName().trim().isEmpty()) {
21 | name = new ClassInfo("???", name.getLocation(), name.getClassLoader(), "???", "???");
22 | }
23 |
24 | final OverwriteClassDialog overwriteClassDialog = new OverwriteClassDialog(
25 | name, lastLoaded, buffer, binBuffer, decompilationController.getVmInfo(), decompilationController.getVmManager(),
26 | decompilationController.getPluginManager(), selectedDecompiler, tab, decompilationController.isVerbose(),
27 | decompilationController
28 | );
29 |
30 | ScreenFinder.centerWindowToCurrentScreen(overwriteClassDialog);
31 | overwriteClassDialog.setVisible(true);
32 |
33 | lastLoaded.setLastManualUpload(overwriteClassDialog.getManualUploadPath());
34 | lastLoaded.setLastSaveSrc(overwriteClassDialog.getSaveSrcPath());
35 | lastLoaded.setLastSaveBin(overwriteClassDialog.getSaveBinPath());
36 | lastLoaded.setFilesToCompile(overwriteClassDialog.getFilesToCompile());
37 | lastLoaded.setOutputExternalFilesDir(overwriteClassDialog.getOutputExternalFilesDir());
38 | lastLoaded.setOutputBinaries(overwriteClassDialog.getOutputBinaries());
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/test/resources/org/jrd/frontend/frame/main/popup/testPatch1:
--------------------------------------------------------------------------------
1 | From 508a07e33c53b050cda0e3abd242f629c299ed7d Mon Sep 17 00:00:00 2001
2 | From: Michal Karm Babacek
3 | Date: Sun, 16 Oct 2022 10:53:11 +0200
4 | Subject: [PATCH] Quarkus 2.13.0.Final to Quarkus 2.13.2.Final
5 |
6 | ---
7 | jenkins/job_dsl/tests/Constants.groovy | 6 +++---
8 | .../tests/mandrel_linux_amd64_perfcheck_tests.groovy | 2 +-
9 | 2 files changed, 4 insertions(+), 4 deletions(-)
10 |
11 | diff --git a/jenkins/job_dsl/tests/Constants.groovy b/jenkins/job_dsl/tests/Constants.groovy
12 | index e7e1dffc..25312af8 100644
13 | --- a/jenkins/job_dsl/tests/Constants.groovy
14 | +++ b/jenkins/job_dsl/tests/Constants.groovy
15 | @@ -2,21 +2,21 @@ class Constants {
16 |
17 | static final ArrayList QUARKUS_VERSION_LATEST =
18 | [
19 | - '2.13.0.Final',
20 | + '2.13.2.Final',
21 | 'main'
22 | ]
23 |
24 | static final ArrayList QUARKUS_VERSION_RELEASED =
25 | [
26 | '2.7.6.Final',
27 | - '2.13.0.Final'
28 | + '2.13.2.Final'
29 | ]
30 |
31 | static final ArrayList QUARKUS_VERSION_ALL =
32 | [
33 | '2.7.6.Final',
34 | '2.12.2.Final',
35 | - '2.13.0.Final'
36 | + '2.13.2.Final'
37 | ]
38 |
39 | static final String QUARKUS_MODULES_AWT_TESTS = '' +
40 | diff --git a/jenkins/job_dsl/tests/mandrel_linux_amd64_perfcheck_tests.groovy b/jenkins/job_dsl/tests/mandrel_linux_amd64_perfcheck_tests.groovy
41 | index 036e583d..f7b21022 100644
42 | --- a/jenkins/job_dsl/tests/mandrel_linux_amd64_perfcheck_tests.groovy
43 | +++ b/jenkins/job_dsl/tests/mandrel_linux_amd64_perfcheck_tests.groovy
44 | @@ -7,7 +7,7 @@ matrixJob('mandrel-linux-amd64-perfcheck-tests') {
45 | '22.0.0.2-Final'
46 | )
47 | text('QUARKUS_VERSION',
48 | - '2.13.0.Final',
49 | + '2.13.2.Final',
50 | '2.8.3.Final',
51 | '2.8.2.Final',
52 | '2.7.1.Final'
53 | --
54 | GitLab
55 |
56 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/communication/CallDecompilerAgent.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.communication;
2 |
3 | import org.jrd.backend.core.Logger;
4 |
5 | import java.io.IOException;
6 |
7 | /**
8 | * This class is handling opening of communication socket and request submitting.
9 | */
10 | public class CallDecompilerAgent implements DelegatingJrdAgent {
11 |
12 | public static final String DEFAULT_ADDRESS = "localhost";
13 | public static final int DEFAULT_PORT = 5395;
14 |
15 | private final int port;
16 | private final String address;
17 | private final DelegatingHelper delegationCandidates = new DelegatingHelper();
18 |
19 | /**
20 | * Constructor of the object
21 | * @param port port where to open socket
22 | * @param host socket host
23 | */
24 | public CallDecompilerAgent(int port, String host) {
25 | if (host == null) {
26 | host = DEFAULT_ADDRESS;
27 | }
28 |
29 | if (port <= 0) {
30 | port = DEFAULT_PORT;
31 | }
32 |
33 | this.address = host;
34 | this.port = port;
35 | }
36 |
37 | /**
38 | * Opens a socket and sends the request to the agent via socket.
39 | * @param request either "CLASSES" or "BYTES \n className", other formats
40 | * are refused
41 | * @return agents response or null
42 | */
43 | @Override
44 | public String submitRequest(final String request) {
45 | final Communicate comm = new Communicate(this.address, this.port);
46 | try {
47 | comm.println(request);
48 | return comm.readResponse();
49 | } catch (IOException ex) {
50 | Logger.getLogger().log(Logger.Level.DEBUG, ex);
51 | return null;
52 | } finally {
53 | comm.close();
54 | }
55 | }
56 |
57 | @Override
58 | public JrdAgent addDelegatingAgent(JrdAgent agent) {
59 | return delegationCandidates.addDelegatingAgent(agent);
60 | }
61 |
62 | @Override
63 | public JrdAgent removeDelegatingAgent(JrdAgent agent) {
64 | return delegationCandidates.removeDelegatingAgent(agent);
65 | }
66 |
67 | @Override
68 | public int cleanDelegatingAgents() {
69 | return delegationCandidates.cleanDelegatingAgents();
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/kcc/wordsets/ConnectedKeywords.java:
--------------------------------------------------------------------------------
1 | package org.kcc.wordsets;
2 |
3 | import org.kcc.CompletionItem;
4 |
5 | import java.util.ArrayList;
6 | import java.util.Arrays;
7 | import java.util.Collections;
8 | import java.util.HashSet;
9 | import java.util.List;
10 | import java.util.regex.Pattern;
11 | import java.util.stream.Collectors;
12 |
13 | public class ConnectedKeywords implements CompletionItem.CompletionItemSet {
14 | private final CompletionItem.CompletionItemSet[] originalSets;
15 |
16 | public ConnectedKeywords(CompletionItem.CompletionItemSet... originalSets) {
17 | this.originalSets = originalSets;
18 | }
19 |
20 | @Override
21 | public CompletionItem[] getItemsArray() {
22 | return getItemsList().toArray(new CompletionItem[0]);
23 | }
24 |
25 | @Override
26 | public List getItemsList() {
27 | List l = new ArrayList<>();
28 | for (CompletionItem.CompletionItemSet item : originalSets) {
29 | l.addAll(
30 | item.getItemsList().stream().map(
31 | a -> new CompletionItem(a.getKey(), a.getDescription() + "\n from: " + item.toString(), a.getRealReplacement())
32 | ).collect(Collectors.toList())
33 | );
34 | }
35 | List r = new ArrayList<>(new HashSet<>(l));
36 | Collections.sort(r);
37 | return r;
38 | }
39 |
40 | @Override
41 | public Pattern getRecommendedDelimiterSet() {
42 | StringBuilder sb = new StringBuilder();
43 | for (int i = 0; i < originalSets.length; i++) {
44 | CompletionItem.CompletionItemSet item = originalSets[i];
45 | sb.append("(").append(item.getRecommendedDelimiterSet().toString()).append(")");
46 | if (i < originalSets.length - 1) {
47 | sb.append("|");
48 | }
49 | }
50 | return Pattern.compile(sb.toString());
51 | }
52 |
53 | @Override
54 | public String toString() {
55 | return Arrays.stream(originalSets).map(a -> a.toString()).collect(Collectors.joining("; "));
56 | }
57 |
58 | public CompletionItem.CompletionItemSet[] getOriginalSets() {
59 | return Arrays.copyOf(originalSets, originalSets.length);
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/license/LicenseView.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.license;
2 |
3 | import org.jrd.backend.core.Logger;
4 | import org.jrd.frontend.frame.main.MainFrameView;
5 |
6 | import javax.swing.BorderFactory;
7 | import javax.swing.JDialog;
8 | import javax.swing.JScrollPane;
9 | import javax.swing.JTextArea;
10 | import javax.swing.border.EmptyBorder;
11 | import javax.swing.border.EtchedBorder;
12 | import java.awt.BorderLayout;
13 | import java.awt.Dimension;
14 | import java.io.BufferedReader;
15 | import java.io.IOException;
16 | import java.io.InputStream;
17 | import java.io.InputStreamReader;
18 | import java.nio.charset.StandardCharsets;
19 |
20 | public class LicenseView extends JDialog {
21 |
22 | JTextArea licenseTextArea;
23 | JScrollPane scrollPane;
24 |
25 | public LicenseView(MainFrameView mainFrameView) {
26 | licenseTextArea = new JTextArea();
27 | licenseTextArea.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
28 | scrollPane = new JScrollPane(licenseTextArea);
29 | scrollPane.setBorder(BorderFactory.createCompoundBorder(new EmptyBorder(10, 10, 10, 10), new EtchedBorder()));
30 |
31 | InputStream in = getClass().getResourceAsStream("/LICENSE");
32 | StringBuilder sb = new StringBuilder();
33 | try (BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) {
34 | reader.lines().forEach(s -> sb.append(s).append('\n'));
35 | } catch (IOException e) {
36 | sb.append("Unable to read LICENSE file.");
37 | Logger.getLogger().log(Logger.Level.ALL, sb.toString());
38 | }
39 |
40 | licenseTextArea.setText(sb.toString());
41 | licenseTextArea.setEditable(false);
42 | licenseTextArea.setCaretPosition(0);
43 |
44 | this.setTitle("License");
45 | this.setSize(new Dimension(600, 650));
46 | this.setMinimumSize(new Dimension(250, 330));
47 | this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
48 | this.setModalityType(ModalityType.APPLICATION_MODAL);
49 | this.setLayout(new BorderLayout());
50 | this.add(scrollPane, BorderLayout.CENTER);
51 | this.setLocationRelativeTo(mainFrameView.getMainFrame());
52 | this.setVisible(true);
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/completion/JrdCompletionSettings.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.completion;
2 |
3 | import org.jrd.frontend.frame.main.decompilerview.SupportedKeySets;
4 | import org.kcc.CompletionItem;
5 | import org.kcc.CompletionSettings;
6 |
7 | public class JrdCompletionSettings extends CompletionSettings {
8 |
9 | private final boolean dynamicClasses;
10 | private final boolean configAdditionalClasses;
11 | private final boolean methodNames;
12 | private final boolean methodFullSignatures;
13 |
14 | public static JrdCompletionSettings getDefault(ClassesAndMethodsProvider isDynamic) {
15 | return getDefault(isDynamic(isDynamic));
16 | }
17 |
18 | public static JrdCompletionSettings getDefault(boolean dynamicClasses) {
19 | if (dynamicClasses) {
20 | return new JrdCompletionSettings(
21 | SupportedKeySets.getDefaultSet(), CompletionSettings.OP.SPARSE, false, true, true, false, true, true
22 | );
23 | } else {
24 | return new JrdCompletionSettings(
25 | SupportedKeySets.getDefaultSet(), CompletionSettings.OP.SPARSE, false, true, false, true, true, true
26 | );
27 | }
28 | }
29 |
30 | public JrdCompletionSettings(
31 | CompletionItem.CompletionItemSet set, CompletionSettings.OP op, boolean caseSensitive, boolean showHelp, boolean dynamicClasses,
32 | boolean configAdditionalClasses, boolean methodNames, boolean methodFullSignatures
33 | ) {
34 | super(set, op, caseSensitive, showHelp);
35 | this.dynamicClasses = dynamicClasses;
36 | this.configAdditionalClasses = configAdditionalClasses;
37 | this.methodNames = methodNames;
38 | this.methodFullSignatures = methodFullSignatures;
39 | }
40 |
41 | public static boolean isDynamic(ClassesAndMethodsProvider isDynamic) {
42 | return !(isDynamic instanceof ClassesAndMethodsProvider.SettingsClassesAndMethodsProvider);
43 | }
44 |
45 | public boolean isDynamicClasses() {
46 | return dynamicClasses;
47 | }
48 |
49 | public boolean isConfigAdditionalClasses() {
50 | return configAdditionalClasses;
51 | }
52 |
53 | public boolean isMethodNames() {
54 | return methodNames;
55 | }
56 |
57 | public boolean isMethodFullSignatures() {
58 | return methodFullSignatures;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/core/VmDecompilerStatus.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.core;
2 |
3 | import org.jrd.backend.data.BytemanCompanion;
4 |
5 | import java.util.Arrays;
6 |
7 | /**
8 | * This class stores all information about the state of decompiler plugin on
9 | * each VM.
10 | */
11 |
12 | public class VmDecompilerStatus {
13 |
14 | private final boolean reused;
15 | private String vmId;
16 | private String hostname;
17 | private int listenPort;
18 | private ClassInfo[] loadedClasses;
19 | private String loadedClassBytes;
20 | private BytemanCompanion bytemanCompanion;
21 |
22 | public VmDecompilerStatus() {
23 | this(false);
24 | }
25 |
26 | public VmDecompilerStatus(boolean reused) {
27 | this.loadedClassBytes = "";
28 | this.loadedClasses = new ClassInfo[]{};
29 | this.reused = reused;
30 | }
31 |
32 | public String getVmId() {
33 | return vmId;
34 | }
35 |
36 | public void setVmId(String vmId) {
37 | this.vmId = vmId;
38 | }
39 |
40 | public String getHostname() {
41 | return hostname;
42 | }
43 |
44 | public void setHostname(String hostname) {
45 | this.hostname = hostname;
46 | }
47 |
48 | public void setListenPort(int port) {
49 | this.listenPort = port;
50 | }
51 |
52 | public int getListenPort() {
53 | return listenPort;
54 | }
55 |
56 | public void setLoadedClasses(ClassInfo[] loadedClassNames) {
57 | this.loadedClasses = Arrays.copyOf(loadedClassNames, loadedClassNames.length);
58 | }
59 |
60 | public String getLoadedClassBytes() {
61 | return loadedClassBytes;
62 | }
63 |
64 | public String[] getLoadedClassNames() {
65 | return Arrays.stream(loadedClasses).map(ClassInfo::getName).toArray(String[]::new);
66 | }
67 |
68 | public ClassInfo[] getLoadedClasses() {
69 | return Arrays.copyOf(loadedClasses, loadedClasses.length);
70 | }
71 |
72 | public void setLoadedClassBytes(String value) {
73 | loadedClassBytes = value;
74 | }
75 |
76 | public boolean isReused() {
77 | return reused;
78 | }
79 |
80 | public void setBytemanCompanion(BytemanCompanion bytemanCompanion) {
81 | this.bytemanCompanion = bytemanCompanion;
82 | }
83 |
84 | public BytemanCompanion getBytemanCompanion() {
85 | return bytemanCompanion;
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/plugins/ConfigPanel.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.plugins;
2 |
3 | import javax.swing.Box;
4 | import javax.swing.JLabel;
5 | import javax.swing.JPanel;
6 | import java.awt.GridBagConstraints;
7 | import java.awt.GridBagLayout;
8 | import java.awt.Insets;
9 |
10 | public class ConfigPanel extends JPanel {
11 |
12 | private final JLabel jsonFileUrl;
13 | private final MessagePanel messagePanel;
14 | private final TextInputPanel namePanel;
15 | private final FileSelectorPanel wrapperUrlPanel;
16 | private final FileSelectorArrayPanel dependencyUrlPanel;
17 |
18 | public ConfigPanel() {
19 | this.setLayout(new GridBagLayout());
20 |
21 | jsonFileUrl = new JLabel();
22 | messagePanel = new MessagePanel(
23 | "Info: You don't have permissions to save this configuration! " + "You can clone it and save the copy."
24 | );
25 | messagePanel.setVisible(false);
26 | namePanel = new TextInputPanel("Name");
27 | wrapperUrlPanel = new FileSelectorPanel("Decompiler wrapper");
28 | dependencyUrlPanel = new FileSelectorArrayPanel("Decompiler dependency jars");
29 |
30 | GridBagConstraints gbc = new GridBagConstraints();
31 | gbc.anchor = GridBagConstraints.NORTHWEST;
32 | gbc.fill = GridBagConstraints.BOTH;
33 | gbc.insets = new Insets(3, 3, 3, 3);
34 | gbc.weightx = 1;
35 | this.add(jsonFileUrl, gbc);
36 | gbc.gridy = 1;
37 | this.add(messagePanel, gbc);
38 | gbc.gridy = 2;
39 | this.add(namePanel, gbc);
40 | gbc.gridy = 3;
41 | this.add(wrapperUrlPanel, gbc);
42 | gbc.gridy = 4;
43 | this.add(dependencyUrlPanel, gbc);
44 | gbc.gridy = 99999;
45 | gbc.weighty = 1;
46 | this.add(Box.createVerticalGlue(), gbc);
47 | //sets gbc for addComponent method
48 | gbc.gridy = 0;
49 | gbc.weighty = 0;
50 | }
51 |
52 | public JLabel getJsonFileUrl() {
53 | return jsonFileUrl;
54 | }
55 |
56 | public MessagePanel getMessagePanel() {
57 | return messagePanel;
58 | }
59 |
60 | public TextInputPanel getNamePanel() {
61 | return namePanel;
62 | }
63 |
64 | public FileSelectorPanel getWrapperUrlPanel() {
65 | return wrapperUrlPanel;
66 | }
67 |
68 | public FileSelectorArrayPanel getDependencyUrlPanel() {
69 | return dependencyUrlPanel;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/data/cli/utils/Saving.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data.cli.utils;
2 |
3 | import org.jrd.backend.core.Logger;
4 | import org.jrd.frontend.utility.CommonUtils;
5 |
6 | import java.io.FileOutputStream;
7 | import java.io.IOException;
8 | import java.io.PrintStream;
9 |
10 | public class Saving implements CommonUtils.StatusKeeper {
11 | public static final String DEFAULT = "default";
12 | public static final String EXACT = "exact";
13 | public static final String FQN = "fqn";
14 | public static final String DIR = "dir";
15 | private final String as;
16 | private final String like;
17 |
18 | public Saving(String as, String like) {
19 | this.as = as;
20 | if (like == null) {
21 | this.like = DEFAULT;
22 | } else {
23 | this.like = like;
24 | }
25 | }
26 |
27 | public boolean shouldSave() {
28 | return getAs() != null;
29 | }
30 |
31 | @Override
32 | public void setText(String s) {
33 | if (shouldSave()) {
34 | System.out.println(s);
35 | } else {
36 | System.err.println(s);
37 | }
38 | }
39 |
40 | @Override
41 | public void onException(Exception ex) {
42 | Logger.getLogger().log(ex);
43 | }
44 |
45 | @SuppressWarnings("ReturnCount") // returns in switch cases
46 | public int toInt(String suffix) {
47 | switch (getLike()) {
48 | case FQN:
49 | return CommonUtils.FULLY_QUALIFIED_NAME;
50 | case EXACT:
51 | return CommonUtils.CUSTOM_NAME;
52 | case DIR:
53 | return CommonUtils.SRC_SUBDIRS_NAME;
54 | case DEFAULT:
55 | if (".java".equals(suffix)) {
56 | return CommonUtils.FULLY_QUALIFIED_NAME;
57 | }
58 | if (".class".equals(suffix)) {
59 | return CommonUtils.SRC_SUBDIRS_NAME;
60 | }
61 | return CommonUtils.CUSTOM_NAME;
62 | default:
63 | throw new RuntimeException("Unknown saving type: " + getLike() + ". Allowed are: " + FQN + "," + DIR + "," + EXACT);
64 | }
65 | }
66 |
67 | public PrintStream openPrintStream() throws IOException {
68 | return new PrintStream(new FileOutputStream(this.getAs()), true, "UTF-8");
69 | }
70 |
71 | public String getAs() {
72 | return as;
73 | }
74 |
75 | public String getLike() {
76 | return like;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/.plugin_config/spotbugs_exclude.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/decompilerview/SupportedKeySets.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main.decompilerview;
2 |
3 | import org.jrd.backend.core.Logger;
4 | import org.kcc.CompletionItem;
5 | import org.kcc.CompletionSettings;
6 | import org.kcc.wordsets.BytecodeKeywordsWithHelp;
7 | import org.kcc.wordsets.BytemanKeywords;
8 | import org.kcc.wordsets.JavaKeywordsWithHelp;
9 | import org.kcc.wordsets.JrdApiKeywords;
10 |
11 | import java.util.ArrayList;
12 | import java.util.Arrays;
13 | import java.util.List;
14 |
15 | public class SupportedKeySets {
16 | public static final SupportedKeySets JRD_KEY_SETS =
17 | new SupportedKeySets(new JrdApiKeywords(), new BytemanKeywords(), new BytecodeKeywordsWithHelp(), new JavaKeywordsWithHelp());
18 |
19 | public static final CompletionSettings JRD_DEFAULT = new CompletionSettings(getDefaultSet(), CompletionSettings.OP.SPARSE, false, true);
20 |
21 | public static CompletionItem.CompletionItemSet getDefaultSet() {
22 | return JRD_KEY_SETS.sets[0];
23 | }
24 |
25 | private final CompletionItem.CompletionItemSet[] sets;
26 |
27 | public SupportedKeySets(CompletionItem.CompletionItemSet... sets) {
28 | this.sets = sets;
29 | }
30 |
31 | public CompletionItem.CompletionItemSet[] getSets() {
32 | return Arrays.copyOf(sets, sets.length);
33 | }
34 |
35 | public List recognize(String textWithKeywords) {
36 | CompletionSettings.RecognitionResult[] rr = CompletionSettings.recognize(textWithKeywords, sets);
37 | List result = new ArrayList<>();
38 | for (CompletionSettings.RecognitionResult r : rr) {
39 | Logger.getLogger().log(Logger.Level.DEBUG, sets[r.getIndex()].toString());
40 | Logger.getLogger().log(Logger.Level.DEBUG, r.toString());
41 | if (r.getPercent() > 5 && result.size() < 2) {
42 | result.add(r.getSet());
43 | Logger.getLogger().log(Logger.Level.DEBUG, "accepted");
44 | }
45 | }
46 | return result;
47 | }
48 |
49 | public boolean isByteman(CompletionItem.CompletionItemSet set) {
50 | return set.toString().equals(sets[1].toString());
51 | }
52 |
53 | public boolean isJasm(CompletionItem.CompletionItemSet set) {
54 | return set.toString().equals(sets[2].toString());
55 | }
56 |
57 | public boolean isJava(CompletionItem.CompletionItemSet set) {
58 | return set.toString().equals(sets[3].toString());
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/plugins/JasmDecompilerWrapper.java:
--------------------------------------------------------------------------------
1 | import java.io.ByteArrayOutputStream;
2 | import java.io.File;
3 | import java.io.IOException;
4 | import java.io.PrintStream;
5 | import java.util.ArrayList;
6 | import java.util.Arrays;
7 | import java.util.HashMap;
8 | import java.util.List;
9 | import java.util.Map;
10 | import java.io.PrintWriter;
11 | import java.util.Set;
12 |
13 | import org.openjdk.asmtools.common.inputs.*;
14 | import org.openjdk.asmtools.common.outputs.log.*;
15 | import org.openjdk.asmtools.common.outputs.*;
16 |
17 | public class JasmDecompilerWrapper {
18 |
19 | public String decompile(byte[] bytecode, String[] options) {
20 | try {
21 | log(null, "jasm decompiler caled with input of bytes: " + bytecode.length);
22 | ToolInput[] originalFiles = new ToolInput[]{new ByteInput(bytecode)};
23 | TextOutput decodedFiles = new TextOutput();
24 | SingleDualOutputStreamOutput decodeLog = new StderrLog();
25 | org.openjdk.asmtools.jdis.Main jdis = new org.openjdk.asmtools.jdis.Main(decodedFiles, decodeLog, originalFiles);
26 | jdis.setVerboseFlag(true);
27 | int r = jdis.disasm();
28 | return decodedFiles.getOutputs().get(0).getBody();
29 | } catch (Exception e) {
30 | e.printStackTrace();
31 | return e.toString();
32 | }
33 | }
34 |
35 | private void log(Object logger, String message) {
36 | System.err.println(message);
37 | }
38 |
39 | public Map compile(Map src, String[] options, Object maybeLogger) throws Exception {
40 | log(maybeLogger, "jasm compiler caled with input of files: " + src.size());
41 | ToolInput[] originalFiles = new ToolInput[src.size()];
42 | ArrayList> input = new ArrayList<>(src.entrySet());
43 | for (int i = 0; i < input.size(); i++) {
44 | originalFiles[i] = new StringInput(input.get(i).getValue());
45 | }
46 | ByteOutput encodedFiles = new ByteOutput();
47 | SingleDualOutputStreamOutput encodeLog = new StderrLog();
48 | org.openjdk.asmtools.jasm.Main jasm = new org.openjdk.asmtools.jasm.Main(encodedFiles, encodeLog, originalFiles);
49 | jasm.setVerboseFlag(true);
50 | int r = jasm.compile();
51 | Map results = new HashMap<>(src.size());
52 | for(ByteOutput.NamedBinary nb: encodedFiles.getOutputs()) {
53 | results.put(nb.getFqn().replace("/", "."), nb.getBody());
54 | }
55 | return results;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/data/cli/workers/AttachDetach.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data.cli.workers;
2 |
3 | import org.jrd.backend.communication.CallDecompilerAgent;
4 | import org.jrd.backend.core.AgentAttachManager;
5 | import org.jrd.backend.core.VmDecompilerStatus;
6 | import org.jrd.backend.data.VmInfo;
7 | import org.jrd.backend.data.VmManager;
8 | import org.jrd.backend.data.cli.CliUtils;
9 | import org.jrd.backend.data.cli.Help;
10 | import org.jrd.backend.data.cli.Lib;
11 | import org.jrd.backend.data.cli.utils.AgentConfig;
12 |
13 | import java.util.List;
14 |
15 | public class AttachDetach {
16 |
17 | private final List filteredArgs;
18 | private final VmManager vmManager;
19 |
20 | public AttachDetach(List filteredArgs, VmManager vmManager) {
21 | this.filteredArgs = filteredArgs;
22 | this.vmManager = vmManager;
23 | }
24 |
25 | public VmInfo attach(AgentConfig agntConfig) throws Exception {
26 | final int mandatoryParam = 2;
27 | if (filteredArgs.size() < mandatoryParam) {
28 | throw new IllegalArgumentException("Incorrect argument count! Please use '" + Help.ATTACH_FORMAT + "'.");
29 | }
30 | if (CliUtils.guessType(filteredArgs.get(1)) != VmInfo.Type.LOCAL) {
31 | throw new IllegalArgumentException("Sorry, first argument must be running jvm PID, nothing else.");
32 | }
33 | VmInfo vmInfo = CliUtils.getVmInfo(filteredArgs.get(1), vmManager);
34 | VmDecompilerStatus status = new AgentAttachManager(vmManager).attachAgentToVm(vmInfo.getVmId(), vmInfo.getVmPid(), agntConfig);
35 | System.out.println("Attached. Listening on: " + status.getListenPort());
36 | return vmInfo;
37 | }
38 |
39 | public void detach() {
40 | if (filteredArgs.size() < 2) {
41 | throw new IllegalArgumentException("Incorrect argument count! Please use '" + Help.DETACH_FORMAT + "'.");
42 | }
43 | if (filteredArgs.get(1).contains(":")) {
44 | String[] hostPort = filteredArgs.get(1).split(":");
45 | Lib.detach(hostPort[0], Integer.parseInt(hostPort[1]), vmManager);
46 | } else {
47 | //TODO is pid? If so, detach its port, else localhost
48 | detach(Integer.parseInt(filteredArgs.get(1)));
49 | }
50 | }
51 |
52 | private void detach(int port) {
53 | detachLocalhost(port, vmManager);
54 | }
55 |
56 | public static void detachLocalhost(int port, VmManager vmManager) {
57 | Lib.detach(CallDecompilerAgent.DEFAULT_ADDRESS, port, vmManager);
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/decompilerview/dummycompiler/AbstractCompileAndRunAction.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main.decompilerview.dummycompiler;
2 |
3 | import org.jrd.frontend.frame.main.decompilerview.dummycompiler.providers.ClasspathProvider;
4 | import org.jrd.frontend.frame.main.decompilerview.dummycompiler.providers.ExecuteMethodProvider;
5 | import org.jrd.frontend.frame.main.decompilerview.dummycompiler.providers.SaveProvider;
6 | import org.jrd.frontend.frame.main.decompilerview.dummycompiler.providers.UploadProvider;
7 |
8 | public abstract class AbstractCompileAndRunAction extends AbstractCompileAction {
9 |
10 | protected final ClasspathProvider classesAndMethodsProvider;
11 | protected final SaveProvider save;
12 | protected final UploadProvider upload;
13 | protected final ExecuteMethodProvider execute;
14 |
15 | public AbstractCompileAndRunAction(
16 | String stub, ClasspathProvider classesAndMethodsProvider, SaveProvider save, UploadProvider upload,
17 | ExecuteMethodProvider execute
18 | ) {
19 | super(stub);
20 | this.classesAndMethodsProvider = classesAndMethodsProvider;
21 | this.save = save;
22 | this.upload = upload;
23 | this.execute = execute;
24 | }
25 |
26 | @Override
27 | public String getText() {
28 | String s = super.getText();
29 | if (classesAndMethodsProvider != null) {
30 | s = s + "
" + classesAndMethodsProvider.getClasspath().cpTextInfo() + "
";
31 | } else {
32 | s = s + "
";
33 | }
34 | if (save != null) {
35 | if (save.getSaveDirectory() == null) {
36 | s = s + "; no saving";
37 | } else {
38 | s = s + "; save to: " + save.getSaveDirectory().getAbsolutePath();
39 | }
40 | }
41 | if (execute != null) {
42 | if (execute.getMethodToExecute() == null) {
43 | s = s + "; nothing to execute";
44 | } else {
45 | s = s + "; will be executed: `" + execute.getMethodToExecute() + "`";
46 | }
47 | }
48 | if (upload != null) {
49 | if (!upload.isUploadEnabled()) {
50 | s = s + "; no adding to running vm";
51 | } else {
52 | s = s + "; will be added to: " + upload.getTarget().getClasspath().cpTextInfo();
53 | if (upload.isBoot()) {
54 | s = s + " to Boot cp!!!";
55 | }
56 | }
57 | }
58 | return s;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/plugins/JcoderDecompilerWrapper.java:
--------------------------------------------------------------------------------
1 | import java.io.ByteArrayOutputStream;
2 | import java.io.File;
3 | import java.io.IOException;
4 | import java.io.PrintStream;
5 | import java.util.ArrayList;
6 | import java.util.Arrays;
7 | import java.util.HashMap;
8 | import java.util.List;
9 | import java.util.Map;
10 | import java.io.PrintWriter;
11 | import java.util.Set;
12 |
13 | import org.openjdk.asmtools.common.inputs.*;
14 | import org.openjdk.asmtools.common.outputs.log.*;
15 | import org.openjdk.asmtools.common.outputs.*;
16 |
17 | public class JcoderDecompilerWrapper {
18 |
19 | public String decompile(byte[] bytecode, String[] options) {
20 | try {
21 | log(null, "jcoder decompiler caled with input of bytes: " + bytecode.length);
22 | ToolInput[] originalFiles = new ToolInput[]{new ByteInput(bytecode)};
23 | TextOutput decodedFiles = new TextOutput();
24 | SingleDualOutputStreamOutput decodeLog = new StderrLog();
25 | org.openjdk.asmtools.jdec.Main jdec = new org.openjdk.asmtools.jdec.Main(decodedFiles, decodeLog, originalFiles);
26 | jdec.setVerboseFlag(true);
27 | int r = jdec.decode();
28 | return decodedFiles.getOutputs().get(0).getBody();
29 | } catch (Exception e) {
30 | e.printStackTrace();
31 | return e.toString();
32 | }
33 | }
34 |
35 | private void log(Object logger, String message) {
36 | System.err.println(message);
37 | }
38 |
39 | public Map compile(Map src, String[] options, Object maybeLogger) throws Exception {
40 | log(maybeLogger, "jcoder compiler caled with input of files: " + src.size());
41 | ToolInput[] originalFiles = new ToolInput[src.size()];
42 | ArrayList> input = new ArrayList<>(src.entrySet());
43 | for (int i = 0; i < input.size(); i++) {
44 | originalFiles[i] = new StringInput(input.get(i).getValue());
45 | }
46 | ByteOutput encodedFiles = new ByteOutput();
47 | SingleDualOutputStreamOutput encodeLog = new StderrLog();
48 | org.openjdk.asmtools.jcoder.Main jcoder = new org.openjdk.asmtools.jcoder.Main(encodedFiles, encodeLog, originalFiles);
49 | jcoder.setVerboseFlag(true);
50 | int r = jcoder.compile();
51 | Map results = new HashMap<>(src.size());
52 | for(ByteOutput.NamedBinary nb: encodedFiles.getOutputs()) {
53 | results.put(nb.getFqn().replace("/", ".").replaceAll("\\.class$",""), nb.getBody());
54 | }
55 | return results;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/about/AboutView.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.about;
2 |
3 | import org.jrd.backend.core.Logger;
4 | import org.jrd.backend.data.MetadataProperties;
5 |
6 | import javax.swing.JDialog;
7 | import javax.swing.JEditorPane;
8 | import javax.swing.JFrame;
9 | import javax.swing.JLabel;
10 | import javax.swing.JOptionPane;
11 | import javax.swing.event.HyperlinkEvent;
12 | import java.awt.Color;
13 | import java.awt.Desktop;
14 | import java.awt.Font;
15 | import java.io.IOException;
16 | import java.net.URISyntaxException;
17 |
18 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
19 |
20 | public class AboutView extends JDialog {
21 |
22 | @SuppressFBWarnings(value = "CT_CONSTRUCTOR_THROW", justification = "be aware, this constrctor throws")
23 | public AboutView(JFrame mainFrameView, boolean showVersion) {
24 | JLabel label = new JLabel();
25 | Font font = label.getFont();
26 |
27 | String style = "font-family:" + font.getFamily() + ";" + "font-weight:" + (font.isBold() ? "bold" : "normal") + ";" + "font-size:" +
28 | font.getSize() + "pt;";
29 |
30 | JEditorPane editorPane = new JEditorPane(
31 | "text/html",
32 | "" + "Java-Runtime-Decompiler
" + "Version " +
33 | (showVersion ? MetadataProperties.getInstance().getVersion() : "No version") + "
" +
34 | "Licenced under the GNU General Public License v3.0
" +
35 | "Visit the GitHub repository" +
36 | " for more information.
" + ""
37 | );
38 |
39 | editorPane.addHyperlinkListener(event -> {
40 | if (event.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) {
41 | try {
42 | Desktop.getDesktop().browse(event.getURL().toURI());
43 | } catch (IOException | URISyntaxException e1) {
44 | Logger.getLogger().log(Logger.Level.ALL, e1);
45 | } catch (UnsupportedOperationException e2) {
46 | Logger.getLogger().log(Logger.Level.ALL, new RuntimeException("Unable to open link."));
47 | }
48 |
49 | }
50 | });
51 | editorPane.setEditable(false);
52 | editorPane.setBackground(new Color(label.getBackground().getRGB()));
53 |
54 | JOptionPane.showMessageDialog(mainFrameView, editorPane, "About Java-Runtime-Decompiler", JOptionPane.INFORMATION_MESSAGE);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/test/java/org/jrd/frontend/frame/overwrite/OverwriteClassDialogTest.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.overwrite;
2 |
3 | import org.jrd.backend.data.Config;
4 | import org.junit.jupiter.api.Assertions;
5 | import org.junit.jupiter.api.Test;
6 |
7 | import java.util.ArrayList;
8 | import java.util.Arrays;
9 | import java.util.List;
10 | import java.util.NoSuchElementException;
11 | import java.util.Optional;
12 |
13 | public class OverwriteClassDialogTest {
14 |
15 | @Test
16 | void testPurgeSourceTarget() {
17 | List params = new ArrayList<>();
18 | Config.getConfig().setBestSourceTarget(Optional.of(8));
19 | OverwriteClassDialog.purgeSourceTarget(params);
20 | Assertions.assertEquals(Arrays.asList("-source", "8", "-target", "8"), params);
21 | Config.getConfig().setBestSourceTarget(Optional.of(11));
22 | OverwriteClassDialog.purgeSourceTarget(params);
23 | Assertions.assertEquals(Arrays.asList("-source", "11", "-target", "11"), params);
24 | Config.getConfig().setBestSourceTarget(Optional.of(8));
25 | params.add(0, "param1");
26 | params.add(1, "param2");
27 | OverwriteClassDialog.purgeSourceTarget(params);
28 | Assertions.assertEquals(Arrays.asList("-source", "8", "-target", "8", "param1", "param2"), params);
29 | Config.getConfig().setBestSourceTarget(Optional.of(11));
30 | OverwriteClassDialog.purgeSourceTarget(params);
31 | Assertions.assertEquals(Arrays.asList("-source", "11", "-target", "11", "param1", "param2"), params);
32 | Config.getConfig().setBestSourceTarget(Optional.of(8));
33 | params.add(0, "param3");
34 | params.add(1, "param4");
35 | OverwriteClassDialog.purgeSourceTarget(params);
36 | Assertions.assertEquals(Arrays.asList("-source", "8", "-target", "8", "param3", "param4", "param1", "param2"), params);
37 | params = new ArrayList<>();
38 | Config.getConfig().setBestSourceTarget(Optional.of(11));
39 | params.add(0, "param1");
40 | params.add(1, "param2");
41 | OverwriteClassDialog.purgeSourceTarget(params);
42 | Assertions.assertEquals(Arrays.asList("-source", "11", "-target", "11", "param1", "param2"), params);
43 | }
44 |
45 | @Test
46 | void testPurgeSourceTargetEmpty() {
47 | List params = new ArrayList<>();
48 | Config.getConfig().setBestSourceTarget(Optional.empty());
49 | params.add(0, "param1");
50 | params.add(1, "param2");
51 | Exception exception = Assertions.assertThrows(NoSuchElementException.class, () -> OverwriteClassDialog.purgeSourceTarget(params));
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/plugins/JasmGDecompilerWrapper.java:
--------------------------------------------------------------------------------
1 | import java.io.ByteArrayOutputStream;
2 | import java.io.File;
3 | import java.io.IOException;
4 | import java.io.PrintStream;
5 | import java.util.ArrayList;
6 | import java.util.Arrays;
7 | import java.util.HashMap;
8 | import java.util.List;
9 | import java.util.Map;
10 | import java.io.PrintWriter;
11 | import java.util.Set;
12 |
13 | import org.openjdk.asmtools.common.inputs.*;
14 | import org.openjdk.asmtools.common.outputs.log.*;
15 | import org.openjdk.asmtools.common.outputs.*;
16 | import org.openjdk.asmtools.jdis.Options;
17 |
18 | public class JasmGDecompilerWrapper {
19 |
20 | public String decompile(byte[] bytecode, String[] options) {
21 | try {
22 | log(null, "jasmG decompiler caled with input of bytes: " + bytecode.length);
23 | ToolInput[] originalFiles = new ToolInput[]{new ByteInput(bytecode)};
24 | TextOutput decodedFiles = new TextOutput();
25 | SingleDualOutputStreamOutput decodeLog = new StderrLog();
26 | org.openjdk.asmtools.jdis.Main jdis = new org.openjdk.asmtools.jdis.Main(decodedFiles, decodeLog, originalFiles);
27 | jdis.setVerboseFlag(true);
28 | Options.setDetailedOutputOptions();
29 | int r = jdis.disasm();
30 | return decodedFiles.getOutputs().get(0).getBody();
31 | } catch (Exception e) {
32 | e.printStackTrace();
33 | return e.toString();
34 | }
35 | }
36 |
37 | private void log(Object logger, String message) {
38 | System.err.println(message);
39 | }
40 |
41 | public Map compile(Map src, String[] options, Object maybeLogger) throws Exception {
42 | log(maybeLogger, "jasmG compiler caled with input of files: " + src.size());
43 | ToolInput[] originalFiles = new ToolInput[src.size()];
44 | ArrayList> input = new ArrayList<>(src.entrySet());
45 | for (int i = 0; i < input.size(); i++) {
46 | originalFiles[i] = new StringInput(input.get(i).getValue());
47 | }
48 | ByteOutput encodedFiles = new ByteOutput();
49 | SingleDualOutputStreamOutput encodeLog = new StderrLog();
50 | org.openjdk.asmtools.jasm.Main jasm = new org.openjdk.asmtools.jasm.Main(encodedFiles, encodeLog, originalFiles);
51 | jasm.setVerboseFlag(true);
52 | int r = jasm.compile();
53 | Map results = new HashMap<>(src.size());
54 | for(ByteOutput.NamedBinary nb: encodedFiles.getOutputs()) {
55 | results.put(nb.getFqn().replace("/", "."), nb.getBody());
56 | }
57 | return results;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/filesystem/NewFsVmController.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.filesystem;
2 |
3 | import org.jrd.backend.data.VmManager;
4 |
5 | import javax.swing.JOptionPane;
6 |
7 | import java.io.File;
8 | import java.util.ArrayList;
9 | import java.util.List;
10 |
11 | public class NewFsVmController {
12 |
13 | NewFsVmView newConnectionView;
14 | VmManager vmManager;
15 |
16 | public NewFsVmController(NewFsVmView newConnectionView, VmManager vmManager) {
17 | this.newConnectionView = newConnectionView;
18 | this.vmManager = vmManager;
19 | newConnectionView.setAddButtonListener(e -> addFsVm());
20 | }
21 |
22 | private void addFsVm() {
23 | String cp = newConnectionView.getCp();
24 | String name = newConnectionView.getNameHelper();
25 | boolean shouldBeSaved = newConnectionView.shouldBeSaved();
26 | List r;
27 |
28 | try {
29 | r = cpToFiles(cp);
30 | } catch (InvalidClasspathException e) {
31 | JOptionPane.showMessageDialog(newConnectionView, e.getMessage(), "Unable to create FS VM", JOptionPane.WARNING_MESSAGE);
32 | return;
33 | }
34 |
35 | vmManager.createFsVM(r, name, shouldBeSaved);
36 | newConnectionView.dispose();
37 | }
38 |
39 | public static List cpToFilesCaught(String input) {
40 | try {
41 | return cpToFiles(input);
42 | } catch (InvalidClasspathException ex) {
43 | throw new RuntimeException(ex);
44 | }
45 | }
46 |
47 | public static List cpToFiles(String input) throws InvalidClasspathException {
48 | String[] classpathElements = input.split(File.pathSeparator);
49 |
50 | if (classpathElements.length == 0) {
51 | throw new InvalidClasspathException("Classpath is empty.");
52 | }
53 |
54 | List classpathList = new ArrayList<>(classpathElements.length);
55 | for (String element : classpathElements) {
56 | File file = new File(element);
57 |
58 | if (!file.exists()) {
59 | throw new InvalidClasspathException("File '" + file.getAbsolutePath() + "' does not exist.");
60 | } else {
61 | classpathList.add(file);
62 | }
63 | }
64 |
65 | return classpathList;
66 | }
67 |
68 | public static class InvalidClasspathException extends Exception {
69 | public InvalidClasspathException(String s, Throwable cause) {
70 | super(s, cause);
71 | }
72 |
73 | public InvalidClasspathException(String s) {
74 | super(s);
75 | }
76 |
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/plugins/JcoderGDecompilerWrapper.java:
--------------------------------------------------------------------------------
1 | import java.io.ByteArrayOutputStream;
2 | import java.io.File;
3 | import java.io.IOException;
4 | import java.io.PrintStream;
5 | import java.util.ArrayList;
6 | import java.util.Arrays;
7 | import java.util.HashMap;
8 | import java.util.List;
9 | import java.util.Map;
10 | import java.io.PrintWriter;
11 | import java.util.Set;
12 |
13 | import org.openjdk.asmtools.common.inputs.*;
14 | import org.openjdk.asmtools.common.outputs.log.*;
15 | import org.openjdk.asmtools.common.outputs.*;
16 | import org.openjdk.asmtools.jdis.Options;
17 |
18 | public class JcoderGDecompilerWrapper {
19 |
20 | public String decompile(byte[] bytecode, String[] options) {
21 | try {
22 | log(null, "jcoder decompiler caled with input of bytes: " + bytecode.length);
23 | ToolInput[] originalFiles = new ToolInput[]{new ByteInput(bytecode)};
24 | TextOutput decodedFiles = new TextOutput();
25 | SingleDualOutputStreamOutput decodeLog = new StderrLog();
26 | org.openjdk.asmtools.jdec.Main jdec = new org.openjdk.asmtools.jdec.Main(decodedFiles, decodeLog, originalFiles);
27 | jdec.setVerboseFlag(true);
28 | jdec.setPrintDetails(true);
29 | int r = jdec.decode();
30 | return decodedFiles.getOutputs().get(0).getBody();
31 | } catch (Exception e) {
32 | e.printStackTrace();
33 | return e.toString();
34 | }
35 | }
36 |
37 | private void log(Object logger, String message) {
38 | System.err.println(message);
39 | }
40 |
41 | public Map compile(Map src, String[] options, Object maybeLogger) throws Exception {
42 | log(maybeLogger, "jcoder compiler caled with input of files: " + src.size());
43 | ToolInput[] originalFiles = new ToolInput[src.size()];
44 | ArrayList> input = new ArrayList<>(src.entrySet());
45 | for (int i = 0; i < input.size(); i++) {
46 | originalFiles[i] = new StringInput(input.get(i).getValue());
47 | }
48 | ByteOutput encodedFiles = new ByteOutput();
49 | SingleDualOutputStreamOutput encodeLog = new StderrLog();
50 | org.openjdk.asmtools.jcoder.Main jcoder = new org.openjdk.asmtools.jcoder.Main(encodedFiles, encodeLog, originalFiles);
51 | jcoder.setVerboseFlag(true);
52 | int r = jcoder.compile();
53 | Map results = new HashMap<>(src.size());
54 | for(ByteOutput.NamedBinary nb: encodedFiles.getOutputs()) {
55 | results.put(nb.getFqn().replace("/", ".").replaceAll("\\.class$",""), nb.getBody());
56 | }
57 | return results;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/plugins/FileSelectorPanel.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.plugins;
2 |
3 | import org.jrd.backend.data.Directories;
4 | import org.jrd.frontend.frame.main.decompilerview.BytecodeDecompilerView;
5 |
6 | import javax.swing.Box;
7 | import javax.swing.JButton;
8 | import javax.swing.JFileChooser;
9 | import javax.swing.JLabel;
10 | import javax.swing.JPanel;
11 | import javax.swing.JTextField;
12 | import java.awt.Dimension;
13 | import java.awt.GridBagConstraints;
14 | import java.awt.GridBagLayout;
15 | import java.io.File;
16 |
17 | public class FileSelectorPanel extends JPanel {
18 |
19 | private JTextField textField;
20 | private JLabel jLabel;
21 | private JButton browseButton;
22 | private JFileChooser chooser;
23 |
24 | FileSelectorPanel(String label) {
25 | this(label, "Browse");
26 | }
27 |
28 | FileSelectorPanel(String label, String buttonLabel) {
29 |
30 | this.textField = new JTextField();
31 | textField.setPreferredSize(new Dimension(0, 32));
32 | textField.setToolTipText(
33 | BytecodeDecompilerView.styleTooltip() + "Select a path to the decompiler wrapper .java file.
" +
34 | FileSelectorArrayRow.getTextFieldToolTip()
35 | );
36 |
37 | this.jLabel = new JLabel(label);
38 | this.browseButton = new JButton(buttonLabel);
39 |
40 | this.chooser = new JFileChooser();
41 | File dir = new File(Directories.getPluginDirectory());
42 | chooser.setCurrentDirectory(FileSelectorArrayRow.fallback(dir));
43 |
44 | browseButton.addActionListener(actionEvent -> {
45 | int returnVar = chooser.showOpenDialog(this);
46 | if (returnVar == JFileChooser.APPROVE_OPTION) {
47 | textField.setText(chooser.getSelectedFile().getPath());
48 | }
49 | });
50 |
51 | this.setLayout(new GridBagLayout());
52 | GridBagConstraints gbc = new GridBagConstraints();
53 | gbc.anchor = GridBagConstraints.WEST;
54 | gbc.fill = GridBagConstraints.BOTH;
55 |
56 | gbc.gridy = 0;
57 | gbc.gridx = 0;
58 | this.add(this.jLabel, gbc);
59 |
60 | gbc.gridy = 1;
61 | gbc.gridx = 0;
62 | gbc.weightx = 1;
63 | this.add(textField, gbc);
64 | gbc.weightx = 0;
65 | gbc.gridx = 1;
66 | this.add(Box.createHorizontalStrut(20), gbc);
67 | gbc.gridx = 2;
68 | this.add(browseButton, gbc);
69 | this.setPreferredSize(new Dimension(0, 80));
70 | }
71 |
72 | public String getText() {
73 | return textField.getText();
74 | }
75 |
76 | public void setText(String text) {
77 | textField.setText(text);
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/data/Main.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data;
2 |
3 | import org.jrd.backend.completion.ClassesAndMethodsProvider;
4 | import org.jrd.backend.core.Logger;
5 | import org.jrd.backend.data.cli.Cli;
6 | import org.jrd.backend.data.cli.Help;
7 | import org.jrd.frontend.frame.hex.StandaloneHex;
8 | import org.jrd.frontend.frame.main.decompilerview.DecompilationController;
9 | import org.jrd.frontend.frame.main.MainFrameView;
10 |
11 | import javax.swing.UIManager;
12 |
13 | public class Main {
14 |
15 | public static void main(String[] allArgs) throws Exception {
16 | Cli cli = new Cli(allArgs);
17 | if (cli.isGui()) {
18 | setLookAndFeel();
19 | if (!cli.getFilteredArgs().isEmpty()) {
20 | Help.printHelpText();
21 | if (!cli.isFs()) {
22 | StandaloneHex hexview = new StandaloneHex(
23 | cli.getFilteredArgs(), cli.isHex(), new ClassesAndMethodsProvider.SettingsClassesAndMethodsProvider()
24 | );
25 | hexview.setVisible(true);
26 | } else {
27 | MainFrameView mainView = new MainFrameView(cli.getFilteredArgs().get(0));
28 | DecompilationController dec = new DecompilationController(mainView, cli.shouldBeVerbose());
29 | mainView.getBytecodeDecompilerView().setCompletionHelper(dec);
30 | }
31 | } else {
32 | if (cli.isHex() && cli.getFilteredArgs().isEmpty()) {
33 | Help.printHelpText();
34 | StandaloneHex hexview = new StandaloneHex(
35 | cli.getFilteredArgs(), cli.isHex(), new ClassesAndMethodsProvider.SettingsClassesAndMethodsProvider()
36 | );
37 | hexview.setVisible(true);
38 | } else {
39 | MainFrameView mainView = new MainFrameView(null);
40 | DecompilationController dec = new DecompilationController(mainView, cli.shouldBeVerbose());
41 | mainView.getBytecodeDecompilerView().setCompletionHelper(dec);
42 | }
43 | }
44 | } else {
45 | cli.consumeCli();
46 | }
47 |
48 | }
49 |
50 | public static void setLookAndFeel() {
51 | try {
52 | String laf = Config.getConfig().getLaF();
53 | if (laf == null) {
54 | UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
55 | } else {
56 | UIManager.setLookAndFeel(laf);
57 | }
58 | } catch (Exception e) {
59 | Logger.getLogger().log(Logger.Level.DEBUG, e);
60 | }
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/plugins/FileSelectorArrayPanel.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.plugins;
2 |
3 | import javax.swing.JLabel;
4 | import javax.swing.JPanel;
5 | import javax.swing.JTextField;
6 | import java.awt.GridBagConstraints;
7 | import java.awt.GridBagLayout;
8 | import java.util.LinkedList;
9 | import java.util.List;
10 |
11 | public class FileSelectorArrayPanel extends JPanel {
12 |
13 | private final JLabel jLabel;
14 | private final FileSelectorArrayAddRow fileSelectorArrayAddRow;
15 |
16 | private final GridBagConstraints gbc;
17 | private List pathTextFields;
18 |
19 | private Boolean first = false;
20 |
21 | FileSelectorArrayPanel(String label) {
22 | gbc = new GridBagConstraints();
23 | this.setLayout(new GridBagLayout());
24 | pathTextFields = new LinkedList<>();
25 | gbc.anchor = GridBagConstraints.NORTHWEST;
26 | gbc.fill = GridBagConstraints.BOTH;
27 | gbc.weightx = 1;
28 | gbc.gridx = 0;
29 | gbc.gridy = 0;
30 |
31 | // Always have at least one row.
32 | FileSelectorArrayRow row = addRow("", false);
33 | first = true;
34 |
35 | jLabel = new JLabel(label);
36 | fileSelectorArrayAddRow = new FileSelectorArrayAddRow(row.getRightBoundMargin());
37 | fileSelectorArrayAddRow.getAddButton().addActionListener(actionEvent -> {
38 | addRow("", true);
39 | });
40 |
41 | this.add(jLabel, gbc);
42 | gbc.gridy = 10000;
43 | this.add(fileSelectorArrayAddRow, gbc);
44 | gbc.gridy = 1;
45 | }
46 |
47 | FileSelectorArrayRow addRow(String url, boolean button) {
48 | // Fill first row created by constructor.
49 | if (first) {
50 | if (!button) {
51 | first = false;
52 | pathTextFields.get(0).setText(url);
53 | return null;
54 | }
55 | }
56 | gbc.gridy++;
57 | FileSelectorArrayRow fileSelectorArrayRow = new FileSelectorArrayRow(this, url);
58 | pathTextFields.add(fileSelectorArrayRow.getTextField());
59 | this.add(fileSelectorArrayRow, gbc);
60 | this.revalidate();
61 |
62 | return fileSelectorArrayRow;
63 | }
64 |
65 | public void removeRow(FileSelectorArrayRow fileSelectorArrayRow) {
66 | if (pathTextFields.size() > 1) {
67 | pathTextFields.remove(fileSelectorArrayRow.getTextField());
68 | this.remove(fileSelectorArrayRow);
69 | this.revalidate();
70 | }
71 | }
72 |
73 | public List getStringList() {
74 | List list = new LinkedList<>();
75 | for (JTextField jTextField : pathTextFields) {
76 | list.add(jTextField.getText());
77 | }
78 | return list;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/settings/ChangeReporter.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.settings;
2 |
3 | import javax.swing.JList;
4 | import javax.swing.JToggleButton;
5 | import javax.swing.event.DocumentEvent;
6 | import javax.swing.event.DocumentListener;
7 | import javax.swing.event.ListDataEvent;
8 | import javax.swing.event.ListDataListener;
9 | import javax.swing.text.JTextComponent;
10 | import java.awt.event.ActionEvent;
11 | import java.awt.event.ActionListener;
12 |
13 | public interface ChangeReporter {
14 |
15 | /**
16 | * Passes a listener to the implementing class to allow for future reporting.
17 | * @param listener the change listener
18 | */
19 | void setChangeReporter(ActionListener listener);
20 |
21 | /**
22 | * Convenience method to make a document change listener perform an action on the listener parameter.
23 | * @param listener the listener which will be triggered
24 | * @param textComponent the component whose document will trigger an event
25 | */
26 | static void addTextChangeListener(ActionListener listener, JTextComponent textComponent) {
27 | textComponent.getDocument().addDocumentListener(new DocumentListener() {
28 | @Override
29 | public void insertUpdate(DocumentEvent documentEvent) {
30 | changedUpdate(documentEvent);
31 | }
32 |
33 | @Override
34 | public void removeUpdate(DocumentEvent documentEvent) {
35 | changedUpdate(documentEvent);
36 | }
37 |
38 | @Override
39 | public void changedUpdate(DocumentEvent documentEvent) {
40 | listener.actionPerformed(createChangeActionEvent(textComponent));
41 | }
42 | });
43 | }
44 |
45 | static void addCheckboxListener(ActionListener listener, JToggleButton checkBox) {
46 | checkBox.addActionListener(checked -> listener.actionPerformed(createChangeActionEvent(checkBox)));
47 | }
48 |
49 | static void addJListListener(ActionListener listener, JList list) {
50 | list.getModel().addListDataListener(new ListDataListener() {
51 | @Override
52 | public void intervalAdded(ListDataEvent listDataEvent) {
53 | contentsChanged(listDataEvent);
54 | }
55 |
56 | @Override
57 | public void intervalRemoved(ListDataEvent listDataEvent) {
58 | contentsChanged(listDataEvent);
59 | }
60 |
61 | @Override
62 | public void contentsChanged(ListDataEvent listDataEvent) {
63 | listener.actionPerformed(createChangeActionEvent(list));
64 | }
65 | });
66 | }
67 |
68 | static ActionEvent createChangeActionEvent(Object source) {
69 | return new ActionEvent(source, 0, "changed");
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/core/AgentAttachManager.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.core;
2 |
3 | import org.jrd.backend.communication.CallDecompilerAgent;
4 | import org.jrd.backend.core.agentstore.KnownAgent;
5 | import org.jrd.backend.core.agentstore.KnownAgents;
6 | import org.jrd.backend.data.VmManager;
7 | import org.jrd.backend.data.cli.utils.AgentConfig;
8 |
9 | import java.util.List;
10 |
11 | /**
12 | * Attach manager for agent contains utility methods and information about
13 | * attach.
14 | */
15 | public class AgentAttachManager {
16 |
17 | private AgentLoader loader;
18 | private VmManager vmManager;
19 |
20 | public AgentAttachManager(VmManager vmManager) {
21 | this.vmManager = vmManager;
22 | this.loader = new AgentLoader();
23 | }
24 |
25 | public VmDecompilerStatus attachAgentToVm(String vmId, int vmPid, AgentConfig agntConfig) {
26 | List knownAgentsOnPid = KnownAgents.getInstance().findAgents(vmPid);
27 | if (knownAgentsOnPid.size() > 0) {
28 | if (knownAgentsOnPid.size() > 1) {
29 | Logger.getLogger().log(
30 | Logger.Level.DEBUG,
31 | "warning, but more then one agent found " + vmId + " Taking " + "first one - " + knownAgentsOnPid.get(0).toString()
32 | );
33 | }
34 | Logger.getLogger().log("reusing " + knownAgentsOnPid.get(0).toString());
35 | VmDecompilerStatus status = new VmDecompilerStatus(true);
36 | status.setHostname(knownAgentsOnPid.get(0).getHost());
37 | status.setListenPort(knownAgentsOnPid.get(0).getPort());
38 | status.setVmId(vmId);
39 | status.setBytemanCompanion(knownAgentsOnPid.get(0).getBytemanCompanion());
40 | vmManager.getVmInfoByID(vmId).replaceVmDecompilerStatus(status);
41 | return status;
42 | } else {
43 | Logger.getLogger().log(Logger.Level.DEBUG, "Attaching agent to VM '" + vmPid + "'");
44 | int attachedPort = AgentLoader.INVALID_PORT;
45 | try {
46 | attachedPort = loader.attach(vmPid, agntConfig);
47 | } catch (Exception ex) {
48 | Logger.getLogger().log(Logger.Level.ALL, ex);
49 | }
50 | if (attachedPort == AgentLoader.INVALID_PORT) {
51 | Logger.getLogger().log(Logger.Level.DEBUG, "Failed to attach agent for VM '" + vmPid);
52 | return null;
53 | }
54 | VmDecompilerStatus status = new VmDecompilerStatus();
55 | status.setHostname(CallDecompilerAgent.DEFAULT_ADDRESS);
56 | status.setListenPort(attachedPort);
57 | status.setVmId(vmId);
58 | vmManager.getVmInfoByID(vmId).replaceVmDecompilerStatus(status);
59 | return status;
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/kcc/KeywordBasedCodeCompletionMain.java:
--------------------------------------------------------------------------------
1 | package org.kcc;
2 |
3 | import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
4 | import org.kcc.wordsets.BytecodeKeywordsWithHelp;
5 | import org.kcc.wordsets.ConnectedKeywords;
6 | import org.kcc.wordsets.JavaKeywordsWithHelp;
7 | import org.kcc.wordsets.JrdApiKeywords;
8 |
9 | import javax.swing.JButton;
10 | import javax.swing.JFrame;
11 | import javax.swing.JLabel;
12 | import javax.swing.SwingUtilities;
13 | import javax.swing.WindowConstants;
14 | import java.awt.BorderLayout;
15 | import java.awt.event.ActionEvent;
16 | import java.awt.event.ActionListener;
17 | import java.awt.event.WindowAdapter;
18 | import java.awt.event.WindowEvent;
19 |
20 | public final class KeywordBasedCodeCompletionMain {
21 |
22 | private KeywordBasedCodeCompletionMain() {
23 | }
24 |
25 | /**
26 | * Experiemntal main method showing as demo for KeywordBasedCodeCompletion;
27 | * move from mainX to main once moved to separeate project
28 | * @param args
29 | * @throws Exception
30 | */
31 | public static void mainX(String[] args) throws Exception {
32 | SwingUtilities.invokeLater(new Runnable() {
33 | @Override
34 | public void run() {
35 | JFrame frame = new JFrame("keyword based code completion example");
36 | JLabel l1;
37 | JButton b1;
38 | //JTextArea t1;
39 | RSyntaxTextArea t1;
40 | frame.setLayout(new BorderLayout());
41 | l1 = new JLabel("hi");
42 | b1 = new JButton("by");
43 | t1 = new RSyntaxTextArea();
44 | frame.add(l1, BorderLayout.NORTH);
45 | frame.add(b1, BorderLayout.SOUTH);
46 | frame.add(t1);
47 | final KeywordBasedCodeCompletion comp = new KeywordBasedCodeCompletion(
48 | t1, new CompletionSettings(new BytecodeKeywordsWithHelp(), CompletionSettings.OP.STARTS, true, true)
49 | );
50 | b1.addActionListener(new ActionListener() {
51 | @Override
52 | public void actionPerformed(ActionEvent actionEvent) {
53 | comp.setCompletionsSet(
54 | new ConnectedKeywords(new BytecodeKeywordsWithHelp(), new JavaKeywordsWithHelp(), new JrdApiKeywords())
55 | );
56 | }
57 | });
58 | frame.addWindowListener(new WindowAdapter() {
59 | @Override
60 | public void windowClosed(WindowEvent e) {
61 | comp.dispose();
62 | }
63 | });
64 | frame.setSize(550, 400);
65 | frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
66 | frame.setVisible(true);
67 |
68 | }
69 | });
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/data/cli/InMemoryJar.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data.cli;
2 |
3 | import java.io.ByteArrayOutputStream;
4 | import java.io.File;
5 | import java.io.IOException;
6 | import java.io.OutputStream;
7 | import java.nio.file.Files;
8 | import java.util.Date;
9 | import java.util.jar.Attributes;
10 | import java.util.jar.JarEntry;
11 | import java.util.jar.JarOutputStream;
12 | import java.util.jar.Manifest;
13 |
14 | public class InMemoryJar {
15 | private Manifest manifest = new Manifest();
16 | ByteArrayOutputStream bos;
17 | JarOutputStream target;
18 |
19 | public InMemoryJar() {
20 | startManifest();
21 | }
22 |
23 | public void startManifest() {
24 | manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
25 | addToManifest("Can-Redefine-Classes", "true");
26 | }
27 |
28 | public void setMainClass(String mainFqn) {
29 | if (mainFqn != null && !"".equals(mainFqn)) {
30 | addToManifest(Attributes.Name.MAIN_CLASS.toString(), mainFqn);
31 | }
32 | }
33 |
34 | public void addToManifest(String key, String value) {
35 | manifest.getMainAttributes().put(new Attributes.Name(key), value);
36 | }
37 |
38 | public JarOutputStream openJar(OutputStream os) throws IOException {
39 | return new JarOutputStream(os, manifest);
40 | }
41 |
42 | private static void addFile(JarOutputStream target, byte[] body, String fqn) throws IOException {
43 | String name = fqn.replace('.', '/') + ".class";
44 | JarEntry entry = new JarEntry(name);
45 | entry.setTime(new Date().getTime());
46 | target.putNextEntry(entry);
47 | target.write(body);
48 | target.closeEntry();
49 | }
50 |
51 | public void addFile(byte[] body, String fqn) throws IOException {
52 | if (target == null) {
53 | open();
54 | }
55 | InMemoryJar.addFile(target, body, fqn);
56 | }
57 |
58 | public void open() throws IOException {
59 | bos = new ByteArrayOutputStream();
60 | target = this.openJar(bos);
61 | }
62 |
63 | public void close() throws IOException {
64 | if (target != null) {
65 | target.flush();
66 | target.close();
67 | target = null;
68 | }
69 | }
70 |
71 | public File save() throws IOException {
72 | File f = File.createTempFile("jrd", "test.zip");
73 | f.deleteOnExit();
74 | save(f);
75 | return f;
76 | }
77 |
78 | public void save(File f) throws IOException {
79 | if (target != null) {
80 | throw new RuntimeException("Not closed!");
81 | }
82 | Files.write(f.toPath(), bos.toByteArray());
83 | }
84 |
85 | public byte[] toBytes() throws IOException {
86 | if (target != null) {
87 | throw new RuntimeException("Not closed!");
88 | }
89 | return bos.toByteArray();
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/test/java/org/jrd/backend/data/cli/InMemoryJarTest.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.data.cli;
2 |
3 | import org.junit.jupiter.api.Assertions;
4 | import org.junit.jupiter.api.Test;
5 |
6 | import java.io.ByteArrayInputStream;
7 | import java.io.ByteArrayOutputStream;
8 | import java.io.File;
9 | import java.io.IOException;
10 | import java.util.Enumeration;
11 | import java.util.jar.JarEntry;
12 | import java.util.jar.JarFile;
13 | import java.util.jar.JarInputStream;
14 | import java.util.zip.ZipEntry;
15 |
16 | public class InMemoryJarTest {
17 |
18 | @Test
19 | public void testJarFile() throws IOException {
20 | InMemoryJar jar = new InMemoryJar();
21 | jar.addFile(new byte[]{0, 1, 2}, "my.clazz");
22 | jar.close();
23 | File f = jar.save();
24 | JarFile jf = new JarFile(f);
25 | boolean one = false;
26 | boolean second = false;
27 | int c = 0;
28 | for (Enumeration list = jf.entries(); list.hasMoreElements();) {
29 | c++;
30 | ZipEntry entry = (ZipEntry) list.nextElement();
31 | if (entry.getName().equals("my/clazz.class")) {
32 | one = true;
33 | Assertions.assertEquals(3, entry.getSize());
34 | }
35 | if (entry.getName().equals("META-INF/MANIFEST.MF")) {
36 | second = true;
37 | Assertions.assertTrue(entry.getSize() > 10);
38 | }
39 | }
40 | jf.close();
41 | Assertions.assertTrue(one);
42 | Assertions.assertTrue(second);
43 | Assertions.assertEquals(2, c);
44 | }
45 |
46 | @Test
47 | public void testJarStream() throws IOException {
48 | InMemoryJar jar = new InMemoryJar();
49 | jar.addFile(new byte[]{0, 1, 2}, "my.clazz");
50 | jar.close();
51 | JarInputStream jf = new JarInputStream(new ByteArrayInputStream(jar.toBytes()));
52 | boolean one = false;
53 | boolean second = false;
54 | int c = 0;
55 | JarEntry entry;
56 | while ((entry = jf.getNextJarEntry()) != null) {
57 | c++;
58 | if (entry.getName().equals("my/clazz.class")) {
59 | one = true;
60 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
61 | while (true) {
62 | int qwe = jf.read();
63 | if (qwe == -1) {
64 | break;
65 | }
66 | baos.write(qwe);
67 | }
68 | Assertions.assertEquals(3, entry.getSize());
69 | }
70 | if (entry.getName().equals("META-INF/MANIFEST.MF")) {
71 | second = true;
72 | Assertions.assertTrue(entry.getSize() > 10);
73 | }
74 | }
75 | jf.close();
76 | Assertions.assertTrue(one);
77 | Assertions.assertFalse(second);
78 | Assertions.assertEquals(1, c);
79 | //unable to read manifest:(
80 | //unable to verify if it is here...
81 | //obviously is, see file
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/.github/workflows/maven.yaml:
--------------------------------------------------------------------------------
1 | name: Java CI
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | pull_request:
8 | branches:
9 | - master
10 | workflow_dispatch:
11 |
12 | jobs:
13 | build:
14 | runs-on: ${{ matrix.os }}
15 |
16 | strategy:
17 | matrix:
18 | os: [ubuntu-latest]
19 | java-version: [ 21, 25 ]
20 | fail-fast: false
21 |
22 | name: ${{ matrix.os }} - Java ${{ matrix.java-version }} - Maven
23 | steps:
24 | - name: Checkout JRD repo
25 | uses: actions/checkout@v2
26 |
27 | - name: Set up JDK ${{ matrix.java-version }}
28 | uses: actions/setup-java@v2
29 | with:
30 | java-version: ${{ matrix.java-version }}
31 | distribution: 'temurin'
32 |
33 | - name: java version
34 | run: java -version
35 |
36 | - name: clone and build procyon devel we depeond on Linux
37 | if: matrix.os == 'ubuntu-latest'
38 | run: |
39 | set -ex
40 | git checkout runtime-decompiler/src/main/java/org/kcc/wordsets/JrdApiKeywords.java
41 | mvn -batch-mode dependency:resolve || echo "this is expected to fail, hoefully all necessary parts for plugins build were downloaded"
42 | bash runtime-decompiler/plugins-build.sh
43 | shell: bash
44 |
45 | - name: Build JRD with Maven
46 | run: |
47 | set -ex
48 | git checkout runtime-decompiler/src/main/java/org/kcc/wordsets/JrdApiKeywords.java
49 | mvn --batch-mode --update-snapshots clean install
50 |
51 | - name: Create and populate config file on Linux
52 | if: matrix.os == 'ubuntu-latest'
53 | run: |
54 | set -ex
55 | CONFIG_HOME="$HOME/.config/java-runtime-decompiler/conf"
56 | mkdir -p -v "$CONFIG_HOME"
57 | AGENT_PATH=$(find "${{ github.workspace }}" -name "decompiler-agent-*.jar" | head -n 1)
58 | echo "{\"AGENT_PATH\":\"${AGENT_PATH}\"}" > "$CONFIG_HOME/config.json"
59 | cat "$CONFIG_HOME/config.json"
60 | shell: bash
61 |
62 | - name: Test Cli
63 | timeout-minutes: 10
64 | run: |
65 | set -e
66 | cd runtime-decompiler
67 | for x in `find -type f | grep src/test/java | sed "s;.*/;;"` ; do
68 | git checkout ../runtime-decompiler/src/main/java/org/kcc/wordsets/JrdApiKeywords.java ;
69 | echo started $x
70 | mvn --batch-mode test -Dtest="**/*$x" -DfailIfNoTests=false "-Dsurefire.reportFormat=plain"
71 | echo finished $x ;
72 | done
73 | git checkout ../runtime-decompiler/src/main/java/org/kcc/wordsets/JrdApiKeywords.java # this was broken by previous mvn run
74 | mvn --batch-mode test -Dtest=*CliTest -DfailIfNoTests=false "-Dsurefire.reportFormat=plain" # run the most important one more times to keep report
75 |
76 | - name: try image
77 | timeout-minutes: 10
78 | run: |
79 | set -e
80 | git checkout runtime-decompiler/src/main/java/org/kcc/wordsets/JrdApiKeywords.java && mvn clean install -DskipTests -Pimages -Plegacy
81 |
82 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/settings/AgentSettingsPanel.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.settings;
2 |
3 | import javax.swing.JButton;
4 | import javax.swing.JFileChooser;
5 | import javax.swing.JLabel;
6 | import javax.swing.JPanel;
7 | import javax.swing.JTextField;
8 | import java.awt.GridBagConstraints;
9 | import java.awt.GridBagLayout;
10 | import java.awt.Insets;
11 | import java.awt.event.ActionListener;
12 | import java.io.File;
13 | import org.jrd.backend.data.Directories;
14 | import org.jrd.frontend.frame.main.decompilerview.BytecodeDecompilerView;
15 | import org.jrd.frontend.frame.plugins.FileSelectorArrayRow;
16 |
17 | public class AgentSettingsPanel extends JPanel implements ChangeReporter {
18 |
19 | private JTextField agentPathTextField;
20 | private JLabel agentPathLabel;
21 | private JButton browseButton;
22 | private JFileChooser chooser;
23 |
24 | AgentSettingsPanel(String initialAgentPath) {
25 | this.setName("Agent settings");
26 | agentPathTextField = new JTextField();
27 | agentPathTextField.setToolTipText(
28 | BytecodeDecompilerView.styleTooltip() + "Select a path to the Decompiler Agent.
" +
29 | FileSelectorArrayRow.getTextFieldToolTip()
30 | );
31 | agentPathTextField.setText(initialAgentPath);
32 |
33 | agentPathLabel = new JLabel("Decompiler Agent path");
34 | browseButton = new JButton("Browse");
35 |
36 | chooser = new JFileChooser();
37 | File dir;
38 | if (Directories.isPortable()) {
39 | dir = new File(Directories.getJrdLocation() + File.separator + "libs");
40 | } else {
41 | dir = new File(Directories.getJrdLocation() + File.separator + "decompiler_agent" + File.separator + "target");
42 | }
43 | chooser.setCurrentDirectory(FileSelectorArrayRow.fallback(dir));
44 |
45 | browseButton.addActionListener(actionEvent -> {
46 | int dialogResult = chooser.showOpenDialog(null);
47 | if (dialogResult == JFileChooser.APPROVE_OPTION) {
48 | agentPathTextField.setText(chooser.getSelectedFile().getPath());
49 | }
50 | });
51 |
52 | this.setLayout(new GridBagLayout());
53 | GridBagConstraints gbc = new GridBagConstraints();
54 | gbc.anchor = GridBagConstraints.WEST;
55 | gbc.fill = GridBagConstraints.BOTH;
56 | gbc.insets = new Insets(5, 5, 5, 5);
57 |
58 | this.add(this.agentPathLabel, gbc);
59 |
60 | gbc.weightx = 1;
61 | gbc.gridy = 1;
62 | gbc.gridwidth = 2;
63 | this.add(agentPathTextField, gbc);
64 |
65 | gbc.weightx = 0;
66 | gbc.gridwidth = 1;
67 | gbc.gridx = 2;
68 | browseButton.setPreferredSize(BytecodeDecompilerView.buttonSizeBasedOnTextField(browseButton, agentPathTextField));
69 | this.add(browseButton, gbc);
70 | }
71 |
72 | public String getAgentPath() {
73 | return agentPathTextField.getText();
74 | }
75 |
76 | @Override
77 | public void setChangeReporter(ActionListener listener) {
78 | ChangeReporter.addTextChangeListener(listener, agentPathTextField);
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/fife/ui/hex/swing/HexEditorTransferHandler.java:
--------------------------------------------------------------------------------
1 | //
2 | // Decompiled by Procyon v0.5.36
3 | //
4 |
5 | package org.fife.ui.hex.swing;
6 |
7 | import javax.swing.JComponent;
8 | import javax.swing.TransferHandler;
9 | import java.awt.datatransfer.DataFlavor;
10 | import java.awt.datatransfer.Transferable;
11 | import java.awt.datatransfer.UnsupportedFlavorException;
12 | import java.io.IOException;
13 | import java.nio.charset.StandardCharsets;
14 |
15 | class HexEditorTransferHandler extends TransferHandler {
16 | private static final long serialVersionUID = 1L;
17 |
18 | @Override
19 | public boolean canImport(final JComponent comp, final DataFlavor[] flavors) {
20 | final HexEditor editor = (HexEditor) comp;
21 | return editor.isEnabled() && this.getImportFlavor(flavors, editor) != null;
22 | }
23 |
24 | @Override
25 | protected Transferable createTransferable(final JComponent c) {
26 | final HexEditor e = (HexEditor) c;
27 | final int start = e.getSmallestSelectionIndex();
28 | final int end = e.getLargestSelectionIndex();
29 | final byte[] array = new byte[end - start + 1];
30 | for (int i = end; i >= start; --i) {
31 | array[i - start] = e.getByte(i);
32 | }
33 | final ByteArrayTransferable bat = new ByteArrayTransferable(start, array);
34 | return bat;
35 | }
36 |
37 | @Override
38 | protected void exportDone(final JComponent source, final Transferable data, final int action) {
39 | if (action == 2) {
40 | final ByteArrayTransferable bat = (ByteArrayTransferable) data;
41 | final int offs = bat.getOffset();
42 | final HexEditor e = (HexEditor) source;
43 | e.removeBytes(offs, bat.getLength());
44 | }
45 | }
46 |
47 | private DataFlavor getImportFlavor(final DataFlavor[] flavors, final HexEditor e) {
48 | for (int i = 0; i < flavors.length; ++i) {
49 | if (flavors[i].equals(DataFlavor.stringFlavor)) {
50 | return flavors[i];
51 | }
52 | }
53 | return null;
54 | }
55 |
56 | @Override
57 | public int getSourceActions(final JComponent c) {
58 | final HexEditor e = (HexEditor) c;
59 | return e.isEnabled() ? 3 : 1;
60 | }
61 |
62 | @Override
63 | public boolean importData(final JComponent c, final Transferable t) {
64 | final HexEditor e = (HexEditor) c;
65 | final boolean imported = false;
66 | final DataFlavor flavor = this.getImportFlavor(t.getTransferDataFlavors(), e);
67 | if (flavor != null) {
68 | try {
69 | final Object data = t.getTransferData(flavor);
70 | if (flavor.equals(DataFlavor.stringFlavor)) {
71 | final String text = (String) data;
72 | final byte[] bytes = text.getBytes(StandardCharsets.UTF_8);
73 | e.replaceSelection(bytes);
74 | }
75 | } catch (UnsupportedFlavorException ufe) {
76 | ufe.printStackTrace();
77 | } catch (IOException ioe) {
78 | ioe.printStackTrace();
79 | }
80 | }
81 | return imported;
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/images/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 |
6 | java-runtime-decompiler
7 | java-runtime-decompiler
8 | ${jrd.version}
9 | ../
10 |
11 |
12 | java-runtime-decompiler-images
13 | Images
14 | Helper to create release images
15 | pom
16 |
17 |
18 | ${project.parent.basedir}
19 |
20 |
21 |
22 |
23 | java-runtime-decompiler
24 | runtime-decompiler
25 | ${jrd.version}
26 |
27 |
28 | java-runtime-decompiler
29 | decompiler-agent
30 | ${jrd.version}
31 |
32 |
33 |
34 |
35 |
36 | images
37 |
38 |
39 |
40 | exec-maven-plugin
41 | org.codehaus.mojo
42 | 1.6.0
43 |
44 |
45 | build-image
46 | install
47 |
48 | exec
49 |
50 |
51 | bash
52 | ${basedir}/image.sh ${project.version}
53 | ${basedir}/build.log
54 |
55 |
56 |
57 | clean-image
58 | clean
59 |
60 | exec
61 |
62 |
63 | rm
64 | -rvf ${basedir}/target
65 | ${basedir}/build.log
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/kcc/CompletionItem.java:
--------------------------------------------------------------------------------
1 | package org.kcc;
2 |
3 | import java.util.List;
4 | import java.util.Objects;
5 | import java.util.regex.Pattern;
6 |
7 | public class CompletionItem implements Comparable {
8 |
9 | public interface CompletionItemSet {
10 |
11 | CompletionItem[] getItemsArray();
12 |
13 | List getItemsList();
14 |
15 | Pattern getRecommendedDelimiterSet();
16 |
17 | static Pattern delimiterSet() {
18 | return Pattern.compile("[a-zA-Z0-9_\\-\\.\\(\\)]");
19 | }
20 |
21 | static Pattern delimiterStrictSet2() {
22 | return Pattern.compile("[a-zA-Z0-9\\.]");
23 | }
24 |
25 | static Pattern delimiterStrictSet3() {
26 | return Pattern.compile("[a-zA-Z0-9_\\.]");
27 | }
28 |
29 | static Pattern delimiterWordSet() {
30 | return Pattern.compile("[a-zA-Z]");
31 | }
32 |
33 | static Pattern delimiterWordAndNumberSet() {
34 | return Pattern.compile("[a-zA-Z0-9]");
35 | }
36 | }
37 |
38 | private final String key;
39 | private final String description;
40 | private final String realReplacement;
41 | private final String searchable;
42 |
43 | public CompletionItem(String key) {
44 | this(key, "", "");
45 | }
46 |
47 | public CompletionItem(String key, String description) {
48 | this(key, description, "");
49 | }
50 |
51 | public CompletionItem(String key, String description, String realReplacement) {
52 | this(key, description, realReplacement, key);
53 | }
54 |
55 | public CompletionItem(String key, String description, String realReplacement, String searchable) {
56 | this.key = key;
57 | this.description = description;
58 | this.realReplacement = realReplacement;
59 | this.searchable = searchable;
60 | }
61 |
62 | @Override
63 | public String toString() {
64 | return key;
65 | }
66 |
67 | public String getKey() {
68 | return key;
69 | }
70 |
71 | public String getSearchable() {
72 | if ("".equals(searchable)) {
73 | return key;
74 | } else {
75 | return searchable;
76 | }
77 | }
78 |
79 | public String getDescription() {
80 | return description;
81 | }
82 |
83 | public String getRealReplacement() {
84 | if (realReplacement.isEmpty()) {
85 | return key;
86 | } else {
87 | return realReplacement;
88 | }
89 | }
90 |
91 | @Override
92 | public int compareTo(CompletionItem o) {
93 | if (o == null) {
94 | return 1;
95 | }
96 | return this.getKey().compareTo(o.getKey());
97 | }
98 |
99 | @Override
100 | public boolean equals(Object o) {
101 | if (this == o) {
102 | return true;
103 | }
104 | if (o == null || getClass() != o.getClass()) {
105 | return false;
106 | }
107 | CompletionItem that = (CompletionItem) o;
108 | return key.equals(that.key);
109 | }
110 |
111 | @Override
112 | public int hashCode() {
113 | return Objects.hash(key);
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/main/decompilerview/dummycompiler/templates/Jasm2TemplateMenuItem.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.main.decompilerview.dummycompiler.templates;
2 |
3 | import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
4 |
5 | import java.awt.event.ActionEvent;
6 | import java.awt.event.ActionListener;
7 |
8 | import javax.swing.JMenuItem;
9 |
10 | public class Jasm2TemplateMenuItem extends JMenuItem {
11 | public Jasm2TemplateMenuItem(final RSyntaxTextArea source) {
12 | super("jasm swing hello with dependence example");
13 | this.addActionListener(new ActionListener() {
14 | @Override
15 | public void actionPerformed(ActionEvent actionEvent) {
16 | source.append(
17 | "package jrd/template;\n" + "\n" + "super public class HelloJasm\n" + "\tversion 52:0\n" + "{\n" +
18 | " public Method \"\":\"()V\"\n" + "\tstack 1 locals 1\n" + " {\n" + "\t\taload_0;\n" +
19 | "\t\tinvokespecial\tMethod java/lang/Object.\"\":\"()V\";\n" + "\t\treturn;\n" + " }\n" +
20 | " public static Method start:\"()V\"\n" + "\tstack 2 locals 0\n" + " {\n" +
21 | "\t\tgetstatic\tField java/lang/System.out:\"Ljava/io/PrintStream;\";\n" +
22 | "\t\tldc\tString \"Hello from jasm! See terminal!\";\n" +
23 | "\t\tinvokevirtual\tMethod java/io/PrintStream.println:\"(Ljava/lang/String;)V\";\n" +
24 | "\t\t//invokestatic\tMethod showJrdAbout:\"()V\";\n" +
25 | "\t\t//invokestatic\tMethod dunmpAgentVars:\"()V\";\n" +
26 | "\t\tgetstatic\tField java/lang/System.out:\"Ljava/io/PrintStream;\";\n" + "\t\tldc\tString \"done\";\n" +
27 | "\t\tinvokevirtual\tMethod java/io/PrintStream.println:\"(Ljava/lang/String;)V\";\n" + "\t\treturn;\n" +
28 | " }\n" + " public static varargs Method main:\"([Ljava/lang/String;)V\"\n" + "\tstack 0 locals 1\n" +
29 | " {\n" + "\t\tinvokestatic\tMethod start:\"()V\";\n" + "\t\treturn;\n" + " }\n" +
30 | " public static Method showJrdAbout:\"()V\"\n" + "\tstack 4 locals 0\n" + " {\n" +
31 | "\t\tnew\tclass org/jrd/frontend/frame/about/AboutView;\n" + "\t\tdup;\n" + "\t\taconst_null;\n" +
32 | "\t\ticonst_0;\n" + "\t\tinvokespecial\t" +
33 | "Method org/jrd/frontend/frame/about/AboutView.\"\":\"(Ljavax/swing/JFrame;Z)V\";\n" +
34 | "\t\ticonst_1;\n" +
35 | "\t\tinvokevirtual\tMethod org/jrd/frontend/frame/about/AboutView.setVisible:\"(Z)V\";\n" +
36 | "\t\treturn;\n" + " }\n" + " public static Method dunmpAgentVars:\"()V\"\n" + "\tstack 1 locals 0\n" +
37 | " {\n" + "\t\tinvokestatic\tMethod org/jrd/agent/api/Variables.dumpAll:\"()Ljava/lang/String;\";\n" +
38 | "\t\tpop;\n" + "\t\treturn;\n" + " }\n" + "\n" + "} // end Class HelloJasm\n"
39 | );
40 | }
41 | });
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/decompiler_agent/src/main/java/org/jrd/agent/api/ClassClassLoaderMap.java:
--------------------------------------------------------------------------------
1 | package org.jrd.agent.api;
2 |
3 | import java.util.ArrayList;
4 | import java.util.HashMap;
5 | import java.util.List;
6 | import java.util.Map;
7 | import java.util.stream.Collectors;
8 |
9 | public class ClassClassLoaderMap {
10 | // class->classlaoder->byte[]
11 | private Map> map = new HashMap<>();
12 |
13 | public void reset() {
14 | map = new HashMap<>();
15 | }
16 |
17 | public void remove(String clazz) {
18 | map.remove(clazz);
19 | }
20 |
21 | public void remove(String clazz, String classloader) {
22 | Map submap = map.get(clazz);
23 | if (submap == null) {
24 | //FIXME is this correct?
25 | return;
26 | }
27 | submap.remove(classloader);
28 | if (submap.isEmpty()) {
29 | map.remove(clazz);
30 | }
31 | }
32 |
33 | public byte[] get(String classname) {
34 | Map classes = map.get(classname);
35 | if (classes == null || classes.isEmpty()) {
36 | return null;
37 | }
38 | byte[] nullLoader = classes.get(null);
39 | if (nullLoader != null) {
40 | return nullLoader;
41 | }
42 | return new ArrayList(classes.values()).get(0);
43 | }
44 |
45 | public byte[] get(String classname, String classlaoder) {
46 | Map classes = map.get(classname);
47 | if (classes == null || classes.isEmpty()) {
48 | return null;
49 | }
50 | byte[] targettedReturn = classes.get(classlaoder);
51 | if (targettedReturn == null && !classes.isEmpty()) {
52 | return new ArrayList<>(classes.values()).get(0);
53 | } else {
54 | return targettedReturn;
55 | }
56 | }
57 |
58 | public byte[] getStrict(String classname, String classlaoder) {
59 | Map classes = map.get(classname);
60 | if (classes == null || classes.isEmpty()) {
61 | return null;
62 | }
63 | return classes.get(classlaoder);
64 | }
65 |
66 | public void put(String nameWithoutSlashes, byte[] classfileBuffer, String loader) {
67 | Map classes = map.get(nameWithoutSlashes);
68 | if (classes == null) {
69 | classes = new HashMap<>();
70 | map.put(nameWithoutSlashes, classes);
71 | }
72 | classes.put(loader, classfileBuffer);
73 | }
74 |
75 | public List keySet() {
76 | return keySetPairs().stream().map(a -> a[0] + ":" + a[1]).collect(Collectors.toList());
77 | }
78 |
79 | public List keySetPairs() {
80 | List r = new ArrayList<>();
81 | for (Map.Entry> fqn : map.entrySet()) {
82 | for (String classloader : fqn.getValue().keySet()) {
83 | r.add(new String[]{fqn.getKey(), nullClassloaderToUnknown(classloader)});
84 | }
85 | }
86 | return r;
87 | }
88 |
89 | public static String nullClassloaderToUnknown(String classloader) {
90 | return classloader == null ? "unknown" : classloader;
91 | }
92 |
93 | public static String unknownToNullClasslaoder(String unknown) {
94 | return "unknown".equals(unknown) ? null : unknown;
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/backend/core/AgentLoader.java:
--------------------------------------------------------------------------------
1 | package org.jrd.backend.core;
2 |
3 | import com.sun.tools.attach.AgentInitializationException;
4 | import com.sun.tools.attach.AgentLoadException;
5 | import com.sun.tools.attach.AttachNotSupportedException;
6 |
7 | import org.jrd.backend.communication.CallDecompilerAgent;
8 | import org.jrd.backend.communication.InstallDecompilerAgentImpl;
9 | import org.jrd.backend.data.cli.utils.AgentConfig;
10 |
11 | import java.io.IOException;
12 | import java.net.ServerSocket;
13 | import java.util.ArrayList;
14 | import java.util.List;
15 |
16 | /**
17 | * This class contains methods for attaching the agent.
18 | */
19 | public class AgentLoader {
20 |
21 | static final int INVALID_PORT = -1;
22 | private static final int PORT_MIN = 10900;
23 | private static final int MAX_PORT_SLOTS = 200;
24 | private static final int PORT_MAX = PORT_MIN + MAX_PORT_SLOTS;
25 |
26 | private static final String AGENT_PORT_PROPERTY = "com.redhat.decompiler.thermostat.port";
27 |
28 | AgentLoader() {
29 | }
30 |
31 | /**
32 | * This method handles the attachment of a decompiler agent to given VM.
33 | *
34 | * @param pid PID of the VM
35 | * @return port number if successful, else {@link #INVALID_PORT}
36 | */
37 | public int attach(int pid, AgentConfig aconf) {
38 | return attachImpl(pid, aconf);
39 | }
40 |
41 | public static int attachImpl(int pid, AgentConfig aconf) {
42 | int port = aconf.getPort().orElse(findPort());
43 | String[] installProps = createProperties(port);
44 |
45 | Logger.getLogger().log(Logger.Level.DEBUG, "Attempting to attach decompiler agent for VM '" + pid + "' on port '" + port + "'");
46 |
47 | try {
48 | InstallDecompilerAgentImpl.install(
49 | Integer.toString(pid), false, false, CallDecompilerAgent.DEFAULT_ADDRESS, port, aconf.getLoneliness(),
50 | aconf.getLiveliness(), installProps
51 | );
52 | } catch (IllegalArgumentException |
53 | IOException |
54 | AttachNotSupportedException |
55 | AgentLoadException |
56 | AgentInitializationException ex) {
57 | Logger.getLogger().log(Logger.Level.ALL, new RuntimeException("Attach failed!! Cause: ", ex));
58 | return INVALID_PORT;
59 | }
60 |
61 | if (port > 0) {
62 | return port;
63 | } else {
64 | return INVALID_PORT;
65 | }
66 | }
67 |
68 | private static int findPort() {
69 | for (int i = PORT_MIN; i <= PORT_MAX; i++) {
70 | try {
71 | try (ServerSocket s = new ServerSocket(i)) {
72 | s.close();
73 | return i;
74 | }
75 | } catch (IOException e) {
76 | Logger.getLogger()
77 | .log(Logger.Level.DEBUG, new RuntimeException("Could not open socket on port " + i + ". Trying again.", e));
78 | }
79 | }
80 |
81 | throw new IllegalStateException("No ports available in range [" + PORT_MIN + "," + PORT_MAX + "]");
82 | }
83 |
84 | private static String[] createProperties(int port) {
85 | List properties = new ArrayList<>();
86 |
87 | properties.add(AGENT_PORT_PROPERTY + "=" + port);
88 |
89 | return properties.toArray(new String[]{});
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/runtime-decompiler/src/main/java/org/jrd/frontend/frame/overwrite/FileToClassValidator.java:
--------------------------------------------------------------------------------
1 | package org.jrd.frontend.frame.overwrite;
2 |
3 | import javax.swing.JLabel;
4 | import javax.swing.JTextField;
5 | import javax.swing.event.DocumentEvent;
6 | import javax.swing.event.DocumentListener;
7 | import java.awt.Color;
8 | import java.io.File;
9 |
10 | /**
11 | *
12 | * @author jvanek
13 | */
14 | public class FileToClassValidator implements DocumentListener {
15 |
16 | private final JLabel output;
17 | private final JTextField file;
18 | private final JTextField clazz;
19 |
20 | public FileToClassValidator(JLabel validation, JTextField filePath, JTextField className) {
21 | this.output = validation;
22 | this.file = filePath;
23 | this.clazz = className;
24 | }
25 |
26 | @Override
27 | public void insertUpdate(DocumentEvent e) {
28 | work();
29 | }
30 |
31 | @Override
32 | public void removeUpdate(DocumentEvent e) {
33 | work();
34 | }
35 |
36 | @Override
37 | public void changedUpdate(DocumentEvent e) {
38 | work();
39 | }
40 |
41 | private void work() {
42 | StringAndScore r = validate(clazz.getText(), file.getText());
43 | output.setForeground(Color.green);
44 | if (r.score > 0) {
45 | output.setForeground(Color.orange);
46 | }
47 | if (r.score > 9) {
48 | output.setForeground(Color.red);
49 | }
50 | output.setText(r.message);
51 | }
52 |
53 | public static StringAndScore validate(String clazz, String file) {
54 | int score = 0;
55 | StringBuilder message = new StringBuilder();
56 | File f = new File(file);
57 | if (!f.isFile()) {
58 | score += 10;
59 | message.append("Not a file! ");
60 | }
61 | if (!f.getName().endsWith(".class")) {
62 | score++;
63 | message.append("Not a ending with class! ");
64 | }
65 | String[] pathHunks = f.getAbsolutePath().replace(".class", "").split("[\\.\\\\/]");
66 | String[] classHunks = clazz.split("[\\.\\\\/]");
67 | if (!pathHunks[pathHunks.length - 1].equals(classHunks[classHunks.length - 1])) {
68 | score += 10;
69 | message.append("File name and class name do not match! ");
70 | }
71 | //skipping name
72 | int i1 = pathHunks.length - 1;
73 | int i2 = classHunks.length - 1;
74 | while (true) {
75 | i1--;
76 | i2--;
77 | if (i1 < 0 || i2 < 0) {
78 | break;
79 | }
80 | if (!pathHunks[i1].equals(classHunks[i2])) {
81 | score++;
82 | message.append("Class package do not match directories. ");
83 | break;
84 | }
85 | }
86 | if (message.length() == 0) {
87 | message.append("file x class looks OK!");
88 | }
89 | return new StringAndScore(score, message.toString());
90 | }
91 |
92 | public static class StringAndScore {
93 |
94 | private final int score;
95 | private final String message;
96 |
97 | public StringAndScore(int score, String message) {
98 | this.score = score;
99 | this.message = message;
100 | }
101 |
102 | public int getScore() {
103 | return score;
104 | }
105 |
106 | public String getMessage() {
107 | return message;
108 | }
109 | }
110 |
111 | }
112 |
--------------------------------------------------------------------------------