diff --git a/src/zutil/Timer.java b/src/zutil/Timer.java
index ec13ea6..dcc8a3d 100755
--- a/src/zutil/Timer.java
+++ b/src/zutil/Timer.java
@@ -24,25 +24,30 @@
package zutil;
+import java.io.Serializable;
+
/**
* This class is a timer, it will track time and
* timeout after a specific amount of time.
*
* Note that the {@link #start()} method needs to be called for the timer to start.
- *
- * Created by Ziver on 2015-07-15.
*/
-public class Timer {
+public class Timer implements Serializable {
/** The timeout period **/
private long period;
/** The timestamp when the timer was started, -1 if timer has not been started or has been reset **/
private long timestamp;
+ /**
+ * Create a new timer with no timeout period configured.
+ */
+ public Timer() {}
+
/**
* Create a new timer that will timeout in a specified amount of time from now.
*
- * @param millisecond the time in milliseconds that the timeout should happen.
+ * @param millisecond is the period in milliseconds that the timeout should happen in.
*/
public Timer(long millisecond) {
this.period = millisecond;
@@ -50,6 +55,17 @@ public class Timer {
}
+ /**
+ * Sets a new timeout period. Note that this will modify the timeout of a already started timer.
+ *
+ * @param millisecond is the new period of timeout in milliseconds.
+ * @return a reference of itself
+ */
+ public Timer setPeriod(long millisecond) {
+ this.period = millisecond;
+ return this;
+ }
+
/**
* Will start or restart the timer if it is already running
*
@@ -62,9 +78,12 @@ public class Timer {
/**
* Will reset the timer so that {@link #hasTimedOut()} returns true
+ *
+ * @return a reference of itself
*/
- public void reset() {
+ public Timer reset() {
timestamp = -1;
+ return this;
}
/**
diff --git a/src/zutil/net/http/page/oauth/OAuth2RegistryFileStore.java b/src/zutil/net/http/page/oauth/OAuth2RegistryFileStore.java
new file mode 100644
index 0000000..9287635
--- /dev/null
+++ b/src/zutil/net/http/page/oauth/OAuth2RegistryFileStore.java
@@ -0,0 +1,57 @@
+package zutil.net.http.page.oauth;
+
+import zutil.ObjectUtil;
+import zutil.io.file.FileUtil;
+import zutil.log.LogUtil;
+import zutil.parser.json.JSONObjectInputStream;
+import zutil.parser.json.JSONObjectOutputStream;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+
+public class OAuth2RegistryFileStore implements OAuth2RegistryStore {
+ private static final Logger logger = LogUtil.getLogger();
+
+ private final File file;
+ private List registerList = new ArrayList<>();
+
+
+ public OAuth2RegistryFileStore(File file) {
+ this.file = file;
+ }
+
+
+ @Override
+ public synchronized List getClientRegistries() {
+ if (file.exists()) {
+ try {
+ String json = FileUtil.getContent(file);
+
+ if (!ObjectUtil.isEmpty(json)) {
+ registerList = JSONObjectInputStream.parse(json);
+ return registerList;
+ }
+ } catch (Exception e) {
+ logger.log(Level.SEVERE, "Was unable to read in OAuth2 registry from file: " + file, e);
+ }
+ }
+ return Collections.emptyList();
+ }
+
+ @Override
+ public synchronized void storeClientRegister(OAuth2ClientRegister register) {
+ registerList.remove(register);
+ registerList.add(register);
+
+ try {
+ FileUtil.setContent(file, JSONObjectOutputStream.toString(registerList));
+ } catch (Exception e) {
+ logger.log(Level.SEVERE, "Was unable to write the OAuth2 registry into file: " + file, e);
+ }
+ }
+}
diff --git a/src/zutil/net/http/page/oauth/OAuth2RegistryStore.java b/src/zutil/net/http/page/oauth/OAuth2RegistryStore.java
index a3bf0dd..c63637b 100644
--- a/src/zutil/net/http/page/oauth/OAuth2RegistryStore.java
+++ b/src/zutil/net/http/page/oauth/OAuth2RegistryStore.java
@@ -36,6 +36,7 @@ public interface OAuth2RegistryStore {
public HashMap accessTokens = new HashMap<>();
+ public OAuth2ClientRegister() {}
public OAuth2ClientRegister(String clientId) {
this.clientId = clientId;
}
diff --git a/src/zutil/parser/json/JSONObjectInputStream.java b/src/zutil/parser/json/JSONObjectInputStream.java
index 03e63ea..1e6d1d3 100755
--- a/src/zutil/parser/json/JSONObjectInputStream.java
+++ b/src/zutil/parser/json/JSONObjectInputStream.java
@@ -62,7 +62,7 @@ public class JSONObjectInputStream extends InputStream implements ObjectInput, C
*/
public static T parse(String json) {
try {
- StringInputStream in = new StringInputStream();
+ StringInputStream in = new StringInputStream(json);
JSONObjectInputStream reader = new JSONObjectInputStream(in);
T object = reader.readGenericObject();
reader.close();
@@ -119,7 +119,15 @@ public class JSONObjectInputStream extends InputStream implements ObjectInput, C
try {
DataNode root = parser.read();
if (root != null) {
- return (T) readObject(c, null, root);
+ if (root.isList()) { // Handle json that starts as an array
+ ArrayList list = new ArrayList();
+ for (DataNode node : root) {
+ list.add((T) readObject(c, null, node));
+ }
+ return (T) list;
+ } else { // Handle json that starts as an object
+ return (T) readObject(c, null, root);
+ }
}
} catch (Exception e) {
logger.log(Level.SEVERE, null, e);
@@ -132,7 +140,7 @@ public class JSONObjectInputStream extends InputStream implements ObjectInput, C
@SuppressWarnings({ "rawtypes", "unchecked" })
protected Object readType(Class> type, Class>[] genericType, Object currentValue, String key, DataNode json)
- throws IllegalAccessException, ClassNotFoundException, InstantiationException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
+ throws IllegalAccessException, ClassNotFoundException, InstantiationException, NoSuchMethodException, InvocationTargetException {
if (json == null || type == null)
return null;
@@ -217,12 +225,12 @@ public class JSONObjectInputStream extends InputStream implements ObjectInput, C
}
- protected Object readObject(Class> type, String key, DataNode json) throws IllegalAccessException, InstantiationException, ClassNotFoundException, IllegalArgumentException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
+ protected Object readObject(Class> type, String key, DataNode json) throws ClassNotFoundException, IllegalArgumentException {
// Only parse if json is a map
if (json == null || !json.isMap())
return null;
// See if the Object id is in the cache before continuing
- if (json.getString("@object_id") != null && objectCache.containsKey(json.getInt(MD_OBJECT_ID)))
+ if (json.getString(MD_OBJECT_ID) != null && objectCache.containsKey(json.getInt(MD_OBJECT_ID)))
return objectCache.get(json.getInt(MD_OBJECT_ID));
// ------------------------------------------------
diff --git a/test/zutil/net/http/page/oauth/OAuth2RegistryFileStoreTest.java b/test/zutil/net/http/page/oauth/OAuth2RegistryFileStoreTest.java
new file mode 100644
index 0000000..92fdcfe
--- /dev/null
+++ b/test/zutil/net/http/page/oauth/OAuth2RegistryFileStoreTest.java
@@ -0,0 +1,52 @@
+package zutil.net.http.page.oauth;
+
+import org.junit.Test;
+import zutil.Timer;
+import zutil.io.file.FileUtil;
+import zutil.net.http.page.oauth.OAuth2RegistryStore.OAuth2ClientRegister;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.Assert.*;
+
+public class OAuth2RegistryFileStoreTest {
+
+ @Test
+ public void getClientRegistries() throws IOException {
+ File file = File.createTempFile("oauth2_test", ".json");
+ file.deleteOnExit();
+ FileUtil.setContent(file, "[{\"@class\": \"zutil.net.http.page.oauth.OAuth2RegistryStore$OAuth2ClientRegister\", \"clientId\": \"test-client-id\", \"authCodes\": {\"code-abc\": {\"period\": 100, \"@class\": \"zutil.Timer\", \"@object_id\": 2, \"timestamp\": 2000000000000}}, \"@object_id\": 1, \"accessTokens\": {\"token-abc\": {\"period\": 500, \"@class\": \"zutil.Timer\", \"@object_id\": 3, \"timestamp\": 2000000000000}}}]");
+
+ OAuth2RegistryFileStore store = new OAuth2RegistryFileStore(file);
+ List list = store.getClientRegistries();
+
+ assertNotNull(list);
+ assertEquals(1, list.size());
+ assertEquals("test-client-id", list.get(0).clientId);
+ assertEquals(2000000000100l, list.get(0).authCodes.get("code-abc").getTimeoutTimeMillis());
+ assertEquals(2000000000500l, list.get(0).accessTokens.get("token-abc").getTimeoutTimeMillis());
+
+ file.delete();
+ }
+
+ @Test
+ public void storeClientRegister() throws IOException {
+ File file = File.createTempFile("oauth2_test", ".json");
+ file.deleteOnExit();
+
+ OAuth2ClientRegister obj = new OAuth2ClientRegister("test-client-id");
+ obj.authCodes.put("code-abc", new Timer(100));
+ obj.accessTokens.put("token-abc", new Timer(500));
+
+ OAuth2RegistryFileStore store = new OAuth2RegistryFileStore(file);
+ store.storeClientRegister(obj);
+
+ assertEquals("[{\"@class\": \"zutil.net.http.page.oauth.OAuth2RegistryStore$OAuth2ClientRegister\", \"clientId\": \"test-client-id\", \"authCodes\": {\"code-abc\": {\"period\": 100, \"@class\": \"zutil.Timer\", \"@object_id\": 2, \"timestamp\": -1}}, \"@object_id\": 1, \"accessTokens\": {\"token-abc\": {\"period\": 500, \"@class\": \"zutil.Timer\", \"@object_id\": 3, \"timestamp\": -1}}}]",
+ FileUtil.getContent(file));
+
+ file.delete();
+ }
+}
\ No newline at end of file