diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 0000000..edfbc0b
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1 @@
+* joshua@hypera.dev
\ No newline at end of file
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..7957476
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,10 @@
+version: 2
+updates:
+ - package-ecosystem: "maven"
+ directory: "/"
+ schedule:
+ interval: "daily"
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "daily"
\ No newline at end of file
diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml
index e054d30..937b596 100644
--- a/.github/workflows/publish-release.yml
+++ b/.github/workflows/publish-release.yml
@@ -10,7 +10,7 @@ jobs:
- name: Set up Java
uses: actions/setup-java@v2
with:
- java-version: '8'
+ java-version: '11'
distribution: 'adopt'
server-id: hypera-releases
server-username: MAVEN_USERNAME
diff --git a/.github/workflows/publish-snapshot.yml b/.github/workflows/publish-snapshot.yml
deleted file mode 100644
index 58937fe..0000000
--- a/.github/workflows/publish-snapshot.yml
+++ /dev/null
@@ -1,22 +0,0 @@
-name: Publish Snapshot
-on:
- push:
- branches: [main]
-jobs:
- publish:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - name: Set up Java
- uses: actions/setup-java@v2
- with:
- java-version: '8'
- distribution: 'adopt'
- server-id: hypera-snapshots
- server-username: MAVEN_USERNAME
- server-password: MAVEN_PASSWORD
- - name: Publish package
- run: mvn --batch-mode deploy
- env:
- MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
- MAVEN_PASSWORD: ${{ secrets.MAVEN_TOKEN }}
diff --git a/SECURITY.md b/SECURITY.md
index 7b526f9..363dd7c 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -4,6 +4,7 @@
| Version | Supported |
| :------ | -----------------: |
+| 3.x.x | :white_check_mark: |
| 2.0.x | :white_check_mark: |
| < 2.0 | :x: |
diff --git a/pom.xml b/pom.xml
index 50c81d1..b018940 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,7 +22,7 @@
dev.hypera
UpdateLib
- 2.1.2
+ 3.1.2-SNAPSHOT
jar
UpdateLib
@@ -113,7 +113,7 @@
-
+
com.googlecode.json-simple
json-simple
@@ -126,13 +126,6 @@
-
-
-
- org.apache.maven
- maven-artifact
- 3.6.3
-
\ No newline at end of file
diff --git a/src/main/java/dev/hypera/updatelib/UpdateLib.java b/src/main/java/dev/hypera/updatelib/UpdateLib.java
new file mode 100644
index 0000000..a9fab12
--- /dev/null
+++ b/src/main/java/dev/hypera/updatelib/UpdateLib.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2021 Joshua Sing
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package dev.hypera.updatelib;
+
+import dev.hypera.updatelib.annotations.RunAsync;
+import dev.hypera.updatelib.checkers.UpdateChecker;
+import dev.hypera.updatelib.data.CheckData;
+import dev.hypera.updatelib.objects.UpdateStatus;
+import dev.hypera.updatelib.objects.UpdateStatusBuilder;
+
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.function.Consumer;
+
+public class UpdateLib {
+
+ private final static String VERSION = "3.1.2-SNAPSHOT"; // Current UpdateLib version.
+
+ private final long resourceId;
+ private final String currentVersion;
+ private final int connectionTimeout;
+
+ private final UpdateChecker updateChecker;
+
+ private final Consumer completeAction;
+ private final Consumer errorHandler;
+
+ private UpdateStatus lastStatus = null;
+ private long lastCheck = 0L;
+
+ /**
+ * UpdateLib Constructor - Used internally by UpdateLib.
+ *
+ * @param resourceId Resource ID.
+ * @param currentVersion Current version of the Resource.
+ * @param repeatingChecksEnabled If UpdateLib should check for updates periodically.
+ * @param interval How often UpdateLib should check for updates.
+ * @param connectionTimeout The amount of milliseconds UpdateLib should wait before timing out on requests.
+ * @param updateChecker {@link UpdateChecker} to be used by UpdateLib to check for updates.
+ * @param completeAction Action to run after UpdateLib has checked for an update.
+ * @param errorHandler Consumer to run if UpdateLib encounters an exception.
+ */
+ protected UpdateLib(long resourceId, String currentVersion, boolean repeatingChecksEnabled, long interval, int connectionTimeout, UpdateChecker updateChecker, Consumer completeAction, Consumer errorHandler) {
+ this.resourceId = resourceId;
+ this.currentVersion = currentVersion;
+ this.connectionTimeout = connectionTimeout;
+ this.updateChecker = updateChecker;
+ this.completeAction = completeAction;
+ this.errorHandler = errorHandler;
+
+ Thread thread = new Thread(this::checkNow);
+ thread.setName("UpdateLib-" + thread.getId());
+ thread.start();
+
+ if(repeatingChecksEnabled) {
+ new Timer().schedule(new TimerTask() {
+ @Override
+ public void run() {
+ checkNow();
+ }
+ }, interval);
+ }
+ }
+
+
+ /**
+ * Start an update check. It's recommended to only run this asynchronously as it may take time to fetch data from
+ * the API.
+ *
+ * @return Response - Instance of {@link UpdateStatus}
+ * @since 2.0.0-SNAPSHOT
+ */
+ @RunAsync
+ public UpdateStatus checkNow() {
+ try {
+ lastStatus = updateChecker.check(new CheckData(resourceId, currentVersion, connectionTimeout));
+ lastCheck = System.currentTimeMillis();
+ if(null != completeAction)
+ completeAction.accept(lastStatus);
+ } catch (Exception ex) {
+ if(null == errorHandler)
+ ex.printStackTrace();
+ else
+ errorHandler.accept(ex);
+ }
+
+ return lastStatus;
+ }
+
+ /**
+ * Get last stored {@link UpdateStatus}. If UpdateLib hasn't checked for an update or the last check failed, this
+ * will return null.
+ *
+ * @return Last stored {@link UpdateStatus}
+ * @since 3.0.0-SNAPSHOT
+ */
+ public UpdateStatus getLastStatus() {
+ return lastStatus;
+ }
+
+ /**
+ * Get the last time UpdateLib checked for updates.
+ *
+ * @return Last check time in milliseconds.
+ * @since 2.0.0-SNAPSHOT
+ */
+ public long getLastCheck() {
+ return lastCheck;
+ }
+
+ /**
+ * Get the current version of UpdateLib.
+ *
+ * @return Current version of UpdateLib.
+ * @since 2.1.0-SNAPSHOT
+ */
+ public static String getVersion() {
+ return VERSION;
+ }
+
+}
diff --git a/src/main/java/dev/hypera/updatelib/UpdateLibBuilder.java b/src/main/java/dev/hypera/updatelib/UpdateLibBuilder.java
index 03002d4..625fa06 100644
--- a/src/main/java/dev/hypera/updatelib/UpdateLibBuilder.java
+++ b/src/main/java/dev/hypera/updatelib/UpdateLibBuilder.java
@@ -16,33 +16,51 @@
package dev.hypera.updatelib;
-import dev.hypera.updatelib.internal.UpdateLib;
-import dev.hypera.updatelib.internal.UpdateResponse;
+import dev.hypera.updatelib.annotations.Builder;
+import dev.hypera.updatelib.checkers.UpdateChecker;
+import dev.hypera.updatelib.checkers.impl.SpigotUpdateChecker;
+import dev.hypera.updatelib.objects.UpdateStatus;
+import dev.hypera.updatelib.utils.Check;
+import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
-@SuppressWarnings("unused")
+@Builder
public class UpdateLibBuilder {
private final long resourceId;
private final String currentVersion;
private boolean repeatingChecksEnabled = true;
- private long checkInterval = 2 * (60 * (60 * 1000)); // 2 Hours
- private int connectionTimeout = 5000; // 5 Seconds
+ private long checkInterval = 2 * (60 * (60 * 1000)); // Defaults to 2 hours.
+ private int connectionTimeout = 10000; // Defaults to 10 seconds.
- private Consumer consumer = null;
+ /**
+ * Defaults to using {@link SpigotUpdateChecker}.
+ */
+ private UpdateChecker updateChecker = new SpigotUpdateChecker();
+
+ private Consumer completeAction = null;
+ private Consumer errorHandler = null; // If error handler is not provided, stack traces will be printed by UpdateLib.
+
+ /**
+ * UpdateLibBuilder Constructor - Used internally by UpdateLib.
+ *
+ * @param currentVersion Current version of the resource.
+ * @param resourceId Resource ID.
+ */
private UpdateLibBuilder(String currentVersion, long resourceId) {
+ Check.notNull("currentVersion", currentVersion);
this.currentVersion = currentVersion;
this.resourceId = resourceId;
}
/**
- * Creates a new instance of {@link UpdateLibBuilder}.
+ * Create a new instance of {@link UpdateLibBuilder}
*
* @param currentVersion Current version of the resource.
- * @param resourceId SpigotMC Resource Id.
+ * @param resourceId Resource ID.
*
* @return Instance of {@link UpdateLibBuilder}
* @since 2.0.0-SNAPSHOT
@@ -52,11 +70,11 @@ public static UpdateLibBuilder create(String currentVersion, long resourceId) {
}
/**
- * Should UpdateLib keep checking for updates? (Time defined by checkInterval)
+ * Sets if UpdateLib should check for updates periodically.
*
- * @param enabled Repeating checks enabled.
+ * @param enabled If UpdateLib should check for updates periodically.
*
- * @see #setCheckInterval(long)
+ * @return {@link UpdateLibBuilder}
* @since 2.0.0-SNAPSHOT
*/
public UpdateLibBuilder setRepeatingChecksEnabled(boolean enabled) {
@@ -65,23 +83,26 @@ public UpdateLibBuilder setRepeatingChecksEnabled(boolean enabled) {
}
/**
- * How often should UpdateLib check for updates? (Only works if repeatingChecksEnabled is true)
+ * Sets how often UpdateLib should check for updates? This is only needed if 'repeatingChecksEnabled' is true.
*
- * @param interval Interval in milliseconds.
+ * @param time Time.
+ * @param unit TimeUnit.
*
+ * @return {@link UpdateLibBuilder}
* @see #setRepeatingChecksEnabled(boolean)
* @since 2.0.0-SNAPSHOT
*/
- public UpdateLibBuilder setCheckInterval(long interval) {
- this.checkInterval = interval;
+ public UpdateLibBuilder setCheckInterval(long time, TimeUnit unit) {
+ this.checkInterval = unit.toMillis(time);
return this;
}
/**
- * After how many milliseconds should we timeout the request to SpigotMC's API?
+ * Sets the amount of milliseconds UpdateLib should wait before timing out on requests.
*
* @param timeout Timeout in milliseconds.
*
+ * @return {@link UpdateLibBuilder}
* @since 2.0.0-SNAPSHOT
*/
public UpdateLibBuilder setConnectionTimeout(int timeout) {
@@ -90,25 +111,52 @@ public UpdateLibBuilder setConnectionTimeout(int timeout) {
}
/**
- * Sets a consumer to run after UpdateLib has checked for an update.
+ * Sets the {@link UpdateChecker} to be used by UpdateLib to check for updates.
+ *
+ * @param updateChecker Instance of an {@link UpdateChecker}
+ *
+ * @return {@link UpdateLibBuilder}
+ * @since 3.0.0-SNAPSHOT
+ */
+ public UpdateLibBuilder setUpdateChecker(UpdateChecker updateChecker) {
+ this.updateChecker = updateChecker;
+ return this;
+ }
+
+ /**
+ * Sets an action to run after UpdateLib has checked for an update.
*
- * @param consumer Consumer to run after checking for an update.
+ * @param action Consumer to run after checking for an update.
*
+ * @return {@link UpdateLibBuilder}
* @since 2.1.0-SNAPSHOT
*/
- public UpdateLibBuilder setConsumer(Consumer consumer) {
- this.consumer = consumer;
+ public UpdateLibBuilder setCompleteAction(Consumer action) {
+ this.completeAction = action;
+ return this;
+ }
+
+ /**
+ * Sets an consumer to run if UpdateLib encounters an exception.
+ *
+ * @param handler Error handler.
+ *
+ * @return {@link UpdateLibBuilder}
+ * @since 3.0.0-SNAPSHOT
+ */
+ public UpdateLibBuilder setErrorHandler(Consumer handler) {
+ this.errorHandler = handler;
return this;
}
/**
- * Builds a new instance of {@link UpdateLib}.
+ * Builds a new instance of {@link UpdateLib}
*
* @return Instance of {@link UpdateLib}
* @since 2.0.0-SNAPSHOT
*/
public UpdateLib build() {
- return new UpdateLib(resourceId, currentVersion, repeatingChecksEnabled, checkInterval, connectionTimeout, consumer);
+ return new UpdateLib(resourceId, currentVersion, repeatingChecksEnabled, checkInterval, connectionTimeout, updateChecker, completeAction, errorHandler);
}
}
diff --git a/src/main/java/dev/hypera/updatelib/annotations/Builder.java b/src/main/java/dev/hypera/updatelib/annotations/Builder.java
new file mode 100644
index 0000000..2466e3f
--- /dev/null
+++ b/src/main/java/dev/hypera/updatelib/annotations/Builder.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2021 Joshua Sing
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package dev.hypera.updatelib.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation for marking a class as a Builder.
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Builder {
+
+}
diff --git a/src/main/java/dev/hypera/updatelib/annotations/Internal.java b/src/main/java/dev/hypera/updatelib/annotations/Internal.java
new file mode 100644
index 0000000..2ca481b
--- /dev/null
+++ b/src/main/java/dev/hypera/updatelib/annotations/Internal.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2021 Joshua Sing
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package dev.hypera.updatelib.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation for marking a class as for use by UpdateLib only.
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Internal {
+
+}
diff --git a/src/main/java/dev/hypera/updatelib/annotations/Required.java b/src/main/java/dev/hypera/updatelib/annotations/Required.java
new file mode 100644
index 0000000..6ee79b8
--- /dev/null
+++ b/src/main/java/dev/hypera/updatelib/annotations/Required.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2021 Joshua Sing
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package dev.hypera.updatelib.annotations;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Annotation for marking something as being required.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Required {
+
+}
diff --git a/src/main/java/dev/hypera/updatelib/annotations/RunAsync.java b/src/main/java/dev/hypera/updatelib/annotations/RunAsync.java
new file mode 100644
index 0000000..4318e86
--- /dev/null
+++ b/src/main/java/dev/hypera/updatelib/annotations/RunAsync.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2021 Joshua Sing
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package dev.hypera.updatelib.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation for marking something as needing to be run Asynchronously.
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface RunAsync {
+
+}
diff --git a/src/main/java/dev/hypera/updatelib/checkers/UpdateChecker.java b/src/main/java/dev/hypera/updatelib/checkers/UpdateChecker.java
new file mode 100644
index 0000000..f1cf763
--- /dev/null
+++ b/src/main/java/dev/hypera/updatelib/checkers/UpdateChecker.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2021 Joshua Sing
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package dev.hypera.updatelib.checkers;
+
+import dev.hypera.updatelib.data.CheckData;
+import dev.hypera.updatelib.objects.UpdateStatus;
+
+public interface UpdateChecker {
+
+ /**
+ * Check for an update.
+ *
+ * @param data Check data.
+ * @return {@link UpdateStatus}
+ * @throws Exception Any exceptions that occur while checking for updates.
+ * @since 3.0.0-SNAPSHOT
+ */
+ UpdateStatus check(CheckData data) throws Exception;
+
+}
diff --git a/src/main/java/dev/hypera/updatelib/checkers/impl/PolymartUpdateChecker.java b/src/main/java/dev/hypera/updatelib/checkers/impl/PolymartUpdateChecker.java
new file mode 100644
index 0000000..2686271
--- /dev/null
+++ b/src/main/java/dev/hypera/updatelib/checkers/impl/PolymartUpdateChecker.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2021 Joshua Sing
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package dev.hypera.updatelib.checkers.impl;
+
+import dev.hypera.updatelib.checkers.UpdateChecker;
+import dev.hypera.updatelib.data.CheckData;
+import dev.hypera.updatelib.exceptions.InvalidResourceException;
+import dev.hypera.updatelib.objects.UpdateStatus;
+import dev.hypera.updatelib.objects.UpdateStatusBuilder;
+import dev.hypera.updatelib.utils.ReaderUtils;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+
+import javax.net.ssl.HttpsURLConnection;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.URL;
+
+public class PolymartUpdateChecker implements UpdateChecker {
+
+ private static final String URL_FORMAT = "https://api.polymart.org/v1/getResourceInfo/?resource_id=%s";
+
+ /**
+ * Check for an update using Polymart's API.
+ *
+ * @param data Check data.
+ * @return {@link UpdateStatus}
+ * @throws Exception Any exceptions that occur while checking for updates.
+ * @since 3.0.0-SNAPSHOT
+ */
+ @Override
+ public UpdateStatus check(CheckData data) throws Exception {
+ URL url = new URL(String.format(URL_FORMAT, data.getResourceId()));
+
+ HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url.openConnection();
+ httpsURLConnection.setConnectTimeout(data.getTimeout());
+ httpsURLConnection.setReadTimeout(data.getTimeout());
+
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpsURLConnection.getInputStream()));
+ JSONObject json = (JSONObject) JSONValue.parse(ReaderUtils.readAll(bufferedReader));
+ bufferedReader.close();
+
+ JSONObject response = (JSONObject) json.get("response");
+ if(!((boolean) response.get("success")))
+ throw new InvalidResourceException("Cannot find Polymart resource with id '" + data.getResourceId() + "'");
+
+ String distributedVersion = ((JSONObject) ((JSONObject) ((JSONObject) response.get("resource")).get("updates")).get("latest")).get("version").toString();
+
+ return UpdateStatusBuilder.create(distributedVersion, data.getCurrentVersion()).build();
+ }
+
+}
diff --git a/src/main/java/dev/hypera/updatelib/checkers/impl/SongodaUpdateChecker.java b/src/main/java/dev/hypera/updatelib/checkers/impl/SongodaUpdateChecker.java
new file mode 100644
index 0000000..94eb9ad
--- /dev/null
+++ b/src/main/java/dev/hypera/updatelib/checkers/impl/SongodaUpdateChecker.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2021 Joshua Sing
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package dev.hypera.updatelib.checkers.impl;
+
+import dev.hypera.updatelib.checkers.UpdateChecker;
+import dev.hypera.updatelib.data.CheckData;
+import dev.hypera.updatelib.exceptions.InvalidResourceException;
+import dev.hypera.updatelib.objects.UpdateStatus;
+import dev.hypera.updatelib.objects.UpdateStatusBuilder;
+import dev.hypera.updatelib.utils.ReaderUtils;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+
+import javax.net.ssl.HttpsURLConnection;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.URL;
+
+public class SongodaUpdateChecker implements UpdateChecker {
+
+ private static final String URL_FORMAT = "https://songoda.com/api/v2/products/id/%s";
+
+ /**
+ * Check for an update using Songoda's API.
+ *
+ * @param data Check data.
+ *
+ * @return {@link UpdateStatus}
+ * @throws Exception Any exceptions that occur while checking for updates.
+ * @since 3.1.0-SNAPSHOT
+ */
+ @Override
+ public UpdateStatus check(CheckData data) throws Exception {
+ URL url = new URL(String.format(URL_FORMAT, data.getResourceId()));
+
+ HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url.openConnection();
+ httpsURLConnection.setConnectTimeout(data.getTimeout());
+ httpsURLConnection.setReadTimeout(data.getTimeout());
+
+ if(httpsURLConnection.getResponseCode() == 404)
+ throw new InvalidResourceException("Cannot find Songoda resource with id '" + data.getResourceId() + "'");
+
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpsURLConnection.getInputStream()));
+ JSONObject json = (JSONObject) JSONValue.parse(ReaderUtils.readAll(bufferedReader));
+ bufferedReader.close();
+
+ JSONObject songodaData = (JSONObject) json.get("data");
+ String distributedVersion = ((JSONObject) ((JSONArray) songodaData.get("versions")).get(0)).get("version").toString();
+
+ return UpdateStatusBuilder.create(distributedVersion, data.getCurrentVersion()).build();
+ }
+
+}
diff --git a/src/main/java/dev/hypera/updatelib/checkers/impl/SpigotLegacyUpdateChecker.java b/src/main/java/dev/hypera/updatelib/checkers/impl/SpigotLegacyUpdateChecker.java
new file mode 100644
index 0000000..a055b59
--- /dev/null
+++ b/src/main/java/dev/hypera/updatelib/checkers/impl/SpigotLegacyUpdateChecker.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2021 Joshua Sing
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package dev.hypera.updatelib.checkers.impl;
+
+import dev.hypera.updatelib.checkers.UpdateChecker;
+import dev.hypera.updatelib.data.CheckData;
+import dev.hypera.updatelib.exceptions.InvalidResourceException;
+import dev.hypera.updatelib.objects.UpdateStatus;
+import dev.hypera.updatelib.objects.UpdateStatusBuilder;
+import dev.hypera.updatelib.utils.ReaderUtils;
+
+import javax.net.ssl.HttpsURLConnection;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.URL;
+
+public class SpigotLegacyUpdateChecker implements UpdateChecker {
+
+ private static final String URL_FORMAT = "https://api.spigotmc.org/legacy/update.php?resource=%s";
+
+ /**
+ * Check for an update using SpigotMC's Legacy API.
+ *
+ * @param data Check data.
+ * @return {@link UpdateStatus}
+ * @throws Exception Any exceptions that occur while checking for updates.
+ * @since 3.0.0-SNAPSHOT
+ */
+ @Override
+ public UpdateStatus check(CheckData data) throws Exception {
+ URL url = new URL(String.format(URL_FORMAT, data.getResourceId()));
+
+ HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url.openConnection();
+ httpsURLConnection.setConnectTimeout(data.getTimeout());
+ httpsURLConnection.setReadTimeout(data.getTimeout());
+
+ if(httpsURLConnection.getResponseCode() == 404)
+ throw new InvalidResourceException("Cannot find SpigotMC resource with id '" + data.getResourceId() + "'");
+
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpsURLConnection.getInputStream()));
+ String distributedVersion = ReaderUtils.readAll(bufferedReader);
+ bufferedReader.close();
+
+ if(distributedVersion.contains("Invalid"))
+ throw new InvalidResourceException("Cannot find SpigotMC resource with id '" + data.getResourceId() + "'");
+
+ return UpdateStatusBuilder.create(distributedVersion, data.getCurrentVersion()).build();
+ }
+
+}
diff --git a/src/main/java/dev/hypera/updatelib/checkers/impl/SpigotUpdateChecker.java b/src/main/java/dev/hypera/updatelib/checkers/impl/SpigotUpdateChecker.java
new file mode 100644
index 0000000..298d3d8
--- /dev/null
+++ b/src/main/java/dev/hypera/updatelib/checkers/impl/SpigotUpdateChecker.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2021 Joshua Sing
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package dev.hypera.updatelib.checkers.impl;
+
+import dev.hypera.updatelib.checkers.UpdateChecker;
+import dev.hypera.updatelib.data.CheckData;
+import dev.hypera.updatelib.exceptions.InvalidResourceException;
+import dev.hypera.updatelib.objects.UpdateStatus;
+import dev.hypera.updatelib.objects.UpdateStatusBuilder;
+import dev.hypera.updatelib.utils.ReaderUtils;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+
+import javax.net.ssl.HttpsURLConnection;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.URL;
+
+public class SpigotUpdateChecker implements UpdateChecker {
+
+ private static final String URL_FORMAT = "https://api.spigotmc.org/simple/0.1/index.php?action=getResource&id=%s";
+
+ /**
+ * Check for an update using SpigotMC's API.
+ *
+ * @param data Check data.
+ * @return {@link UpdateStatus}
+ * @throws Exception Any exceptions that occur while checking for updates.
+ * @since 3.0.0-SNAPSHOT
+ */
+ @Override
+ public UpdateStatus check(CheckData data) throws Exception {
+ URL url = new URL(String.format(URL_FORMAT, data.getResourceId()));
+
+ HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url.openConnection();
+ httpsURLConnection.setConnectTimeout(data.getTimeout());
+ httpsURLConnection.setReadTimeout(data.getTimeout());
+
+ if(httpsURLConnection.getResponseCode() == 404)
+ throw new InvalidResourceException("Cannot find SpigotMC resource with id '" + data.getResourceId() + "'");
+
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpsURLConnection.getInputStream()));
+ JSONObject json = (JSONObject) JSONValue.parse(ReaderUtils.readAll(bufferedReader));
+ bufferedReader.close();
+
+ String distributedVersion = json.get("current_version").toString();
+
+ return UpdateStatusBuilder.create(distributedVersion, data.getCurrentVersion()).build();
+ }
+
+}
diff --git a/src/main/java/dev/hypera/updatelib/internal/UpdateResponse.java b/src/main/java/dev/hypera/updatelib/data/CheckData.java
similarity index 53%
rename from src/main/java/dev/hypera/updatelib/internal/UpdateResponse.java
rename to src/main/java/dev/hypera/updatelib/data/CheckData.java
index a681325..6f6b388 100644
--- a/src/main/java/dev/hypera/updatelib/internal/UpdateResponse.java
+++ b/src/main/java/dev/hypera/updatelib/data/CheckData.java
@@ -14,48 +14,61 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-package dev.hypera.updatelib.internal;
+package dev.hypera.updatelib.data;
-public class UpdateResponse {
+import dev.hypera.updatelib.annotations.Internal;
- private final boolean updateAvailable;
+@Internal
+public class CheckData {
+
+ private final long resourceId;
private final String currentVersion;
- private final String spigotVersion;
+ private final int timeout;
- public UpdateResponse(boolean updateAvailable, String currentVersion, String spigotVersion) {
- this.updateAvailable = updateAvailable;
+ /**
+ * CheckData Constructor - Used internally by UpdateLib.
+ *
+ * @param resourceId Resource ID.
+ * @param currentVersion Current resource version.
+ * @param timeout Connection timeout.
+ *
+ * @since 3.0.0-SNAPSHOT
+ */
+ public CheckData(long resourceId, String currentVersion, int timeout) {
+ this.resourceId = resourceId;
this.currentVersion = currentVersion;
- this.spigotVersion = spigotVersion;
+ this.timeout = timeout;
}
/**
- * Is an update available?
+ * Get resource ID.
*
- * @return Update available.
- * @since 2.0.0-SNAPSHOT
+ * @return Resource ID.
+ * @since 3.0.0-SNAPSHOT
*/
- public boolean isUpdateAvailable() {
- return updateAvailable;
+ public long getResourceId() {
+ return resourceId;
}
/**
- * Get the current version of the plugin.
+ * Get current version.
*
* @return Current version.
- * @since 2.0.0-SNAPSHOT
+ * @since 3.0.0-SNAPSHOT
*/
public String getCurrentVersion() {
return currentVersion;
}
/**
- * Get the current version of the plugin on SpigotMC.
+ * Get connection timeout.
*
- * @return Current SpigotMC version.
- * @since 2.0.0-SNAPSHOT
+ * @return Connection timeout in milliseconds.
+ * @since 3.0.0-SNAPSHOT
*/
- public String getSpigotVersion() {
- return spigotVersion;
+ public int getTimeout() {
+ return timeout;
}
+
}
diff --git a/src/main/java/dev/hypera/updatelib/exceptions/InvalidResourceException.java b/src/main/java/dev/hypera/updatelib/exceptions/InvalidResourceException.java
new file mode 100644
index 0000000..37dd473
--- /dev/null
+++ b/src/main/java/dev/hypera/updatelib/exceptions/InvalidResourceException.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2021 Joshua Sing
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package dev.hypera.updatelib.exceptions;
+
+import java.io.IOException;
+
+/**
+ * Invalid Resource Exception.
+ *
+ * @since 3.0.0-SNAPSHOT
+ */
+public class InvalidResourceException extends IOException {
+
+ public InvalidResourceException() {
+ super();
+ }
+
+ public InvalidResourceException(String s) {
+ super(s);
+ }
+
+ public InvalidResourceException(String s, Throwable throwable) {
+ super(s, throwable);
+ }
+
+ public InvalidResourceException(Throwable throwable) {
+ super(throwable);
+ }
+
+}
diff --git a/src/main/java/dev/hypera/updatelib/exceptions/VersionSchemeException.java b/src/main/java/dev/hypera/updatelib/exceptions/VersionSchemeException.java
new file mode 100644
index 0000000..dc54e5c
--- /dev/null
+++ b/src/main/java/dev/hypera/updatelib/exceptions/VersionSchemeException.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2021 Joshua Sing
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package dev.hypera.updatelib.exceptions;
+
+/**
+ * Version Scheme Exception.
+ *
+ * @since 3.0.0-SNAPSHOT
+ */
+public class VersionSchemeException extends IllegalStateException {
+
+ public VersionSchemeException() {
+ super();
+ }
+
+ public VersionSchemeException(String s) {
+ super(s);
+ }
+
+ public VersionSchemeException(String s, Throwable throwable) {
+ super(s, throwable);
+ }
+
+ public VersionSchemeException(Throwable throwable) {
+ super(throwable);
+ }
+
+}
diff --git a/src/main/java/dev/hypera/updatelib/internal/UpdateLib.java b/src/main/java/dev/hypera/updatelib/internal/UpdateLib.java
deleted file mode 100644
index 40641a7..0000000
--- a/src/main/java/dev/hypera/updatelib/internal/UpdateLib.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 2021 Joshua Sing
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-package dev.hypera.updatelib.internal;
-
-import dev.hypera.updatelib.internal.tasks.UpdateChecker;
-import dev.hypera.updatelib.internal.tasks.UpdateTask;
-
-import java.util.Timer;
-import java.util.function.Consumer;
-
-public class UpdateLib {
-
- private final static String version = "2.1.1";
-
- private final long resourceId;
- private final String currentVersion;
- private final int connectionTimeout;
- private final Consumer consumer;
-
- private long lastCheck = 0L;
- private UpdateResponse lastResponse = null;
-
- public UpdateLib(long resourceId, String currentVersion, boolean repeatingChecksEnabled, long checkInterval, int connectionTimeout, Consumer consumer) {
- this.resourceId = resourceId;
- this.currentVersion = currentVersion;
- this.connectionTimeout = connectionTimeout;
- this.consumer = consumer;
-
- Thread thread = new Thread(() -> {
- try {
- checkNow();
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- });
-
- thread.setName("UpdateLib-" + thread.getId());
- thread.start();
-
- if(repeatingChecksEnabled) {
- new Timer().schedule(new UpdateTask(resourceId, currentVersion, connectionTimeout, consumer, this), checkInterval);
- }
- }
-
- /**
- * Checks for a update now.
- *
- * @return Response (instance of {@link UpdateResponse}).
- * @throws Exception Any errors that occurred while checking.
- * @since 2.0.0-SNAPSHOT
- */
- public UpdateResponse checkNow() throws Exception {
- lastCheck = System.currentTimeMillis();
- lastResponse = new UpdateChecker().check(resourceId, currentVersion, connectionTimeout);
- if(null != consumer)
- consumer.accept(getLastResponse());
- return lastResponse;
- }
-
- /**
- * Get last {@link UpdateResponse} stored - If UpdateLib hasn't checked for updates yet, this will return null.
- *
- * @return Last {@link UpdateResponse} stored.
- * @since 2.0.0-SNAPSHOT
- */
- public UpdateResponse getLastResponse() {
- return lastResponse;
- }
-
- /**
- * Set last response. - Used internally by UpdateLib.
- *
- * @param lastResponse Last response.
- *
- * @since 2.0.0-SNAPSHOT
- */
- public void setLastResponse(UpdateResponse lastResponse) {
- this.lastResponse = lastResponse;
- }
-
- /**
- * Get the last time UpdateLib checked for an update.
- *
- * @return Last time in milliseconds.
- * @since 2.0.0-SNAPSHOT
- */
- public long getLastCheckTime() {
- return lastCheck;
- }
-
- /**
- * Set last check time. - Used internally by UpdateLib.
- *
- * @param lastCheck Last check time in milliseconds.
- *
- * @since 2.0.0-SNAPSHOT
- */
- public void setLastCheck(long lastCheck) {
- this.lastCheck = lastCheck;
- }
-
- /**
- * Get UpdateLib version.
- *
- * @return Version.
- * @since 2.1.0-SNAPSHOT
- */
- public static String getVersion() {
- return version;
- }
-
-}
diff --git a/src/main/java/dev/hypera/updatelib/internal/tasks/UpdateChecker.java b/src/main/java/dev/hypera/updatelib/internal/tasks/UpdateChecker.java
deleted file mode 100644
index 8896abf..0000000
--- a/src/main/java/dev/hypera/updatelib/internal/tasks/UpdateChecker.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2021 Joshua Sing
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-package dev.hypera.updatelib.internal.tasks;
-
-import dev.hypera.updatelib.internal.UpdateResponse;
-import org.apache.maven.artifact.versioning.ComparableVersion;
-import org.json.simple.JSONObject;
-import org.json.simple.JSONValue;
-
-import javax.net.ssl.HttpsURLConnection;
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.net.URL;
-
-public class UpdateChecker {
-
- private static final String URL_BASE = "https://api.spigotmc.org/simple/0.1/index.php?action=getResource&id=";
-
- /**
- * Check for an update. - Used internally by UpdateLib.
- *
- * @param resourceId The ID of the SpigotMC resource.
- * @param currentVersion The current version of the plugin.
- * @param timeout How long we should wait before timing out the connection or read.
- *
- * @return Update response.
- * @throws Exception Any errors that occur while checking for an update.
- * @since 2.0.0-SNAPSHOT
- */
- public UpdateResponse check(long resourceId, String currentVersion, int timeout) throws Exception {
- URL url = new URL(URL_BASE + resourceId);
-
- HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url.openConnection();
- httpsURLConnection.setConnectTimeout(timeout);
- httpsURLConnection.setReadTimeout(timeout);
-
- BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpsURLConnection.getInputStream()));
- JSONObject json = (JSONObject) JSONValue.parse(readAll(bufferedReader));
- String spigotVersion = (String) json.get("current_version");
-
- if(null == spigotVersion)
- return null;
- return new UpdateResponse(new ComparableVersion(currentVersion).compareTo(new ComparableVersion(spigotVersion)) < 0, currentVersion, spigotVersion);
- }
-
- /**
- * Read all from a BufferedReader and return it as a string.
- *
- * @param bufferedReader BufferedReader to read from.
- *
- * @return Contents of reader.
- * @throws Exception Any errors that occur during execution.
- * @since 2.0.0-SNAPSHOT
- */
- private String readAll(BufferedReader bufferedReader) throws Exception {
- StringBuilder stringBuilder = new StringBuilder();
- String line;
- while((line = bufferedReader.readLine()) != null)
- stringBuilder.append(line).append("\n");
- return stringBuilder.toString();
- }
-
-}
diff --git a/src/main/java/dev/hypera/updatelib/internal/tasks/UpdateTask.java b/src/main/java/dev/hypera/updatelib/internal/tasks/UpdateTask.java
deleted file mode 100644
index a8dd270..0000000
--- a/src/main/java/dev/hypera/updatelib/internal/tasks/UpdateTask.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2021 Joshua Sing
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-package dev.hypera.updatelib.internal.tasks;
-
-import dev.hypera.updatelib.internal.UpdateLib;
-import dev.hypera.updatelib.internal.UpdateResponse;
-
-import java.util.TimerTask;
-import java.util.function.Consumer;
-
-public class UpdateTask extends TimerTask {
-
- private final long resourceId;
- private final String currentVersion;
- private final int timeout;
- private final Consumer consumer;
-
- private final UpdateLib updateLib;
-
- public UpdateTask(long resourceId, String currentVersion, int timeout, Consumer consumer, UpdateLib updateLib) {
- this.resourceId = resourceId;
- this.currentVersion = currentVersion;
- this.timeout = timeout;
- this.consumer = consumer;
- this.updateLib = updateLib;
- }
-
- @Override
- public void run() {
- Thread thread = new Thread(() -> {
- try {
- updateLib.setLastResponse(new UpdateChecker().check(resourceId, currentVersion, timeout));
- updateLib.setLastCheck(System.currentTimeMillis());
-
- if(null != consumer) consumer.accept(updateLib.getLastResponse());
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- });
- thread.setName("UpdateLib-" + thread.getId());
- thread.start();
- }
-
-}
diff --git a/src/main/java/dev/hypera/updatelib/objects/UpdateStatus.java b/src/main/java/dev/hypera/updatelib/objects/UpdateStatus.java
new file mode 100644
index 0000000..ec90a7f
--- /dev/null
+++ b/src/main/java/dev/hypera/updatelib/objects/UpdateStatus.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2021 Joshua Sing
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package dev.hypera.updatelib.objects;
+
+public class UpdateStatus {
+
+ private final String distributedVersion;
+ private final String currentVersion;
+ private final Status status;
+
+ /**
+ * UpdateStatus Constructor - Used internally by UpdateLib.
+ *
+ * @param distributedVersion Latest distributed resource version.
+ * @param currentVersion Current resource version.
+ * @param status Update status.
+ *
+ * @since 3.0.0-SNAPSHOT
+ */
+ protected UpdateStatus(String distributedVersion, String currentVersion, Status status) {
+ this.distributedVersion = distributedVersion;
+ this.currentVersion = currentVersion;
+ this.status = status;
+ }
+
+ /**
+ * Get latest distributed version.
+ *
+ * @return Distributed version.
+ * @since 3.0.0-SNAPSHOT
+ */
+ public String getDistributedVersion() {
+ return distributedVersion;
+ }
+
+ /**
+ * Get current resource version.
+ *
+ * @return Current version.
+ * @since 3.0.0-SNAPSHOT
+ */
+ public String getCurrentVersion() {
+ return currentVersion;
+ }
+
+ /**
+ * Get update status.
+ *
+ * @return Update status.
+ * @since 3.0.0-SNAPSHOT
+ */
+ public Status getStatus() {
+ return status;
+ }
+
+ /**
+ * If an update is available.
+ * @return Update available.
+ * @since 3.0.0-SNAPSHOT
+ */
+ public boolean isAvailable() {
+ return status.equals(Status.AVAILABLE) || status.equals(Status.MAJOR_AVAILABLE) || status.equals(Status.MINOR_AVAILABLE);
+ }
+
+ public enum Status {
+ MAJOR_AVAILABLE,
+ MINOR_AVAILABLE,
+ AVAILABLE,
+ UNAVAILABLE,
+ FAILED;
+
+ public static Status fromNumber(VersionScheme scheme, int i) {
+ if(scheme.equals(VersionScheme.CALENDAR)) return AVAILABLE;
+
+ switch(i) {
+ case 2:
+ return MAJOR_AVAILABLE;
+ case 3:
+ return MINOR_AVAILABLE;
+ default:
+ return AVAILABLE;
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/dev/hypera/updatelib/objects/UpdateStatusBuilder.java b/src/main/java/dev/hypera/updatelib/objects/UpdateStatusBuilder.java
new file mode 100644
index 0000000..90d2e0e
--- /dev/null
+++ b/src/main/java/dev/hypera/updatelib/objects/UpdateStatusBuilder.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2021 Joshua Sing
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package dev.hypera.updatelib.objects;
+
+import dev.hypera.updatelib.annotations.Builder;
+import dev.hypera.updatelib.annotations.Internal;
+import dev.hypera.updatelib.exceptions.VersionSchemeException;
+import dev.hypera.updatelib.utils.Check;
+import dev.hypera.updatelib.utils.VersionUtils;
+
+import java.util.Optional;
+
+@Builder
+@Internal
+public class UpdateStatusBuilder {
+
+ private final String distributedVersion;
+ private final String currentVersion;
+
+ private VersionScheme scheme;
+
+ /**
+ * UpdateStatusBuilder Constructor - Used internally by UpdateLib.
+ *
+ * @param distributedVersion Latest distributed resource version.
+ * @param currentVersion Current resource version.
+ *
+ * @since 3.0.0-SNAPSHOT
+ */
+ private UpdateStatusBuilder(String distributedVersion, String currentVersion) {
+ Check.notNull("currentVersion", currentVersion);
+ this.distributedVersion = distributedVersion;
+ this.currentVersion = currentVersion;
+ }
+
+ /**
+ * Create a new instance of {@link UpdateStatusBuilder}
+ *
+ * @param distributedVersion Latest distributed resource version.
+ * @param currentVersion Current resource version.
+ *
+ * @return {@link UpdateStatusBuilder}
+ * @since 3.0.0-SNAPSHOT
+ */
+ public static UpdateStatusBuilder create(String distributedVersion, String currentVersion) {
+ return new UpdateStatusBuilder(distributedVersion, currentVersion);
+ }
+
+ /**
+ * Set version scheme.
+ *
+ * @param scheme {@link VersionScheme} to use.
+ *
+ * @return {@link UpdateStatusBuilder}
+ * @since 3.0.0-SNAPSHOT
+ */
+ public UpdateStatusBuilder setVersionScheme(VersionScheme scheme) {
+ this.scheme = scheme;
+ return this;
+ }
+
+ /**
+ * Builds a new instance of {@link UpdateStatus}
+ *
+ * @return Instance of {@link UpdateStatus}
+ * @since 3.0.0-SNAPSHOT
+ */
+ public UpdateStatus build() {
+ if(null == distributedVersion)
+ return new UpdateStatus(null, currentVersion, UpdateStatus.Status.FAILED);
+
+ if(null == scheme) {
+ Optional versionScheme = VersionUtils.detectScheme(distributedVersion);
+ Optional currentVersionScheme = VersionUtils.detectScheme(currentVersion);
+
+ if(!versionScheme.isPresent() || !currentVersionScheme.isPresent())
+ throw new VersionSchemeException("Cannot find version scheme for '" + distributedVersion + "'/'" + currentVersion + "'");
+ if(!versionScheme.get().equals(currentVersionScheme.get()))
+ throw new VersionSchemeException("Current and distributed version schemes must match.");
+
+ scheme = versionScheme.get();
+ }
+
+ return new UpdateStatus(distributedVersion, currentVersion, VersionUtils.compare(scheme, distributedVersion, currentVersion));
+ }
+
+}
diff --git a/src/main/java/dev/hypera/updatelib/objects/VersionScheme.java b/src/main/java/dev/hypera/updatelib/objects/VersionScheme.java
new file mode 100644
index 0000000..b112a39
--- /dev/null
+++ b/src/main/java/dev/hypera/updatelib/objects/VersionScheme.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2021 Joshua Sing
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package dev.hypera.updatelib.objects;
+
+import java.util.regex.Pattern;
+
+public enum VersionScheme {
+
+ BASIC("MAJOR.MINOR", "^(v?)(?0|[1-9]\\d*)\\.(?0|[1-9]\\d*)(?:-(?(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?$"),
+ SEMANTIC("MAJOR.MINOR.PATCH - https://semver.org/", "^(v?)(?0|[1-9]\\d*)\\.(?0|[1-9]\\d*)\\.(?0|[1-9]\\d*)(?:-(?(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+(?[0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"),
+ CALENDAR("YYYY-MM-DD - https://calver.org", "^(v?)(?\\d{4})-(?\\d{2})-(?\\d{2})$");
+
+ private final String description;
+ private final Pattern pattern;
+
+ VersionScheme(String description, String regex) {
+ this.description = description;
+ this.pattern = Pattern.compile(regex);
+ }
+
+ /**
+ * Get human readable description of the Version Scheme.
+ *
+ * @return Description.
+ * @since 3.0.0-SNAPSHOT
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * Get the regex pattern of the Version Scheme.
+ *
+ * @return Regex pattern.
+ * @since 3.0.0-SNAPSHOT
+ */
+ public Pattern getPattern() {
+ return pattern;
+ }
+
+}
diff --git a/src/main/java/dev/hypera/updatelib/utils/Check.java b/src/main/java/dev/hypera/updatelib/utils/Check.java
new file mode 100644
index 0000000..b2b8cba
--- /dev/null
+++ b/src/main/java/dev/hypera/updatelib/utils/Check.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2021 Joshua Sing
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package dev.hypera.updatelib.utils;
+
+import dev.hypera.updatelib.annotations.Internal;
+
+@Internal
+public class Check {
+
+ /**
+ * Check if object is null, if so, throw an IllegalArgumentException.
+ *
+ * @param name Name of the object.
+ * @param object Object.
+ *
+ * @since 3.0.0-SNAPSHOT
+ */
+ public static void notNull(String name, Object object) {
+ if(null == object)
+ fail(name + " cannot be null");
+ }
+
+ /**
+ * Check if objects are null, if so, throw an IllegalArgumentException.
+ *
+ * @param names Object names.
+ * @param objects Objects to check.
+ *
+ * @since 3.1.2-SNAPSHOT
+ */
+ public static void notNull(String[] names, Object... objects) {
+ for(int i = 0; i < objects.length; i++) {
+ if(null == objects[i])
+ fail(names[i] + " cannot be null.");
+ }
+ }
+
+ /**
+ * Throw an IllegalArgumentException.
+ *
+ * @param message Message.
+ *
+ * @since 3.0.0-SNAPSHOT
+ */
+ private static void fail(String message) {
+ throw new IllegalArgumentException(message);
+ }
+
+}
diff --git a/src/main/java/dev/hypera/updatelib/utils/ReaderUtils.java b/src/main/java/dev/hypera/updatelib/utils/ReaderUtils.java
new file mode 100644
index 0000000..c81ccfe
--- /dev/null
+++ b/src/main/java/dev/hypera/updatelib/utils/ReaderUtils.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021 Joshua Sing
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package dev.hypera.updatelib.utils;
+
+import dev.hypera.updatelib.annotations.Internal;
+
+import java.io.BufferedReader;
+
+@Internal
+public class ReaderUtils {
+
+ /**
+ * Read all from BufferedReader.
+ *
+ * @param bufferedReader BufferedReader to read from.
+ *
+ * @return Buffer content.
+ * @throws Exception Any exceptions that occur.
+ * @since 3.0.0-SNAPSHOT
+ */
+ public static String readAll(BufferedReader bufferedReader) throws Exception {
+ StringBuilder stringBuilder = new StringBuilder();
+
+ String line;
+ while((line = bufferedReader.readLine()) != null) {
+ stringBuilder.append(line).append("\n");
+ }
+
+ return stringBuilder.toString();
+ }
+
+}
diff --git a/src/main/java/dev/hypera/updatelib/utils/VersionUtils.java b/src/main/java/dev/hypera/updatelib/utils/VersionUtils.java
new file mode 100644
index 0000000..509d08b
--- /dev/null
+++ b/src/main/java/dev/hypera/updatelib/utils/VersionUtils.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2021 Joshua Sing
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package dev.hypera.updatelib.utils;
+
+import dev.hypera.updatelib.annotations.Internal;
+import dev.hypera.updatelib.exceptions.VersionSchemeException;
+import dev.hypera.updatelib.objects.UpdateStatus;
+import dev.hypera.updatelib.objects.VersionScheme;
+
+import java.util.Arrays;
+import java.util.Optional;
+import java.util.regex.Matcher;
+
+@Internal
+public class VersionUtils {
+
+ /**
+ * Detect {@link VersionScheme} from string. - Used internally by UpdateLib.
+ *
+ * @param version Version string.
+ *
+ * @return Optional {@link VersionScheme}
+ * @since 3.0.0-SNAPSHOT
+ */
+ public static Optional detectScheme(String version) {
+ return Arrays.stream(VersionScheme.values()).filter(scheme -> scheme.getPattern().matcher(version).find()).findFirst();
+ }
+
+ /**
+ * Compare two versions. - Used internally by UpdateLib.
+ *
+ * @param versionScheme Version scheme.
+ * @param newVersion New/Distributed version.
+ * @param currentVersion Current resource version.
+ *
+ * @return {@link UpdateStatus.Status}
+ * @since 3.0.0-SNAPSHOT
+ */
+ public static UpdateStatus.Status compare(VersionScheme versionScheme, String newVersion, String currentVersion) {
+ Check.notNull(new String[] { "version scheme", "new version", "current version" }, versionScheme, newVersion, currentVersion);
+
+ if(newVersion.equals(currentVersion))
+ return UpdateStatus.Status.UNAVAILABLE;
+ else if(versionScheme.equals(VersionScheme.CALENDAR))
+ return UpdateStatus.Status.AVAILABLE;
+
+ Matcher matcher = versionScheme.getPattern().matcher(newVersion);
+ Matcher currentMatcher = versionScheme.getPattern().matcher(currentVersion);
+
+ if(!matcher.find() || !currentMatcher.find())
+ throw new VersionSchemeException("Version does not matcher version scheme.");
+
+ for(int i = 1; i < Math.max(currentMatcher.groupCount(), matcher.groupCount()); i++) {
+ if(safeCheck(currentMatcher.group(i), matcher.group(i)))
+ return UpdateStatus.Status.fromNumber(versionScheme, i);
+ }
+
+ return UpdateStatus.Status.AVAILABLE;
+ }
+
+ /**
+ * Safely check two integers. - Used internally by UpdateLib.
+ *
+ * @param currentGroup Group 1
+ * @param newGroup Group 2
+ *
+ * @return If newGroup > currentGroup.
+ * @since 3.0.0-SNAPSHOT
+ */
+ private static boolean safeCheck(String currentGroup, String newGroup) {
+ if(isEmpty(currentGroup) && isEmpty(newGroup))
+ return false;
+
+ if(isEmpty(currentGroup) || isEmpty(newGroup))
+ return true;
+
+ int currentInt;
+ int newInt;
+
+ try {
+ currentInt = Integer.parseInt(currentGroup);
+ newInt = Integer.parseInt(newGroup);
+ } catch (Exception ex) {
+ return !newGroup.equals(currentGroup);
+ }
+
+ return newInt > currentInt;
+ }
+
+ private static boolean isEmpty(String one) {
+ if(null == one)
+ return true;
+ return one.equals("");
+ }
+
+}