diff --git a/CHANGELOG.md b/CHANGELOG.md
index 384f702..edc3723 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,9 +4,10 @@ All notable changes to this project will are documented in this changelog file.
## Unreleased
### Added
-- A bit more convenient Hex Editor
-- Support for keeping selection when switching between BytesEditor tabs
+- A bit more convenient Hex Editor (smart backspace/delete, support undo/redo, support keeping selection between tabs)
+- Use working directory for petep.json file
- Fixed copy&paste behaviour of Text editor for bytes
+- Small refactors and fixes
## [2.1.0] - 2023-05-10
### Added
diff --git a/README.md b/README.md
index eab4b50..7871626 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,8 @@ chmod +x petep.sh
petep.bat
```
-***Note:** These run scripts contain useful variables, including path to Java executable.
+***Note:** These run scripts contain useful variables,
+including working directory (for `petep.json` file), and path to Java executable.
You might need to change it if you do not have it in PATH or you use multiple Java versions.*
## Supported functionality
diff --git a/scripts/petep.bat b/scripts/petep.bat
index 56f17f1..1b147d0 100644
--- a/scripts/petep.bat
+++ b/scripts/petep.bat
@@ -1,13 +1,18 @@
@echo off
+
+rem Useful params, change if needed
set JAVA_EXE=java.exe
-set JAVAW_EXE=javaw.exe
-set DIRNAME=%~dp0
-set APP_HOME=%DIRNAME%
+set JAVAW_EXE=java.exe
+set APP_HOME=%~dp0
+set WORKING_DIR=%APP_HOME%
set CMD_LINE_ARGS=%*
set DEFAULT_JVM_OPTS=
set CLASSPATH=%APP_HOME%\lib\*
set MAIN_CLASS="com.warxim.petep.Main"
+rem Set working directory (important for petep.json), by default the startup directory is used
+cd /D "%WORKING_DIR%"
+
if "%~2"=="--nogui" (
goto NOGUI
)
diff --git a/scripts/petep.sh b/scripts/petep.sh
index 1d7fccb..5cbfff9 100644
--- a/scripts/petep.sh
+++ b/scripts/petep.sh
@@ -1,16 +1,22 @@
#!/bin/bash
+# Useful params, change if needed
JAVA="java"
-APP_HOME="`pwd`"
+APP_HOME=$(cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd)
+WORKING_DIR=$APP_HOME
DEFAULT_JVM_OPTS=
CMD_LINE_ARGS=$@
CLASSPATH=$APP_HOME/lib/*
MAIN_CLASS="com.warxim.petep.Main"
LOG_FILE=petep.log
+# Set working directory (important for petep.json), by default the startup directory is used
+cd $WORKING_DIR
+
+# Run PETEP
if [[ $2 == '--nogui' ]];
then
- $JAVA -cp "$CLASSPATH" $MAIN_CLASS $CMD_LINE_ARGS
+ $JAVA $DEFAULT_JVM_OPTS -cp "$CLASSPATH" $MAIN_CLASS $CMD_LINE_ARGS
else
- nohup $JAVA -cp "$CLASSPATH" $MAIN_CLASS $CMD_LINE_ARGS > $LOG_FILE &
-fi
\ No newline at end of file
+ nohup $JAVA $DEFAULT_JVM_OPTS -cp "$CLASSPATH" $MAIN_CLASS $CMD_LINE_ARGS > $LOG_FILE &
+fi
diff --git a/src/main/java/com/warxim/petep/Bundle.java b/src/main/java/com/warxim/petep/Bundle.java
index 8acc3b1..fa491ee 100644
--- a/src/main/java/com/warxim/petep/Bundle.java
+++ b/src/main/java/com/warxim/petep/Bundle.java
@@ -19,7 +19,12 @@
import com.warxim.petep.bootstrap.CommandLineArguments;
import com.warxim.petep.common.Constant;
import com.warxim.petep.common.ContextType;
-import com.warxim.petep.configuration.*;
+import com.warxim.petep.configuration.ExtensionsLoader;
+import com.warxim.petep.configuration.ExtensionsSaver;
+import com.warxim.petep.configuration.ModulesLoader;
+import com.warxim.petep.configuration.ModulesSaver;
+import com.warxim.petep.configuration.ProjectLoader;
+import com.warxim.petep.configuration.ProjectSaver;
import com.warxim.petep.core.PetepManager;
import com.warxim.petep.core.listener.PetepListenerManager;
import com.warxim.petep.exception.ConfigurationException;
@@ -34,7 +39,7 @@
import com.warxim.petep.util.FileUtils;
import lombok.Getter;
-import java.io.File;
+import java.nio.file.Path;
/**
* Singleton for PETEP assets.
@@ -91,13 +96,15 @@ public void load(CommandLineArguments arguments) throws ConfigurationException {
contextType = arguments.getContextType();
projectPath = arguments.getProjectPath();
- var configDirectory = FileUtils.getProjectFileAbsolutePath(Constant.PROJECT_CONFIG_DIRECTORY) + File.separator;
+ var configDirectory = Path.of(FileUtils.getProjectFileAbsolutePath(Constant.PROJECT_CONFIG_DIRECTORY));
- project = ProjectLoader.load(configDirectory + Constant.PROJECT_CONFIG_FILE);
+ project = ProjectLoader.load(configDirectory.resolve(Constant.PROJECT_CONFIG_FILE).toString());
receiverManager = new ReceiverManager();
// Create managers.
- extensionManager = new ExtensionManager(ExtensionsLoader.load(configDirectory + Constant.EXTENSIONS_CONFIG_FILE));
+ extensionManager = new ExtensionManager(ExtensionsLoader.load(
+ configDirectory.resolve(Constant.EXTENSIONS_CONFIG_FILE).toString()
+ ));
proxyModuleFactoryManager = new ProxyFactoryModuleManager();
interceptorModuleFactoryManager = new InterceptorModuleFactoryManager();
petepListenerManager = new PetepListenerManager();
@@ -107,16 +114,16 @@ public void load(CommandLineArguments arguments) throws ConfigurationException {
// Load proxies.
var proxyModuleContainer = new ProxyModuleContainer(ModulesLoader.load(
- configDirectory + Constant.PROXIES_CONFIG_FILE,
+ configDirectory.resolve(Constant.PROXIES_CONFIG_FILE).toString(),
proxyModuleFactoryManager));
// Load interceptor module managers.
var interceptorModuleContainerC2S = new InterceptorModuleContainer(ModulesLoader.load(
- configDirectory + Constant.INTERCEPTORS_C2S_CONFIG_FILE,
+ configDirectory.resolve(Constant.INTERCEPTORS_C2S_CONFIG_FILE).toString(),
interceptorModuleFactoryManager));
var interceptorModuleContainerS2C = new InterceptorModuleContainer(ModulesLoader.load(
- configDirectory + Constant.INTERCEPTORS_S2C_CONFIG_FILE,
+ configDirectory.resolve(Constant.INTERCEPTORS_S2C_CONFIG_FILE).toString(),
interceptorModuleFactoryManager));
// Create PETEP manager.
@@ -132,27 +139,26 @@ public void load(CommandLineArguments arguments) throws ConfigurationException {
* @throws ConfigurationException if the bundle could not be saved because of configuration error
*/
public void save() throws ConfigurationException {
- var configDirectory =
- FileUtils.getProjectFileAbsolutePath(Constant.PROJECT_CONFIG_DIRECTORY) + File.separator;
+ var configDirectory = Path.of(FileUtils.getProjectFileAbsolutePath(Constant.PROJECT_CONFIG_DIRECTORY));
ProjectSaver.save(
- configDirectory + Constant.PROJECT_CONFIG_FILE,
+ configDirectory.resolve(Constant.PROJECT_CONFIG_FILE).toString(),
project);
ExtensionsSaver.save(
- configDirectory + Constant.EXTENSIONS_CONFIG_FILE,
+ configDirectory.resolve(Constant.EXTENSIONS_CONFIG_FILE).toString(),
extensionManager.getList());
ModulesSaver.save(
- configDirectory + Constant.PROXIES_CONFIG_FILE,
+ configDirectory.resolve(Constant.PROXIES_CONFIG_FILE).toString(),
petepManager.getProxyModuleContainer().getList());
ModulesSaver.save(
- configDirectory + Constant.INTERCEPTORS_C2S_CONFIG_FILE,
+ configDirectory.resolve(Constant.INTERCEPTORS_C2S_CONFIG_FILE).toString(),
petepManager.getInterceptorModuleContainerC2S().getList());
ModulesSaver.save(
- configDirectory + Constant.INTERCEPTORS_S2C_CONFIG_FILE,
+ configDirectory.resolve(Constant.INTERCEPTORS_S2C_CONFIG_FILE).toString(),
petepManager.getInterceptorModuleContainerS2C().getList());
}
diff --git a/src/main/java/com/warxim/petep/bootstrap/PetepBootstrap.java b/src/main/java/com/warxim/petep/bootstrap/PetepBootstrap.java
index e6f5ad9..d3994d0 100644
--- a/src/main/java/com/warxim/petep/bootstrap/PetepBootstrap.java
+++ b/src/main/java/com/warxim/petep/bootstrap/PetepBootstrap.java
@@ -45,7 +45,7 @@ public void start() throws BootstrapException {
try {
// Initialize utils.
FileUtils.setProjectDirectory(
- FileUtils.getApplicationFileAbsolutePath(arguments.getProjectPath()));
+ FileUtils.getWorkingDirectoryFileAbsolutePath(arguments.getProjectPath()));
// Load PETEP bundle.
Bundle.getInstance().load(arguments);
diff --git a/src/main/java/com/warxim/petep/gui/PetepGui.java b/src/main/java/com/warxim/petep/gui/PetepGui.java
index d5ab343..66e8d34 100644
--- a/src/main/java/com/warxim/petep/gui/PetepGui.java
+++ b/src/main/java/com/warxim/petep/gui/PetepGui.java
@@ -19,7 +19,6 @@
import com.sun.javafx.css.StyleManager;
import com.warxim.petep.Bundle;
import com.warxim.petep.common.Constant;
-import com.warxim.petep.exception.ConfigurationException;
import com.warxim.petep.gui.common.GuiConstant;
import com.warxim.petep.gui.common.PetepApplication;
import com.warxim.petep.gui.dialog.Dialogs;
@@ -74,20 +73,9 @@ public void start(Stage stage) {
*
Shows dialog to ask user, whether the project should be saved or not.
*/
private void onClose(WindowEvent event) {
- var decision = Dialogs.createYesOrNoOrCancelDialog("Save project", "Do you want to save project before closing PETEP?");
- if (decision.isEmpty()) {
+ var closeProject = Dialogs.createCloseProjectDialog();
+ if (!closeProject) {
event.consume();
- return;
- }
-
- if (Boolean.TRUE.equals(decision.get())) {
- try {
- Bundle.getInstance().save();
- } catch (ConfigurationException e) {
- event.consume();
- Logger.getGlobal().log(Level.SEVERE, "Could not save project!", e);
- Dialogs.createExceptionDialog("Could not save project", "Could not save project!", e);
- }
}
}
}
diff --git a/src/main/java/com/warxim/petep/gui/controller/ApplicationController.java b/src/main/java/com/warxim/petep/gui/controller/ApplicationController.java
index ead0c2d..dc6c127 100644
--- a/src/main/java/com/warxim/petep/gui/controller/ApplicationController.java
+++ b/src/main/java/com/warxim/petep/gui/controller/ApplicationController.java
@@ -28,13 +28,13 @@
import com.warxim.petep.gui.guide.GuideDialog;
import com.warxim.petep.helper.DefaultGuiHelper;
import com.warxim.petep.util.GuiUtils;
-import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.TabPane;
+import javafx.stage.Stage;
import java.io.IOException;
import java.net.URL;
@@ -133,7 +133,12 @@ private void onProjectInfoMenuClick(ActionEvent event) {
*/
@FXML
private void onExitMenuClick(ActionEvent event) {
- Platform.exit();
+ var closeProject = Dialogs.createCloseProjectDialog();
+ if (!closeProject) {
+ return;
+ }
+ var stage = (Stage) tabs.getScene().getWindow();
+ stage.close();
}
/**
diff --git a/src/main/java/com/warxim/petep/gui/dialog/Dialogs.java b/src/main/java/com/warxim/petep/gui/dialog/Dialogs.java
index d393f30..cd91558 100644
--- a/src/main/java/com/warxim/petep/gui/dialog/Dialogs.java
+++ b/src/main/java/com/warxim/petep/gui/dialog/Dialogs.java
@@ -16,7 +16,9 @@
*/
package com.warxim.petep.gui.dialog;
+import com.warxim.petep.Bundle;
import com.warxim.petep.common.Constant;
+import com.warxim.petep.exception.ConfigurationException;
import com.warxim.petep.extension.PetepAPI;
import com.warxim.petep.gui.GuiBundle;
import javafx.event.ActionEvent;
@@ -357,6 +359,28 @@ public static void createNewVersionDialog(String newVersion) {
alert.showAndWait();
}
+ /**
+ * Create close project dialog
+ * @return {@code} true if project should be closed
+ */
+ public static boolean createCloseProjectDialog() {
+ var decision = Dialogs.createYesOrNoOrCancelDialog("Save project", "Do you want to save project before closing PETEP?");
+ if (decision.isEmpty()) {
+ return false;
+ }
+
+ if (Boolean.TRUE.equals(decision.get())) {
+ try {
+ Bundle.getInstance().save();
+ } catch (ConfigurationException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Could not save project!", e);
+ Dialogs.createExceptionDialog("Could not save project", "Could not save project!", e);
+ return false;
+ }
+ }
+ return true;
+ }
+
/**
* Opens PETEP website.
*/
diff --git a/src/main/java/com/warxim/petep/util/FileUtils.java b/src/main/java/com/warxim/petep/util/FileUtils.java
index 1160291..f8ed68c 100644
--- a/src/main/java/com/warxim/petep/util/FileUtils.java
+++ b/src/main/java/com/warxim/petep/util/FileUtils.java
@@ -27,8 +27,8 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
+import java.util.Comparator;
import java.util.logging.Logger;
-import java.util.stream.Stream;
/**
* File utils.
@@ -66,13 +66,7 @@ public static File getApplicationFile(String path) {
* @return Absolute path of application file
*/
public static String getApplicationFileAbsolutePath(String path) {
- if (Paths.get(path).isAbsolute()) {
- // Absolute path
- return path;
- }
-
- // Relative path
- return Paths.get(getApplicationDirectory()).resolve(path).normalize().toString();
+ return getFileAbsolutePath(getApplicationDirectory(), path);
}
/**
@@ -81,17 +75,7 @@ public static String getApplicationFileAbsolutePath(String path) {
* @return Path relative to application directory
*/
public static String applicationRelativize(Path path) {
- try {
- var applicationDirectoryPath = Paths.get(getApplicationDirectory());
-
- // Resolve path
- path = applicationDirectoryPath.resolve(path).normalize();
-
- // Relativize the path
- return applicationDirectoryPath.relativize(path).toString();
- } catch (IllegalArgumentException e) {
- return path.toString();
- }
+ return relativize(Path.of(getApplicationDirectory()), path);
}
/**
@@ -103,23 +87,31 @@ public static String applicationRelativize(String path) {
return applicationRelativize(Paths.get(path));
}
+ /**
+ * Relativizes given path to working directory path
+ * @param path Absolute path to relativize
+ * @return Path relative to working directory
+ */
+ public static String workingDirectoryRelativize(Path path) {
+ return relativize(Path.of(getWorkingDirectory()), path);
+ }
+
+ /**
+ * Relativizes given path to working directory path
+ * @param path Absolute path to relativize
+ * @return Path relative to working directory
+ */
+ public static String workingDirectoryRelativize(String path) {
+ return workingDirectoryRelativize(Path.of(path));
+ }
+
/**
* Relativizes given path to project directory path
* @param path Absolute path to relativize
* @return Path relative to project directory
*/
public static String projectRelativize(Path path) {
- try {
- var projectDirectoryPath = Paths.get(getProjectDirectory());
-
- // Resolve path
- path = projectDirectoryPath.resolve(path).normalize();
-
- // Relativize the path
- return projectDirectoryPath.relativize(path).toString();
- } catch (IllegalArgumentException e) {
- return path.toString();
- }
+ return relativize(Path.of(getProjectDirectory()), path);
}
/**
@@ -131,6 +123,23 @@ public static String projectRelativize(String path) {
return projectRelativize(Paths.get(path));
}
+ /**
+ * Relativizes given path to root directory path
+ * @param path Absolute path to relativize
+ * @return Path relative to root directory
+ */
+ public static String relativize(Path rootDirectoryPath, Path path) {
+ try {
+ // Resolve path
+ path = rootDirectoryPath.resolve(path).normalize();
+
+ // Relativize the path
+ return rootDirectoryPath.relativize(path).toString();
+ } catch (IllegalArgumentException e) {
+ return path.toString();
+ }
+ }
+
/**
* Obtains project file.
* @param path Path relative to project directory
@@ -146,13 +155,16 @@ public static File getProjectFile(String path) {
* @return Absolute path of project file
*/
public static String getProjectFileAbsolutePath(String path) {
- if (Paths.get(path).isAbsolute()) {
- // Absolute path
- return path;
- }
+ return getFileAbsolutePath(getProjectDirectory(), path);
+ }
- // Relative path
- return Paths.get(getProjectDirectory()).resolve(path).normalize().toString();
+ /**
+ * Obtains working directory file absolute path
+ * @param path Path relative to working directory
+ * @return Absolute path of working directory file
+ */
+ public static String getWorkingDirectoryFileAbsolutePath(String path) {
+ return getFileAbsolutePath(getWorkingDirectory(), path);
}
/**
@@ -179,6 +191,14 @@ public static String getProjectDirectory() {
return System.getProperty("user.dir");
}
+ /**
+ * Obtains working directory.
+ * @return Current working directory
+ */
+ public static String getWorkingDirectory() {
+ return System.getProperty("user.dir");
+ }
+
/**
* Sets working directory (used internally).
* @param directory Directory to be set
@@ -213,13 +233,32 @@ public static void copyDirectory(String source, String destination) throws IOExc
* @throws IOException If the copy failed
*/
public static void copyDirectory(Path source, Path destination) throws IOException {
- try (Stream stream = Files.walk(source)) {
+ try (var stream = Files.walk(source)) {
+ var destFile = destination.toFile();
+ if (!destFile.exists() && !destFile.mkdirs()) {
+ throw new IOException(String.format("Could not create directory '%s'", destFile.getAbsolutePath()));
+ }
stream.forEach(src -> copy(src, destination.resolve(source.relativize(src))));
} catch (UncheckedIOException e) {
throw e.getCause();
}
}
+ /**
+ * Deletes directories recursively
+ * @param directory Directory to delete (including content)
+ * @return {@code true} if the deletion was successful
+ */
+ public static boolean deleteDirectories(String directory) {
+ try (var stream = Files.walk(Path.of(directory))) {
+ return stream.sorted(Comparator.reverseOrder())
+ .map(Path::toFile)
+ .allMatch(File::delete);
+ } catch (IOException e) {
+ return false;
+ }
+ }
+
/**
* Copies from source to destination and replace existing.
* @param source Source path
@@ -241,11 +280,13 @@ private static String initApplicationDirectory() {
try {
var path = Paths.get(Main.class.getProtectionDomain().getCodeSource().getLocation().toURI());
+ // PETEP run from lib/petep.jar
if (path.toString().toLowerCase().endsWith(".jar")) {
return path.getParent().getParent().toString();
}
- return getProjectDirectory();
+ // Fallback for working directory in IDE
+ return Paths.get(".").toAbsolutePath().normalize().toString();
} catch (URISyntaxException e) {
Logger.getGlobal().severe(e.getMessage());
}
diff --git a/src/main/java/com/warxim/petep/wizard/configuration/WizardConfigurationLoader.java b/src/main/java/com/warxim/petep/wizard/configuration/WizardConfigurationLoader.java
index 486527c..521f62f 100644
--- a/src/main/java/com/warxim/petep/wizard/configuration/WizardConfigurationLoader.java
+++ b/src/main/java/com/warxim/petep/wizard/configuration/WizardConfigurationLoader.java
@@ -31,6 +31,7 @@
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.time.Instant;
@@ -86,12 +87,12 @@ public static List load(String path) {
*/
private static Optional loadProjectDecorator(JsonElement element) {
try {
- var configFile = FileUtils.getApplicationFileAbsolutePath(
- element.getAsString()
- + File.separator
- + Constant.PROJECT_CONFIG_DIRECTORY
- + File.separator
- + Constant.PROJECT_CONFIG_FILE);
+ var configFile = FileUtils.getWorkingDirectoryFileAbsolutePath(
+ Path.of(element.getAsString())
+ .resolve(Constant.PROJECT_CONFIG_DIRECTORY)
+ .resolve(Constant.PROJECT_CONFIG_FILE)
+ .toString()
+ );
// Load project information.
var project = ProjectLoader.load(configFile);
diff --git a/src/main/java/com/warxim/petep/wizard/controller/WizardController.java b/src/main/java/com/warxim/petep/wizard/controller/WizardController.java
index c8460bf..be58f42 100644
--- a/src/main/java/com/warxim/petep/wizard/controller/WizardController.java
+++ b/src/main/java/com/warxim/petep/wizard/controller/WizardController.java
@@ -44,6 +44,7 @@
import java.io.File;
import java.io.IOException;
import java.net.URL;
+import java.nio.file.Path;
import java.time.Instant;
import java.util.ResourceBundle;
import java.util.logging.Level;
@@ -74,7 +75,9 @@ public final class WizardController implements Initializable {
@Override
public void initialize(URL location, ResourceBundle resources) {
// Create observable list of projects.
- projects = FXCollections.observableList(WizardConfigurationLoader.load(Constant.WIZARD_CONFIG_FILE));
+ projects = FXCollections.observableList(WizardConfigurationLoader.load(
+ FileUtils.getWorkingDirectoryFileAbsolutePath(Constant.WIZARD_CONFIG_FILE)
+ ));
// Initialize columns.
nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
@@ -105,7 +108,10 @@ private void onNewButtonClick(ActionEvent event) {
projectsTable.getSelectionModel().select(maybeProject.get());
// Save wizard configuration.
- WizardConfigurationSaver.save(Constant.WIZARD_CONFIG_FILE, projects);
+ WizardConfigurationSaver.save(
+ FileUtils.getWorkingDirectoryFileAbsolutePath(Constant.WIZARD_CONFIG_FILE),
+ projects
+ );
} catch (IOException e) {
Logger.getGlobal().log(Level.SEVERE, "Exception during openning of project dialog", e);
}
@@ -134,7 +140,10 @@ private void onEditButtonClick(ActionEvent event) {
projectsTable.getSelectionModel().select(maybeProject.get());
// Save wizard configuration.
- WizardConfigurationSaver.save(Constant.WIZARD_CONFIG_FILE, projects);
+ WizardConfigurationSaver.save(
+ FileUtils.getWorkingDirectoryFileAbsolutePath(Constant.WIZARD_CONFIG_FILE),
+ projects
+ );
} catch (IOException e) {
Logger.getGlobal().log(Level.SEVERE, "Exception during openning of project dialog", e);
} catch (ConfigurationException e) {
@@ -171,7 +180,7 @@ private void onOpenButtonClick(ActionEvent event) {
// Choose project directory.
var directoryChooser = new DirectoryChooser();
directoryChooser.setTitle("Open project");
- directoryChooser.setInitialDirectory(new File(System.getProperty("user.dir")));
+ directoryChooser.setInitialDirectory(new File(FileUtils.getWorkingDirectory()));
var directory = directoryChooser.showDialog(null);
if (directory == null) {
@@ -180,15 +189,14 @@ private void onOpenButtonClick(ActionEvent event) {
// Load project.
try {
- var configFile = directory.getPath()
- + File.separator
- + Constant.PROJECT_CONFIG_DIRECTORY
- + File.separator
- + Constant.PROJECT_CONFIG_FILE;
+ var configFile = Path.of(directory.getPath())
+ .resolve(Constant.PROJECT_CONFIG_DIRECTORY)
+ .resolve(Constant.PROJECT_CONFIG_FILE)
+ .toString();
var project = ProjectLoader.load(configFile);
- var relativizedPath = FileUtils.applicationRelativize(directory.getPath());
+ var relativizedPath = FileUtils.workingDirectoryRelativize(directory.getPath());
var lastModified = Instant.ofEpochMilli(new File(configFile).lastModified());
// Add project to table.
@@ -199,7 +207,10 @@ private void onOpenButtonClick(ActionEvent event) {
lastModified));
// Save wizard configuration.
- WizardConfigurationSaver.save(Constant.WIZARD_CONFIG_FILE, projects);
+ WizardConfigurationSaver.save(
+ FileUtils.getWorkingDirectoryFileAbsolutePath(Constant.WIZARD_CONFIG_FILE),
+ projects
+ );
} catch (ConfigurationException e) {
Dialogs.createExceptionDialog("Project could not be loaded", "Project could not be loaded!",
e);
@@ -228,7 +239,10 @@ private void onRemoveButtonClick(ActionEvent event) {
projects.remove(project);
// Save wizard configuration.
- WizardConfigurationSaver.save(Constant.WIZARD_CONFIG_FILE, projects);
+ WizardConfigurationSaver.save(
+ FileUtils.getWorkingDirectoryFileAbsolutePath(Constant.WIZARD_CONFIG_FILE),
+ projects
+ );
}
/**
diff --git a/src/main/java/com/warxim/petep/wizard/dialog/EditProjectDialog.java b/src/main/java/com/warxim/petep/wizard/dialog/EditProjectDialog.java
index f7693da..bdfe348 100644
--- a/src/main/java/com/warxim/petep/wizard/dialog/EditProjectDialog.java
+++ b/src/main/java/com/warxim/petep/wizard/dialog/EditProjectDialog.java
@@ -25,8 +25,8 @@
import com.warxim.petep.wizard.project.WizardProjectDecorator;
import javafx.collections.FXCollections;
-import java.io.File;
import java.io.IOException;
+import java.nio.file.Path;
import java.time.Instant;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -46,11 +46,10 @@ public EditProjectDialog(WizardProjectDecorator project) throws IOException, Con
// Load extensions for the project
var list = WizardExtensionsLoader.load(
- FileUtils.getApplicationFileAbsolutePath(project.getPath())
- + File.separator
- + Constant.PROJECT_CONFIG_DIRECTORY
- + File.separator
- + Constant.EXTENSIONS_CONFIG_FILE);
+ Path.of(FileUtils.getWorkingDirectoryFileAbsolutePath(project.getPath()))
+ .resolve(Constant.PROJECT_CONFIG_DIRECTORY)
+ .resolve(Constant.EXTENSIONS_CONFIG_FILE)
+ .toString());
// Fill inputs
nameInput.setText(project.getName());
diff --git a/src/main/java/com/warxim/petep/wizard/dialog/NewProjectDialog.java b/src/main/java/com/warxim/petep/wizard/dialog/NewProjectDialog.java
index 1821e54..47c0119 100644
--- a/src/main/java/com/warxim/petep/wizard/dialog/NewProjectDialog.java
+++ b/src/main/java/com/warxim/petep/wizard/dialog/NewProjectDialog.java
@@ -32,6 +32,8 @@
import java.io.File;
import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
@@ -61,8 +63,8 @@ public NewProjectDialog() throws IOException {
extensionsList.setItems(extensions);
- initPresets();
initToggles();
+ initPresets();
}
/**
@@ -95,6 +97,13 @@ protected WizardProjectDecorator obtainResult() {
private void initPresets() {
var presetsDirectory = FileUtils.getApplicationFile(Constant.PRESETS_DIRECTORY);
var presetsFiles = presetsDirectory.listFiles();
+ if (presetsFiles == null || presetsFiles.length == 0) {
+ // If there are no presets, disable the option and use custom project type
+ presetInput.setDisable(true);
+ presetRadioInput.setDisable(true);
+ customRadioInput.setSelected(true);
+ return;
+ }
var presets = Arrays.stream(presetsFiles)
.filter(File::isDirectory)
.map(File::getName)
@@ -144,7 +153,8 @@ private static void createPresetProject(
throws IOException, ConfigurationException {
FileUtils.copyDirectory(
new File(FileUtils.getApplicationFile(Constant.PRESETS_DIRECTORY), presetPath).getPath(),
- path);
+ FileUtils.getWorkingDirectoryFileAbsolutePath(path)
+ );
saveProject(path, projectDecorator.getProject());
}
@@ -158,33 +168,31 @@ private static void createCustomProject(
List extensions)
throws ConfigurationException, IOException {
// Create project directory.
+ path = FileUtils.getWorkingDirectoryFileAbsolutePath(path);
WizardProjectDirectoryCreator.create(path);
// Save project.
saveProject(path, projectDecorator.getProject());
- saveExtensions(path,extensions);
+ saveExtensions(path, extensions);
- var configDirectory = path
- + File.separator
- + Constant.PROJECT_CONFIG_DIRECTORY
- + File.separator;
+ var configDirectory = Path.of(path).resolve(Constant.PROJECT_CONFIG_DIRECTORY);
// Create proxies.json if it does not exist.
- var file = configDirectory + Constant.PROXIES_CONFIG_FILE;
- if (!new File(file).exists()) {
- ModulesSaver.save(file, new ArrayList<>());
+ var file = configDirectory.resolve(Constant.PROXIES_CONFIG_FILE);
+ if (!Files.exists(file)) {
+ ModulesSaver.save(file.toString(), new ArrayList<>());
}
// Create interceptors-C2S.json if it does not exist.
- file = configDirectory + Constant.INTERCEPTORS_C2S_CONFIG_FILE;
- if (!new File(file).exists()) {
- ModulesSaver.save(file, new ArrayList<>());
+ file = configDirectory.resolve(Constant.INTERCEPTORS_C2S_CONFIG_FILE);
+ if (!Files.exists(file)) {
+ ModulesSaver.save(file.toString(), new ArrayList<>());
}
// Create interceptors-S2C.json if it does not exist.
- file = configDirectory + Constant.INTERCEPTORS_S2C_CONFIG_FILE;
- if (!new File(file).exists()) {
- ModulesSaver.save(file, new ArrayList<>());
+ file = configDirectory.resolve(Constant.INTERCEPTORS_S2C_CONFIG_FILE);
+ if (!Files.exists(file)) {
+ ModulesSaver.save(file.toString(), new ArrayList<>());
}
}
}
diff --git a/src/main/java/com/warxim/petep/wizard/dialog/ProjectDialog.java b/src/main/java/com/warxim/petep/wizard/dialog/ProjectDialog.java
index 0be0bef..4c98db2 100644
--- a/src/main/java/com/warxim/petep/wizard/dialog/ProjectDialog.java
+++ b/src/main/java/com/warxim/petep/wizard/dialog/ProjectDialog.java
@@ -36,6 +36,7 @@
import java.io.File;
import java.io.IOException;
+import java.nio.file.Path;
import java.util.List;
/**
@@ -87,17 +88,17 @@ protected final void onAddInternalButtonClick(ActionEvent event) {
}
// Choose from internal extensions.
- var dialog = new ChoiceDialog(Constant.INTERNAL_EXTENSIONS.get(0), Constant.INTERNAL_EXTENSIONS);
-
- dialog.setTitle("Add internal extension");
- dialog.setHeaderText("Add internal extension");
- dialog.setContentText("Extension:");
-
- // Add extension to list.
- var result = dialog.showAndWait();
- if (result.isPresent()) {
- extensions.add(new WizardProjectExtension(result.get(), null, null));
+ var result = Dialogs.createChoiceDialog(
+ "Add internal extension",
+ "Extension:",
+ Constant.INTERNAL_EXTENSIONS,
+ Constant.INTERNAL_EXTENSIONS.get(0)
+ );
+ if (result.isEmpty()) {
+ return;
}
+
+ addExtension(result.get());
}
/**
@@ -108,7 +109,7 @@ protected final void onAddExternalButtonClick(ActionEvent event) {
// Choose extension file.
var fileChooser = new FileChooser();
fileChooser.setTitle("Open project");
- fileChooser.setInitialDirectory(new File(System.getProperty("user.dir")));
+ fileChooser.setInitialDirectory(new File(FileUtils.getApplicationDirectory()));
fileChooser.getExtensionFilters()
.add(new FileChooser.ExtensionFilter("PETEP jar extensions (*.jar)", "*.jar"));
@@ -118,7 +119,19 @@ protected final void onAddExternalButtonClick(ActionEvent event) {
}
// Add extension to list.
- extensions.add(new WizardProjectExtension(FileUtils.applicationRelativize(file.getPath()), null, null));
+ addExtension(FileUtils.applicationRelativize(file.getPath()));
+ }
+
+ /**
+ * Adds extension to the extension list if not already present
+ */
+ private void addExtension(String newExtensionPath) {
+ var alreadyExists = extensions.stream()
+ .anyMatch(extension -> extension.getPath().equals(newExtensionPath));
+ if (alreadyExists) {
+ return;
+ }
+ extensions.add(new WizardProjectExtension(newExtensionPath, null, null));
}
/**
@@ -131,7 +144,7 @@ protected final void onRemoveButtonClick(ActionEvent event) {
return;
}
- if (!Dialogs.createYesOrNoDialog("Are you sure?",
+ if (!Dialogs.createYesOrNoDialog("Remove extension",
"Do you really want to remove the extension '" + extension.getPath()
+ "' from the project? (Extension data stored in the configuration will be lost!)")) {
return;
@@ -162,7 +175,7 @@ protected final boolean isValid() {
private void onPathButtonClick(ActionEvent event) {
var directoryChooser = new DirectoryChooser();
directoryChooser.setTitle("Save project");
- directoryChooser.setInitialDirectory(new File(System.getProperty("user.dir")));
+ directoryChooser.setInitialDirectory(new File(FileUtils.getWorkingDirectory()));
var directory = directoryChooser.showDialog(null);
if (directory == null) {
@@ -176,18 +189,17 @@ private void onPathButtonClick(ActionEvent event) {
return;
}
- pathInput.setText(FileUtils.applicationRelativize(directory.getPath()));
+ pathInput.setText(FileUtils.workingDirectoryRelativize(directory.getPath()));
}
/**
* Saves project and its extension configuration.
*/
protected static void saveProject(String path, Project project) throws ConfigurationException {
- var projectConfigPath = FileUtils.getApplicationFileAbsolutePath(path)
- + File.separator
- + Constant.PROJECT_CONFIG_DIRECTORY
- + File.separator
- + Constant.PROJECT_CONFIG_FILE;
+ var projectConfigPath = Path.of(FileUtils.getWorkingDirectoryFileAbsolutePath(path))
+ .resolve(Constant.PROJECT_CONFIG_DIRECTORY)
+ .resolve(Constant.PROJECT_CONFIG_FILE)
+ .toString();
ProjectSaver.save(projectConfigPath, project);
}
@@ -196,11 +208,10 @@ protected static void saveProject(String path, Project project) throws Configura
*/
protected static void saveExtensions(String path, List extensions)
throws ConfigurationException {
- var projectExtensionsPath = FileUtils.getApplicationFileAbsolutePath(path)
- + File.separator
- + Constant.PROJECT_CONFIG_DIRECTORY
- + File.separator
- + Constant.EXTENSIONS_CONFIG_FILE;
+ var projectExtensionsPath = Path.of(FileUtils.getWorkingDirectoryFileAbsolutePath(path))
+ .resolve(Constant.PROJECT_CONFIG_DIRECTORY)
+ .resolve(Constant.EXTENSIONS_CONFIG_FILE)
+ .toString();
WizardExtensionsSaver.save(projectExtensionsPath, extensions);
}
}
diff --git a/src/test/java/com/warxim/petep/extension/internal/history/service/HistoryTestBase.java b/src/test/java/com/warxim/petep/extension/internal/history/service/HistoryTestBase.java
index dc73d3c..9b2ceb6 100644
--- a/src/test/java/com/warxim/petep/extension/internal/history/service/HistoryTestBase.java
+++ b/src/test/java/com/warxim/petep/extension/internal/history/service/HistoryTestBase.java
@@ -8,11 +8,11 @@
import com.warxim.petep.extension.internal.history.model.HistoricProxy;
import com.warxim.petep.extension.internal.history.repository.CachedDatabaseHistoryRepository;
import com.warxim.petep.extension.internal.history.repository.DatabaseHistoryRepository;
+import com.warxim.petep.util.FileUtils;
import lombok.extern.java.Log;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;
-import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
@@ -20,12 +20,15 @@
import java.sql.SQLException;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ExecutionException;
@Log
public class HistoryTestBase {
- protected static final String TEST_DIRECTORY = "./test_temp_directory";
+ protected static final String TEST_DIRECTORY = "./tmp_test_history";
protected static final Path TEST_DIRECTORY_PATH = Path.of(TEST_DIRECTORY);
private List services = new ArrayList<>();
@@ -33,6 +36,7 @@ public class HistoryTestBase {
@BeforeSuite(alwaysRun = true)
public void beforeSuite() throws IOException {
log.info("Creating test directory: " + TEST_DIRECTORY);
+ FileUtils.deleteDirectories(TEST_DIRECTORY);
Files.createDirectories(TEST_DIRECTORY_PATH);
}
@@ -43,10 +47,7 @@ public void afterSuite() throws IOException {
}
log.info("Deleting test directory: " + TEST_DIRECTORY);
- Files.walk(TEST_DIRECTORY_PATH)
- .sorted(Comparator.reverseOrder())
- .map(Path::toFile)
- .forEach(File::delete);
+ FileUtils.deleteDirectories(TEST_DIRECTORY);
}
protected static String getTestFilePath(String path) {
diff --git a/src/test/java/com/warxim/petep/test/base/util/TestUtils.java b/src/test/java/com/warxim/petep/test/base/util/TestUtils.java
index abc16d0..69fbb83 100644
--- a/src/test/java/com/warxim/petep/test/base/util/TestUtils.java
+++ b/src/test/java/com/warxim/petep/test/base/util/TestUtils.java
@@ -41,7 +41,7 @@ public static T getWithRetries(Supplier supplier, int retryCount, int ret
if (value != null) {
return value;
}
- TestUtils.sleep(retryInterval);
+ sleep(retryInterval);
}
throw new AssertionError("Could not get value!");
}
diff --git a/src/test/java/com/warxim/petep/util/FileUtilsTest.java b/src/test/java/com/warxim/petep/util/FileUtilsTest.java
index ac4e0e3..f35f22c 100644
--- a/src/test/java/com/warxim/petep/util/FileUtilsTest.java
+++ b/src/test/java/com/warxim/petep/util/FileUtilsTest.java
@@ -39,6 +39,7 @@ public void getApplicationFileAbsolutePathTest(String directory, String path, St
try (var mocked = mockStatic(FileUtils.class)) {
mocked.when(FileUtils::getApplicationDirectory).thenReturn(directory);
mocked.when(() -> FileUtils.getApplicationFileAbsolutePath(anyString())).thenCallRealMethod();
+ mocked.when(() -> FileUtils.getFileAbsolutePath(anyString(), anyString())).thenCallRealMethod();
mocked.when(() -> FileUtils.getApplicationFile(anyString())).thenCallRealMethod();
assertThat(unifyPath(FileUtils.getApplicationFileAbsolutePath(path)))
@@ -57,6 +58,7 @@ public void getProjectFileAbsolutePathTest(String directory, String path, String
try (var mocked = mockStatic(FileUtils.class)) {
mocked.when(FileUtils::getProjectDirectory).thenReturn(directory);
mocked.when(() -> FileUtils.getProjectFileAbsolutePath(anyString())).thenCallRealMethod();
+ mocked.when(() -> FileUtils.getFileAbsolutePath(anyString(), anyString())).thenCallRealMethod();
mocked.when(() -> FileUtils.getProjectFile(anyString())).thenCallRealMethod();
assertThat(unifyPath(FileUtils.getProjectFileAbsolutePath(path)))
@@ -67,6 +69,21 @@ public void getProjectFileAbsolutePathTest(String directory, String path, String
}
}
+ @Test(dataProvider = "paths")
+ public void getWorkingDirectoryFileAbsolutePathTest(String directory, String path, String expectedResult, boolean windowsOnly) {
+ if (windowsOnly && !isWindows()) {
+ return;
+ }
+ try (var mocked = mockStatic(FileUtils.class)) {
+ mocked.when(FileUtils::getWorkingDirectory).thenReturn(directory);
+ mocked.when(() -> FileUtils.getWorkingDirectoryFileAbsolutePath(anyString())).thenCallRealMethod();
+ mocked.when(() -> FileUtils.getFileAbsolutePath(anyString(), anyString())).thenCallRealMethod();
+
+ assertThat(unifyPath(FileUtils.getWorkingDirectoryFileAbsolutePath(path)))
+ .isEqualTo(unifyPath(expectedResult));
+ }
+ }
+
@DataProvider(name = "pathsToRelativize")
public Object[][] pathsToRelativizeProvider() {
var winDirectory = "D:/Projects/Test";
@@ -93,6 +110,7 @@ public void applicationRelativizeTest(String directory, String path, String expe
mocked.when(FileUtils::getApplicationDirectory).thenReturn(directory);
mocked.when(() -> FileUtils.applicationRelativize(anyString())).thenCallRealMethod();
mocked.when(() -> FileUtils.applicationRelativize(any(Path.class))).thenCallRealMethod();
+ mocked.when(() -> FileUtils.relativize(any(Path.class), any(Path.class))).thenCallRealMethod();
assertThat(unifyPath(FileUtils.applicationRelativize(path)))
.isEqualTo(unifyPath(expectedResult));
@@ -102,6 +120,44 @@ public void applicationRelativizeTest(String directory, String path, String expe
}
}
+ @Test(dataProvider = "pathsToRelativize")
+ public void projectRelativizeTest(String directory, String path, String expectedResult, boolean windowsOnly) {
+ if (windowsOnly && !isWindows()) {
+ return;
+ }
+ try (var mocked = mockStatic(FileUtils.class)) {
+ mocked.when(FileUtils::getProjectDirectory).thenReturn(directory);
+ mocked.when(() -> FileUtils.projectRelativize(anyString())).thenCallRealMethod();
+ mocked.when(() -> FileUtils.projectRelativize(any(Path.class))).thenCallRealMethod();
+ mocked.when(() -> FileUtils.relativize(any(Path.class), any(Path.class))).thenCallRealMethod();
+
+ assertThat(unifyPath(FileUtils.projectRelativize(path)))
+ .isEqualTo(unifyPath(expectedResult));
+
+ assertThat(unifyPath(FileUtils.projectRelativize(Path.of(path))))
+ .isEqualTo(unifyPath(expectedResult));
+ }
+ }
+
+ @Test(dataProvider = "pathsToRelativize")
+ public void workingDirectoryRelativizeTest(String directory, String path, String expectedResult, boolean windowsOnly) {
+ if (windowsOnly && !isWindows()) {
+ return;
+ }
+ try (var mocked = mockStatic(FileUtils.class)) {
+ mocked.when(FileUtils::getWorkingDirectory).thenReturn(directory);
+ mocked.when(() -> FileUtils.workingDirectoryRelativize(anyString())).thenCallRealMethod();
+ mocked.when(() -> FileUtils.workingDirectoryRelativize(any(Path.class))).thenCallRealMethod();
+ mocked.when(() -> FileUtils.relativize(any(Path.class), any(Path.class))).thenCallRealMethod();
+
+ assertThat(unifyPath(FileUtils.workingDirectoryRelativize(path)))
+ .isEqualTo(unifyPath(expectedResult));
+
+ assertThat(unifyPath(FileUtils.workingDirectoryRelativize(Path.of(path))))
+ .isEqualTo(unifyPath(expectedResult));
+ }
+ }
+
private static boolean isWindows() {
return System.getProperty("os.name").toLowerCase().contains("win");
}