jList, VMListModel listModel) {
+ add(new Button("Next").onClick(actionEvent -> {
+ JFileChooser fileChooser = FileUtils.chooseFile(FileUtils.HOME);
+ int result = fileChooser.showOpenDialog(null);
+ if (result != JFileChooser.APPROVE_OPTION) {
+ return;
+ }
+ File agent = fileChooser.getSelectedFile();
+ if (agent == null) {
+ return;
+ }
+ if (!FileUtils.checkExtension(agent, ".jar")) {
+ WindowMessage.info("File error", "The Java-Agent must have a " +
+ ".jar file extension.");
+ return;
+ }
+ try {
+ VMUtils.attach(agent, jList.getSelectedValue());
+ } catch (IOException | AgentInitializationException | AttachNotSupportedException | AgentLoadException e) {
+ e.printStackTrace();
+ WindowMessage.info("Load result", e.getMessage());
+ }
+ }));
+
+ add(new Button("Refresh").onClick(actionEvent -> listModel.refreshElements()));
+ }
+}
diff --git a/src/ua/juniffiro/extrajar/gui/panels/MainPanel.java b/src/ua/juniffiro/extrajar/gui/panels/MainPanel.java
new file mode 100644
index 0000000..732c99e
--- /dev/null
+++ b/src/ua/juniffiro/extrajar/gui/panels/MainPanel.java
@@ -0,0 +1,19 @@
+package ua.juniffiro.extrajar.gui.panels;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * +-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+-+
+ * ( Created ) ( by ) ( @juniffiro )
+ * 05/02/2023
+ * +-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+-+
+ */
+public class MainPanel extends JPanel {
+
+ public MainPanel() {
+ setLayout(new BorderLayout());
+ add(new ProgramInfoPanel(), BorderLayout.NORTH);
+ add(new ActionsPanel(), BorderLayout.CENTER);
+ }
+}
diff --git a/src/ua/juniffiro/extrajar/gui/panels/ProgramInfoPanel.java b/src/ua/juniffiro/extrajar/gui/panels/ProgramInfoPanel.java
new file mode 100644
index 0000000..95539ec
--- /dev/null
+++ b/src/ua/juniffiro/extrajar/gui/panels/ProgramInfoPanel.java
@@ -0,0 +1,26 @@
+package ua.juniffiro.extrajar.gui.panels;
+
+import javax.swing.*;
+
+/**
+ * +-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+-+
+ * ( Created ) ( by ) ( @juniffiro )
+ * 05/02/2023
+ * +-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+-+
+ */
+public class ProgramInfoPanel extends JPanel {
+
+ public ProgramInfoPanel() {
+ JLabel jLabel = new JLabel();
+ jLabel.setSize(5, 5);
+ String s = "" +
+ "Select the desired JVM
" +
+ "
" + "If the process is not in the list, then the method does not work.
" +
+ "";
+ jLabel.setText(s);
+ jLabel.setHorizontalAlignment(SwingConstants.CENTER);
+ jLabel.setVerticalAlignment(SwingConstants.CENTER);
+
+ add(jLabel);
+ }
+}
diff --git a/src/ua/juniffiro/extrajar/gui/panels/actions/VMJList.java b/src/ua/juniffiro/extrajar/gui/panels/actions/VMJList.java
new file mode 100644
index 0000000..a438462
--- /dev/null
+++ b/src/ua/juniffiro/extrajar/gui/panels/actions/VMJList.java
@@ -0,0 +1,24 @@
+package ua.juniffiro.extrajar.gui.panels.actions;
+
+import ua.juniffiro.extrajar.gui.listcell.VMListCellRenderer;
+import ua.juniffiro.extrajar.gui.listcell.VMListModel;
+import com.sun.tools.attach.VirtualMachineDescriptor;
+
+import javax.swing.*;
+
+/**
+ * +-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+-+
+ * ( Created ) ( by ) ( @juniffiro )
+ * 06/02/2023
+ * +-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+-+
+ */
+public class VMJList extends JList {
+
+ public VMJList(VMListModel vms) {
+ setModel(vms);
+ setCellRenderer(new VMListCellRenderer()); // jList view
+ setVisibleRowCount(5);
+ setFixedCellHeight(20);
+ setFixedCellWidth(500);
+ }
+}
diff --git a/src/ua/juniffiro/extrajar/log/Log.java b/src/ua/juniffiro/extrajar/log/Log.java
new file mode 100644
index 0000000..184bb3d
--- /dev/null
+++ b/src/ua/juniffiro/extrajar/log/Log.java
@@ -0,0 +1,33 @@
+package ua.juniffiro.extrajar.log;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class Log {
+
+ public static final Logger logger = Logger.getLogger("Loader");
+
+ public static void log(String message, Level level) {
+ logger.log(level, message);
+ }
+
+ public static void info(String message) {
+ logger.info(message);
+ }
+
+ public static void warn(String message) {
+ logger.warning(message);
+ }
+
+ public static void error(String message) {
+ logger.severe(message);
+ }
+
+ public static void log(Object object, Level level) {
+ log(object.toString(), level);
+ }
+
+ public static void log(Level level, String message, Object... objects) {
+ log(String.format(message, objects), level);
+ }
+}
\ No newline at end of file
diff --git a/src/ua/juniffiro/extrajar/utils/FileUtils.java b/src/ua/juniffiro/extrajar/utils/FileUtils.java
new file mode 100644
index 0000000..4ddeb58
--- /dev/null
+++ b/src/ua/juniffiro/extrajar/utils/FileUtils.java
@@ -0,0 +1,59 @@
+package ua.juniffiro.extrajar.utils;
+
+import javax.swing.*;
+import java.io.File;
+
+/**
+ * +-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+-+
+ * ( Created ) ( by ) ( @juniffiro )
+ * 05/02/2023
+ * +-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+-+
+ */
+public class FileUtils {
+
+ /**
+ * User's home directory
+ */
+ public static File HOME = new File(System.getProperty("user.home"));
+
+ /**
+ * Get file extension.
+ * On error it returns an empty string.
+ *
+ * @return File extension.
+ */
+ public static String getFileExtension(File file) {
+ String name = file.getName();
+ int lastIndexOf = name.lastIndexOf(".");
+ if (lastIndexOf == -1) {
+ return "";
+ }
+ return name.substring(lastIndexOf);
+ }
+
+ /**
+ * Check if the file you are checking
+ * has the required extension.
+ * @param file
+ * File to check.
+ * @param extension
+ * The necessary extension to check.
+ */
+ public static boolean checkExtension(File file, String extension) {
+ return getFileExtension(file).equals(extension);
+ }
+
+ /**
+ * Select file from directory.
+ * @param openDirectory
+ * Directory that will be initially
+ * selected and opened in the file
+ * selection window.
+ * @return Returns the file selection window.
+ */
+ public static JFileChooser chooseFile(File openDirectory) {
+ JFileChooser fileChooser = new JFileChooser();
+ fileChooser.setCurrentDirectory(openDirectory);
+ return fileChooser;
+ }
+}
diff --git a/src/ua/juniffiro/extrajar/utils/VMUtils.java b/src/ua/juniffiro/extrajar/utils/VMUtils.java
new file mode 100644
index 0000000..4cfbbdd
--- /dev/null
+++ b/src/ua/juniffiro/extrajar/utils/VMUtils.java
@@ -0,0 +1,132 @@
+package ua.juniffiro.extrajar.utils;
+
+import com.sun.tools.attach.*;
+import ua.juniffiro.extrajar.log.Log;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Optional;
+import java.util.logging.Level;
+
+public class VMUtils {
+
+ /**
+ * Get all virtual machine descriptors
+ * at the current time.
+ */
+ public static List getAllVms() {
+ return VirtualMachine.list();
+ }
+
+ /**
+ * Get VMD by Display Name.
+ * @return Returns the VMD in Optional wrapper.
+ */
+ public static Optional getVmdByName(String displayName) {
+ return VirtualMachine.list()
+ .stream()
+ .filter(vmd -> {
+ Log.info(vmd.displayName());
+ return vmd.displayName().contains(displayName);
+ })
+ .findFirst();
+ }
+
+ /**
+ * Get VMD by PID.
+ * @return Returns the VMD in Optional wrapper.
+ */
+ public static Optional getVmdByPid(String pid) {
+ return VirtualMachine.list()
+ .stream()
+ .filter(vmd -> {
+ Log.info(vmd.displayName());
+ return vmd.id().equals(pid);
+ })
+ .findFirst();
+ }
+
+ /**
+ * Attach the Java agent to VMD.
+ * @param agent
+ * Java agent
+ * @param vmd
+ * VirtualMachineDescriptor
+ * @return Operation Result
+ * You can check if the agent
+ * was loaded successfully.
+ */
+ public static boolean attach(File agent, VirtualMachineDescriptor vmd) throws IOException, AttachNotSupportedException, AgentLoadException, AgentInitializationException {
+ if (!agent.exists() || agent.isDirectory()) {
+ Log.log(Level.SEVERE, "File %s problem", agent.getName());
+ return false;
+ }
+ if (vmd == null) {
+ Log.log(Level.SEVERE, "VM %s not found.");
+ return false;
+ }
+ String pid = vmd.id();
+ VirtualMachine vm = VirtualMachine.attach(pid);
+ loadAgent(vm, agent);
+ return true;
+ }
+
+ /**
+ * Method for loading a Java agent
+ * into the JVM.
+ * @param vm
+ * Virtual machine
+ * @param agent
+ * Java agent
+ */
+ private static void loadAgent(VirtualMachine vm, File agent) throws AgentLoadException, IOException, AgentInitializationException {
+ Log.info("Trying to load an agent into the JVM");
+ vm.loadAgent(agent.getAbsolutePath());
+ vm.detach();
+ Log.info("Agent loaded in JVM.");
+ }
+
+ /**
+ * Attach the Java agent to the VMD,
+ * using the displayed name to find
+ * the desired descriptor.
+ *
+ * @param agent
+ * Java agent
+ * @param displayName
+ * VMD Display Name.
+ * @return Operation Result
+ * You can check if the agent
+ * was loaded successfully.
+ *
+ * @throws AgentLoadException
+ * If agent cannot be loaded
+ * into the target Java virtual
+ * machine.
+ *
+ * @throws IOException
+ * If there is a problem with
+ * the agent file.
+ *
+ * @throws AttachNotSupportedException
+ * Thrown by VirtalMachine.attach when attempting
+ * to attach to a Java virtual machine for which
+ * a compatible AttachProvider does not exist.
+ * It is also thrown by AttachProvider.attachVirtualMachine
+ * if the provider attempts to attach to a Java virtual machine
+ * with which it not compatible.
+ *
+ * @throws AgentInitializationException
+ * If an agent initialization error has occurred.
+ */
+ public static boolean attach(File agent, String displayName) throws AgentLoadException, IOException, AttachNotSupportedException, AgentInitializationException {
+ Optional vmd = getVmdByName(displayName);
+ if (!vmd.isPresent()) {
+ Log.log(Level.SEVERE, "VM %s not found.", displayName);
+ return false;
+ }
+ attach(agent, vmd.get());
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/ua/juniffiro/extrajar/utils/WindowMessage.java b/src/ua/juniffiro/extrajar/utils/WindowMessage.java
new file mode 100644
index 0000000..bd4ab35
--- /dev/null
+++ b/src/ua/juniffiro/extrajar/utils/WindowMessage.java
@@ -0,0 +1,25 @@
+package ua.juniffiro.extrajar.utils;
+
+import javax.swing.*;
+
+/**
+ * +-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+-+
+ * ( Created ) ( by ) ( @juniffiro )
+ * 05/02/2023
+ * +-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+-+
+ */
+public class WindowMessage {
+
+ /**
+ * Displaying a message from an
+ * application in a dialog box.
+ *
+ * @param title
+ * Window title
+ * @param text
+ * Message text
+ */
+ public static void info(String title, String text) {
+ JOptionPane.showConfirmDialog(null, text, title, JOptionPane.DEFAULT_OPTION);
+ }
+}