Basic functioning plugin completed.
This commit is contained in:
parent
fd1961d5f3
commit
4bf7d5f82f
35
.devcontainer/devcontainer.json
Normal file
35
.devcontainer/devcontainer.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
|
||||||
|
// README at: https://github.com/devcontainers/templates/tree/main/src/java
|
||||||
|
{
|
||||||
|
"name": "Java",
|
||||||
|
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
|
||||||
|
"image": "mcr.microsoft.com/devcontainers/java:1-21-bullseye",
|
||||||
|
|
||||||
|
"features": {
|
||||||
|
"ghcr.io/devcontainers/features/java:1": {
|
||||||
|
"version": "none",
|
||||||
|
"installMaven": "true",
|
||||||
|
"installGradle": "false"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"customizations": {
|
||||||
|
"vscode": {
|
||||||
|
"extensions": [
|
||||||
|
"redhat.java",
|
||||||
|
"redhat.vscode-xml"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||||
|
// "forwardPorts": [],
|
||||||
|
|
||||||
|
// Use 'postCreateCommand' to run commands after the container is created.
|
||||||
|
// "postCreateCommand": "java -version",
|
||||||
|
|
||||||
|
// Configure tool-specific properties.
|
||||||
|
// "customizations": {},
|
||||||
|
|
||||||
|
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
|
||||||
|
// "remoteUser": "root"
|
||||||
|
}
|
130
.gitignore
vendored
Normal file
130
.gitignore
vendored
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
# File created using '.gitignore Generator' for Visual Studio Code: https://bit.ly/vscode-gig
|
||||||
|
# Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode,linux,gradle,java,kotlin,maven
|
||||||
|
# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode,linux,gradle,java,kotlin,maven
|
||||||
|
|
||||||
|
### Java ###
|
||||||
|
# Compiled class file
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Log file
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# BlueJ files
|
||||||
|
*.ctxt
|
||||||
|
|
||||||
|
# Mobile Tools for Java (J2ME)
|
||||||
|
.mtj.tmp/
|
||||||
|
|
||||||
|
# Package Files #
|
||||||
|
*.jar
|
||||||
|
*.war
|
||||||
|
*.nar
|
||||||
|
*.ear
|
||||||
|
*.zip
|
||||||
|
*.tar.gz
|
||||||
|
*.rar
|
||||||
|
|
||||||
|
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||||
|
hs_err_pid*
|
||||||
|
replay_pid*
|
||||||
|
|
||||||
|
### Kotlin ###
|
||||||
|
# Compiled class file
|
||||||
|
|
||||||
|
# Log file
|
||||||
|
|
||||||
|
# BlueJ files
|
||||||
|
|
||||||
|
# Mobile Tools for Java (J2ME)
|
||||||
|
|
||||||
|
# Package Files #
|
||||||
|
|
||||||
|
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||||
|
|
||||||
|
### Linux ###
|
||||||
|
*~
|
||||||
|
|
||||||
|
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||||
|
.fuse_hidden*
|
||||||
|
|
||||||
|
# KDE directory preferences
|
||||||
|
.directory
|
||||||
|
|
||||||
|
# Linux trash folder which might appear on any partition or disk
|
||||||
|
.Trash-*
|
||||||
|
|
||||||
|
# .nfs files are created when an open file is removed but is still being accessed
|
||||||
|
.nfs*
|
||||||
|
|
||||||
|
### Maven ###
|
||||||
|
target/
|
||||||
|
pom.xml.tag
|
||||||
|
pom.xml.releaseBackup
|
||||||
|
pom.xml.versionsBackup
|
||||||
|
pom.xml.next
|
||||||
|
release.properties
|
||||||
|
dependency-reduced-pom.xml
|
||||||
|
buildNumber.properties
|
||||||
|
.mvn/timing.properties
|
||||||
|
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
|
||||||
|
.mvn/wrapper/maven-wrapper.jar
|
||||||
|
|
||||||
|
# Eclipse m2e generated files
|
||||||
|
# Eclipse Core
|
||||||
|
.project
|
||||||
|
# JDT-specific (Eclipse Java Development Tools)
|
||||||
|
.classpath
|
||||||
|
|
||||||
|
### VisualStudioCode ###
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
!.vscode/*.code-snippets
|
||||||
|
|
||||||
|
# Local History for Visual Studio Code
|
||||||
|
.history/
|
||||||
|
|
||||||
|
# Built Visual Studio Code Extensions
|
||||||
|
*.vsix
|
||||||
|
|
||||||
|
### VisualStudioCode Patch ###
|
||||||
|
# Ignore all local history of files
|
||||||
|
.history
|
||||||
|
.ionide
|
||||||
|
|
||||||
|
### Gradle ###
|
||||||
|
.gradle
|
||||||
|
**/build/
|
||||||
|
!src/**/build/
|
||||||
|
|
||||||
|
# Ignore Gradle GUI config
|
||||||
|
gradle-app.setting
|
||||||
|
|
||||||
|
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||||
|
!gradle-wrapper.jar
|
||||||
|
|
||||||
|
# Avoid ignore Gradle wrappper properties
|
||||||
|
!gradle-wrapper.properties
|
||||||
|
|
||||||
|
# Cache of project
|
||||||
|
.gradletasknamecache
|
||||||
|
|
||||||
|
# Eclipse Gradle plugin generated files
|
||||||
|
# Eclipse Core
|
||||||
|
# JDT-specific (Eclipse Java Development Tools)
|
||||||
|
|
||||||
|
### Gradle Patch ###
|
||||||
|
# Java heap dump
|
||||||
|
*.hprof
|
||||||
|
|
||||||
|
# End of https://www.toptal.com/developers/gitignore/api/visualstudiocode,linux,gradle,java,kotlin,maven
|
||||||
|
|
||||||
|
# Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option)
|
||||||
|
|
||||||
|
buildtools/*
|
||||||
|
!buildtools/install.sh
|
||||||
|
devserver/*
|
||||||
|
!devserver/start.sh
|
||||||
|
!devserver/loadplugin.sh
|
4
.vscode/settings.json
vendored
Normal file
4
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"java.configuration.updateBuildConfiguration": "automatic",
|
||||||
|
"java.compile.nullAnalysis.mode": "automatic"
|
||||||
|
}
|
15
.vscode/tasks.json
vendored
Normal file
15
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"type": "java (buildArtifact)",
|
||||||
|
"targetPath": "${workspaceFolder}/devserver/plugins/${workspaceFolderBasename}.jar",
|
||||||
|
"elements": [
|
||||||
|
"${compileOutput}",
|
||||||
|
"${dependencies}"
|
||||||
|
],
|
||||||
|
"problemMatcher": [],
|
||||||
|
"label": "Build SpigotResourceSync to plugins"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
6
buildtools/install.sh
Normal file
6
buildtools/install.sh
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
curl -o BuildTools.jar https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar
|
||||||
|
java -jar BuildTools.jar --rev 1.20.4 --final-name spigot.jar
|
||||||
|
cp spigot.jar ../devserver/.
|
||||||
|
echo "Moved spigot.jar to ../devserver/."
|
3
devserver/loadplugin.sh
Normal file
3
devserver/loadplugin.sh
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
cp ../target/*.jar ./plugins/.
|
3
devserver/start.sh
Executable file
3
devserver/start.sh
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
java -Xmx2G -XX:+UseG1GC -jar spigot.jar nogui
|
58
pom.xml
Normal file
58
pom.xml
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>systems.reslate.entertainment.spigotresourcesync</groupId>
|
||||||
|
<artifactId>spigotresourcesync</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>21</maven.compiler.source>
|
||||||
|
<maven.compiler.target>21</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>spigot-repo</id>
|
||||||
|
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.spigotmc</groupId>
|
||||||
|
<artifactId>spigot-api</artifactId>
|
||||||
|
<version>1.20.4-R0.1-SNAPSHOT</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-io</groupId>
|
||||||
|
<artifactId>commons-io</artifactId>
|
||||||
|
<version>2.17.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.dataformat</groupId>
|
||||||
|
<artifactId>jackson-dataformat-yaml</artifactId>
|
||||||
|
<version>2.18.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||||
|
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||||
|
<version>2.18.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-core</artifactId>
|
||||||
|
<version>2.18.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-engine</artifactId>
|
||||||
|
<version>5.11.0-M2</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,121 @@
|
|||||||
|
package solutions.reslate.entertainment.spigotresourcesync;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import org.bukkit.configuration.InvalidConfigurationException;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
|
||||||
|
import solutions.reslate.entertainment.spigotresourcesync.data.Configuration;
|
||||||
|
import solutions.reslate.entertainment.spigotresourcesync.events.ObjectLoadListener;
|
||||||
|
import solutions.reslate.entertainment.spigotresourcesync.serialisation.Serialiser;
|
||||||
|
|
||||||
|
public class ConfigManager extends FileConfiguration {
|
||||||
|
private Serialiser<Configuration> serialiser;
|
||||||
|
private Configuration config;
|
||||||
|
private File file;
|
||||||
|
private Logger logger;
|
||||||
|
private Collection<ObjectLoadListener<Configuration>> configLoadListener;
|
||||||
|
|
||||||
|
|
||||||
|
public ConfigManager(File file, Serialiser<Configuration> serialiser, Logger logger) {
|
||||||
|
super();
|
||||||
|
this.serialiser = serialiser;
|
||||||
|
this.config = new Configuration();
|
||||||
|
this.file = file;
|
||||||
|
this.logger = logger;
|
||||||
|
this.configLoadListener = new HashSet<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void flush() {
|
||||||
|
try {
|
||||||
|
save(this.file);
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.severe(String.format("Unable to save configuration to \"%s\". %s", this.file.getAbsolutePath(), e.getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save(String file) throws IOException {
|
||||||
|
this.save(new File(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save(File file) throws IOException {
|
||||||
|
this.serialiser.flushTo(file, this.config);
|
||||||
|
logger.info(String.format("Saved configuration to \"%s\".", this.file.getAbsolutePath()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load() {
|
||||||
|
try {
|
||||||
|
this.load(file);
|
||||||
|
} catch (IOException | InvalidConfigurationException e) {
|
||||||
|
logger.severe(String.format("Unable to load configuration from \"%s\".", file.getAbsolutePath(), e.getMessage()));
|
||||||
|
if (file.exists()) {
|
||||||
|
logger.severe(String.format("Found pre-existing file. No overwriting will occur. Delete \"%s\" and restart to generate new configuration.", this.file.getAbsolutePath()));
|
||||||
|
} else {
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load(String file) throws FileNotFoundException, IOException, InvalidConfigurationException {
|
||||||
|
this.load(new File(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load(File file) throws FileNotFoundException, IOException, InvalidConfigurationException {
|
||||||
|
try (FileReader reader = new FileReader(file)) {
|
||||||
|
this.load(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load(Reader reader) throws IOException, InvalidConfigurationException {
|
||||||
|
this.config = this.serialiser.load(reader, Configuration.class);
|
||||||
|
logger.info(String.format("Successfully loaded configuration from \"%s\".", this.file.getAbsolutePath()));
|
||||||
|
onLoadConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Configuration getConfiguration() {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onLoadConfig() {
|
||||||
|
for (ObjectLoadListener<Configuration> objectUpdateListener : configLoadListener) {
|
||||||
|
objectUpdateListener.objectLoaded(config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String saveToString() {
|
||||||
|
return serialiser.serialize(this.config);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadFromString(String contents) throws InvalidConfigurationException {
|
||||||
|
this.config = serialiser.deserialize(contents, Configuration.class);
|
||||||
|
onLoadConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addConfigLoadListener(ObjectLoadListener<Configuration> listener) {
|
||||||
|
this.configLoadListener.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeConfigLoadListener(ObjectLoadListener<Configuration> listener) {
|
||||||
|
this.configLoadListener.remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetConfiguration() {
|
||||||
|
this.config = new Configuration();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
package solutions.reslate.entertainment.spigotresourcesync;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
import solutions.reslate.entertainment.spigotresourcesync.serialisation.JacksonYamlSerialiser;
|
||||||
|
import solutions.reslate.entertainment.spigotresourcesync.synchronisation.ApacheCommonsIOSynchroniser;
|
||||||
|
|
||||||
|
public class SpigotResourceSync extends JavaPlugin {
|
||||||
|
private ConfigManager configManager;
|
||||||
|
private SyncListManager syncListManager;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisable() {
|
||||||
|
configManager.flush();
|
||||||
|
super.onDisable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoad() {
|
||||||
|
configManager = new ConfigManager(new File("plugins", getName() + ".yml"), new JacksonYamlSerialiser<>(), getLogger());
|
||||||
|
configManager.load();
|
||||||
|
syncListManager = new SyncListManager(configManager.getConfiguration(), new ApacheCommonsIOSynchroniser(), getLogger());
|
||||||
|
configManager.addConfigLoadListener(syncListManager);
|
||||||
|
if (configManager.getConfiguration().getSyncOnLoad()) {
|
||||||
|
syncListManager.synchroniseAllSyncList();
|
||||||
|
}
|
||||||
|
super.onLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
super.onEnable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileConfiguration getConfig() {
|
||||||
|
return configManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveConfig() {
|
||||||
|
configManager.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveDefaultConfig() {
|
||||||
|
configManager.resetConfiguration();
|
||||||
|
configManager.flush();
|
||||||
|
super.saveDefaultConfig();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package solutions.reslate.entertainment.spigotresourcesync;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import solutions.reslate.entertainment.spigotresourcesync.data.Configuration;
|
||||||
|
import solutions.reslate.entertainment.spigotresourcesync.data.SyncPair;
|
||||||
|
import solutions.reslate.entertainment.spigotresourcesync.events.ObjectLoadListener;
|
||||||
|
import solutions.reslate.entertainment.spigotresourcesync.synchronisation.Synchroniser;
|
||||||
|
|
||||||
|
public class SyncListManager implements ObjectLoadListener<Configuration> {
|
||||||
|
private Configuration configuration;
|
||||||
|
private Synchroniser synchroniser;
|
||||||
|
private Logger logger;
|
||||||
|
|
||||||
|
public SyncListManager(Configuration configuration, Synchroniser synchroniser, Logger logger) {
|
||||||
|
super();
|
||||||
|
this.logger = logger;
|
||||||
|
this.configuration = configuration;
|
||||||
|
this.synchroniser = synchroniser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void synchroniseAllSyncList() {
|
||||||
|
logger.info("Synchronising all sync pairs...");
|
||||||
|
for (SyncPair syncPair : this.configuration.getSyncList().gatherAllSyncPairs()) {
|
||||||
|
File source = new File(syncPair.getSource());
|
||||||
|
File dest = new File(syncPair.getDestination());
|
||||||
|
try {
|
||||||
|
synchroniser.sync(source, dest);
|
||||||
|
logger.info(String.format("Synchronised \"%s\" to \"%s\"!", source.getName(), dest.getName()));
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.warning(String.format("Failed to synchronise \"%s\" to \"%s\". %s", source.getAbsolutePath(), dest.getAbsolutePath(), e.getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.info("Done synchronising.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void objectLoaded(Configuration obj) {
|
||||||
|
logger.info("Updating synchronisation list due to recently loading configuration...");
|
||||||
|
this.configuration = obj;
|
||||||
|
synchroniseAllSyncList();
|
||||||
|
logger.info("Done.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package solutions.reslate.entertainment.spigotresourcesync.data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class Configuration implements Serializable {
|
||||||
|
private boolean enabled;
|
||||||
|
private boolean syncOnLoad;
|
||||||
|
private SyncList syncList;
|
||||||
|
|
||||||
|
public Configuration() {
|
||||||
|
super();
|
||||||
|
enabled = true;
|
||||||
|
syncOnLoad = true;
|
||||||
|
syncList = new SyncList();
|
||||||
|
syncList.addSynchronisationPair("exampleA", "exampleB", "general");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getSyncOnLoad() {
|
||||||
|
return syncOnLoad;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSyncOnLoad(boolean syncOnLoad) {
|
||||||
|
this.syncOnLoad = syncOnLoad;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SyncList getSyncList() {
|
||||||
|
return syncList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSyncList(SyncList syncList) {
|
||||||
|
this.syncList = syncList;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
package solutions.reslate.entertainment.spigotresourcesync.data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.SequencedCollection;
|
||||||
|
import java.util.SequencedMap;
|
||||||
|
|
||||||
|
|
||||||
|
public class SyncList implements Serializable {
|
||||||
|
private SequencedMap<String, SequencedCollection<SyncPair>> syncPairs;
|
||||||
|
|
||||||
|
public SyncList() {
|
||||||
|
super();
|
||||||
|
this.syncPairs = new LinkedHashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SyncPair> gatherAllSyncPairs() {
|
||||||
|
List<SyncPair> allSyncPairs = new ArrayList<>();
|
||||||
|
for (SequencedCollection<SyncPair> syncPairs : this.syncPairs.values()) {
|
||||||
|
allSyncPairs.addAll(syncPairs);
|
||||||
|
}
|
||||||
|
return allSyncPairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSynchronisationPair(String source, String dest, String group) {
|
||||||
|
this.addSynchronisationPair(new SyncPair(source, dest), group);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSynchronisationPair(SyncPair syncPair, String group) {
|
||||||
|
addSynchronisationGroup(group);
|
||||||
|
this.syncPairs.get(group).add(syncPair);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeSynchronisationSet(String source, String dest, String group) {
|
||||||
|
if (this.syncPairs.containsKey(group)) {
|
||||||
|
this.syncPairs.get(group).remove(new SyncPair(source, dest));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSynchronisationGroup(String group) {
|
||||||
|
if (!this.syncPairs.containsKey(group)) {
|
||||||
|
this.syncPairs.put(group, new LinkedHashSet<>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeSynchronisationGroup(String group) {
|
||||||
|
if (this.syncPairs.containsKey(group)) {
|
||||||
|
this.syncPairs.remove(group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> gatherSynchronisationGroups() {
|
||||||
|
return new ArrayList<>(this.syncPairs.keySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
public SequencedMap<String, SequencedCollection<SyncPair>> getSyncPairs() {
|
||||||
|
return syncPairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSyncPairs(SequencedMap<String, SequencedCollection<SyncPair>> syncPairs) {
|
||||||
|
this.syncPairs = syncPairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
package solutions.reslate.entertainment.spigotresourcesync.data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class SyncPair implements Serializable {
|
||||||
|
private String source;
|
||||||
|
private String destination;
|
||||||
|
|
||||||
|
public SyncPair(String source, String destination) {
|
||||||
|
super();
|
||||||
|
this.source = source;
|
||||||
|
this.destination = destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SyncPair() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSource(String source) {
|
||||||
|
this.source = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDestination(String destination) {
|
||||||
|
this.destination = destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSource() {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDestination() {
|
||||||
|
return destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(this.source, this.destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SyncPair syncPair = (SyncPair) obj;
|
||||||
|
return this.source.equals(syncPair.source)
|
||||||
|
&& this.destination.equals(syncPair.destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("(%s, %s)", this.source, this.destination);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package solutions.reslate.entertainment.spigotresourcesync.events;
|
||||||
|
|
||||||
|
import java.util.EventListener;
|
||||||
|
|
||||||
|
public interface ObjectLoadListener<T> extends EventListener {
|
||||||
|
void objectLoaded(T obj);
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
package solutions.reslate.entertainment.spigotresourcesync.serialisation;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Reader;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||||
|
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
|
||||||
|
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.Feature;
|
||||||
|
|
||||||
|
public class JacksonYamlSerialiser<T> implements Serialiser<T> {
|
||||||
|
|
||||||
|
private ObjectMapper mapper;
|
||||||
|
|
||||||
|
public JacksonYamlSerialiser() {
|
||||||
|
super();
|
||||||
|
YAMLFactory yamlFactory = new YAMLFactory()
|
||||||
|
.disable(Feature.WRITE_DOC_START_MARKER);
|
||||||
|
mapper = new ObjectMapper(yamlFactory)
|
||||||
|
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void flushTo(File file, T serialisable) throws IOException {
|
||||||
|
try (FileWriter writer = new FileWriter(file)) {
|
||||||
|
mapper.writeValue(writer, serialisable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T load(File file, Class<T> type) throws IOException {
|
||||||
|
try (FileReader reader = new FileReader(file)) {
|
||||||
|
return this.load(reader, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T load(Reader reader, Class<T> type) throws IOException {
|
||||||
|
try {
|
||||||
|
return mapper.readValue(reader, type);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String serialize(T serialisable) {
|
||||||
|
try {
|
||||||
|
return mapper.writeValueAsString(serialisable);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
throw new IllegalArgumentException("Given type cannot be serialised.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T deserialize(String data, Class<T> type) {
|
||||||
|
try {
|
||||||
|
return mapper.readValue(data, type);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
throw new IllegalArgumentException("Given string cannot be deserialised.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package solutions.reslate.entertainment.spigotresourcesync.serialisation;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Reader;
|
||||||
|
|
||||||
|
public interface Serialiser<T> {
|
||||||
|
void flushTo(File file, T serialisable) throws IOException;
|
||||||
|
String serialize(T serialisable);
|
||||||
|
T load(File file, Class<T> type) throws IOException;
|
||||||
|
T load(Reader reader, Class<T> type) throws IOException;
|
||||||
|
T deserialize(String data, Class<T> type);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package solutions.reslate.entertainment.spigotresourcesync.synchronisation;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
|
||||||
|
public class ApacheCommonsIOSynchroniser implements Synchroniser {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sync(File source, File dest, File root) throws IOException {
|
||||||
|
if (root != null) {
|
||||||
|
source = Path.of(root.getPath(), source.getPath()).toFile();
|
||||||
|
source = Path.of(root.getPath(), dest.getPath()).toFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source.isDirectory()) {
|
||||||
|
if (dest.isDirectory()) {
|
||||||
|
FileUtils.copyDirectory(source, dest);
|
||||||
|
} else {
|
||||||
|
throw new IOException("Cannot synchronise directy to non-directory!");
|
||||||
|
// TODO add more detail to error message.
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (dest.isDirectory()) {
|
||||||
|
FileUtils.copyFileToDirectory(source, dest);
|
||||||
|
} else {
|
||||||
|
FileUtils.copyFile(source, dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sync(String source, String dest, String root) throws IOException {
|
||||||
|
this.sync(new File(source), new File(dest), root != null ? new File(root) : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sync(File source, File dest) throws IOException {
|
||||||
|
sync(source, dest, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sync(String source, String dest) throws IOException {
|
||||||
|
sync(source, dest, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package solutions.reslate.entertainment.spigotresourcesync.synchronisation;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public interface Synchroniser {
|
||||||
|
void sync(File source, File dest, File root) throws IOException;
|
||||||
|
void sync(File source, File dest) throws IOException;
|
||||||
|
void sync(String source, String dest, String root) throws IOException;
|
||||||
|
void sync(String source, String dest) throws IOException;
|
||||||
|
}
|
3
src/main/resources/plugin.yml
Normal file
3
src/main/resources/plugin.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
name: SpigotResourceSync
|
||||||
|
version: 1.0.0
|
||||||
|
main: solutions.reslate.entertainment.spigotresourcesync.SpigotResourceSync
|
@ -0,0 +1,32 @@
|
|||||||
|
package solutions.reslate.entertainment.spigotresourcesync;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import solutions.reslate.entertainment.spigotresourcesync.data.Configuration;
|
||||||
|
import solutions.reslate.entertainment.spigotresourcesync.data.SyncPair;
|
||||||
|
import solutions.reslate.entertainment.spigotresourcesync.serialisation.JacksonYamlSerialiser;
|
||||||
|
import solutions.reslate.entertainment.spigotresourcesync.serialisation.Serialiser;
|
||||||
|
|
||||||
|
public class TestConfigManager {
|
||||||
|
@Test
|
||||||
|
void persistConfiguration() throws IOException {
|
||||||
|
File dummyConfig = File.createTempFile("dummy_config", ".yml");
|
||||||
|
Serialiser<Configuration> dummySerialiser = new JacksonYamlSerialiser<>();
|
||||||
|
Logger logger = Logger.getLogger(this.getClass().getName());
|
||||||
|
ConfigManager initialConfigManager = new ConfigManager(dummyConfig, dummySerialiser, logger);
|
||||||
|
SyncPair dummySyncPair = new SyncPair("abc", "def");
|
||||||
|
initialConfigManager.getConfiguration().getSyncList().addSynchronisationPair(dummySyncPair, "a");
|
||||||
|
initialConfigManager.flush();
|
||||||
|
assumeTrue(dummyConfig.exists());
|
||||||
|
ConfigManager finalConfigManager = new ConfigManager(dummyConfig, dummySerialiser, logger);
|
||||||
|
finalConfigManager.load();
|
||||||
|
assertEquals(dummySyncPair, finalConfigManager.getConfiguration().getSyncList().gatherAllSyncPairs().get(0));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package solutions.reslate.entertainment.spigotresourcesync;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class TestSyncListManager {
|
||||||
|
@Test
|
||||||
|
void testDirectorySync() {
|
||||||
|
// TODO Write directory sync test.
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package solutions.reslate.entertainment.spigotresourcesync.data;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class TestSynchronisationPair {
|
||||||
|
@Test
|
||||||
|
void dataEqualsThereforeObjectEquals() {
|
||||||
|
SyncPair firstPair = new SyncPair("abc", "def");
|
||||||
|
SyncPair secondPair = new SyncPair("abc", "def");
|
||||||
|
assertEquals(firstPair, secondPair);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
package solutions.reslate.entertainment.spigotresourcesync.serialisation;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.SequencedCollection;
|
||||||
|
import java.util.SequencedMap;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import solutions.reslate.entertainment.spigotresourcesync.data.SyncPair;
|
||||||
|
|
||||||
|
public class TestJacksonYamlSerialiser {
|
||||||
|
@Test
|
||||||
|
void testListSerialisation() throws IOException {
|
||||||
|
ArrayList<String> dummyList = new ArrayList<>();
|
||||||
|
dummyList.add("abc");
|
||||||
|
dummyList.add("def");
|
||||||
|
File dummyFile = File.createTempFile("dummy_file", ".yml");
|
||||||
|
JacksonYamlSerialiser<List<String>> dummyJacksonYamlSerialiser = new JacksonYamlSerialiser<>();
|
||||||
|
dummyJacksonYamlSerialiser.flushTo(dummyFile, dummyList);
|
||||||
|
assumeTrue(dummyFile.exists());
|
||||||
|
List<String> writtenLines = Files.readAllLines(dummyFile.toPath());
|
||||||
|
assertEquals(2, writtenLines.size());
|
||||||
|
assertEquals("- \"abc\"", writtenLines.get(0));
|
||||||
|
assertEquals("- \"def\"", writtenLines.get(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSyncPairSerialisation() throws IOException {
|
||||||
|
File dummyFile = File.createTempFile("dummy_file", ".yml");
|
||||||
|
SyncPair dummySyncPair = new SyncPair("abc", "def");
|
||||||
|
JacksonYamlSerialiser<SyncPair> dummyJacksonYamlSerialiser = new JacksonYamlSerialiser<>();
|
||||||
|
dummyJacksonYamlSerialiser.flushTo(dummyFile, dummySyncPair);
|
||||||
|
assumeTrue(dummyFile.exists());
|
||||||
|
List<String> writtenLines = Files.readAllLines(dummyFile.toPath());
|
||||||
|
assertEquals(2, writtenLines.size());
|
||||||
|
assertEquals("source: \"abc\"", writtenLines.get(0));
|
||||||
|
assertEquals("destination: \"def\"", writtenLines.get(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSequencedCollectionSerialisation() throws IOException {
|
||||||
|
File dummyFile = File.createTempFile("dummy_file", ".yml");
|
||||||
|
SequencedCollection<String> collection = new LinkedHashSet<>();
|
||||||
|
collection.add("abc");
|
||||||
|
collection.add("def");
|
||||||
|
JacksonYamlSerialiser<SequencedCollection<String>> dummyJacksonYamlSerialiser = new JacksonYamlSerialiser<>();
|
||||||
|
dummyJacksonYamlSerialiser.flushTo(dummyFile, collection);
|
||||||
|
assumeTrue(dummyFile.exists());
|
||||||
|
List<String> writtenLines = Files.readAllLines(dummyFile.toPath());
|
||||||
|
assertEquals(2, writtenLines.size());
|
||||||
|
assertEquals("- \"abc\"", writtenLines.get(0));
|
||||||
|
assertEquals("- \"def\"", writtenLines.get(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSequencedMapSerialisation() throws IOException {
|
||||||
|
File dummyFile = File.createTempFile("dummy_file", ".yml");
|
||||||
|
SequencedMap<String, String> collection = new LinkedHashMap<>();
|
||||||
|
collection.put("abc", "def");
|
||||||
|
collection.put("123", "456");
|
||||||
|
JacksonYamlSerialiser<SequencedMap<String, String>> dummyJacksonYamlSerialiser = new JacksonYamlSerialiser<>();
|
||||||
|
dummyJacksonYamlSerialiser.flushTo(dummyFile, collection);
|
||||||
|
assumeTrue(dummyFile.exists());
|
||||||
|
List<String> writtenLines = Files.readAllLines(dummyFile.toPath());
|
||||||
|
assertEquals(2, writtenLines.size());
|
||||||
|
assertEquals("abc: \"def\"", writtenLines.get(0));
|
||||||
|
assertEquals("\"123\": \"456\"", writtenLines.get(1));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package solutions.reslate.entertainment.spigotresourcesync.synchroniser;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import solutions.reslate.entertainment.spigotresourcesync.synchronisation.ApacheCommonsIOSynchroniser;
|
||||||
|
|
||||||
|
public class TestApacheCommonsIOSynchroniser {
|
||||||
|
@Test
|
||||||
|
void testDir2DirSync() throws IOException {
|
||||||
|
ApacheCommonsIOSynchroniser dummySynchroniser = new ApacheCommonsIOSynchroniser();
|
||||||
|
File dummyDirA = Files.createTempDirectory("dir_A").toFile();
|
||||||
|
File dummyDirB = Files.createTempDirectory("dir_B").toFile();
|
||||||
|
File dummyFileA = File.createTempFile("file_A", ".txt", dummyDirA);
|
||||||
|
dummySynchroniser.sync(dummyDirA, dummyDirB);
|
||||||
|
assertTrue(new File(dummyDirB, dummyFileA.getName()).exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testFile2DirSync() throws IOException {
|
||||||
|
ApacheCommonsIOSynchroniser dummySynchroniser = new ApacheCommonsIOSynchroniser();
|
||||||
|
File dummyDirA = Files.createTempDirectory("dir_A").toFile();
|
||||||
|
File dummyDirB = Files.createTempDirectory("dir_B").toFile();
|
||||||
|
File dummyFileA = File.createTempFile("file_A", ".txt", dummyDirA);
|
||||||
|
dummySynchroniser.sync(dummyFileA, dummyDirB);
|
||||||
|
assertTrue(new File(dummyDirB, dummyFileA.getName()).exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testFile2FileSync() throws IOException {
|
||||||
|
ApacheCommonsIOSynchroniser dummySynchroniser = new ApacheCommonsIOSynchroniser();
|
||||||
|
File dummyDirA = Files.createTempDirectory("dir_A").toFile();
|
||||||
|
File dummyDirB = Files.createTempDirectory("dir_B").toFile();
|
||||||
|
File dummyFileA = File.createTempFile("file_A", ".txt", dummyDirA);
|
||||||
|
File dummyFileB = new File(dummyDirB, "file_B");
|
||||||
|
dummySynchroniser.sync(dummyFileA, dummyFileB);
|
||||||
|
assertTrue(dummyFileB.exists());
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user