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