Added a file store and added support for lists in the JSONObjectInputStream

This commit is contained in:
Ziver Koc 2021-09-10 22:17:45 +02:00
parent 6d3b27ed2b
commit 7206636502
5 changed files with 147 additions and 10 deletions

View file

@ -24,25 +24,30 @@
package zutil; package zutil;
import java.io.Serializable;
/** /**
* This class is a timer, it will track time and * This class is a timer, it will track time and
* timeout after a specific amount of time. * timeout after a specific amount of time.
* <br> * <br>
* Note that the {@link #start()} method needs to be called for the timer to start. * 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 **/ /** The timeout period **/
private long period; private long period;
/** The timestamp when the timer was started, -1 if timer has not been started or has been reset **/ /** The timestamp when the timer was started, -1 if timer has not been started or has been reset **/
private long timestamp; 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. * 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) { public Timer(long millisecond) {
this.period = 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 * 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 * Will reset the timer so that {@link #hasTimedOut()} returns true
*
* @return a reference of itself
*/ */
public void reset() { public Timer reset() {
timestamp = -1; timestamp = -1;
return this;
} }
/** /**

View file

@ -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<OAuth2ClientRegister> registerList = new ArrayList<>();
public OAuth2RegistryFileStore(File file) {
this.file = file;
}
@Override
public synchronized List<OAuth2ClientRegister> 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);
}
}
}

View file

@ -36,6 +36,7 @@ public interface OAuth2RegistryStore {
public HashMap<String, Timer> accessTokens = new HashMap<>(); public HashMap<String, Timer> accessTokens = new HashMap<>();
public OAuth2ClientRegister() {}
public OAuth2ClientRegister(String clientId) { public OAuth2ClientRegister(String clientId) {
this.clientId = clientId; this.clientId = clientId;
} }

View file

@ -62,7 +62,7 @@ public class JSONObjectInputStream extends InputStream implements ObjectInput, C
*/ */
public static <T> T parse(String json) { public static <T> T parse(String json) {
try { try {
StringInputStream in = new StringInputStream(); StringInputStream in = new StringInputStream(json);
JSONObjectInputStream reader = new JSONObjectInputStream(in); JSONObjectInputStream reader = new JSONObjectInputStream(in);
T object = reader.readGenericObject(); T object = reader.readGenericObject();
reader.close(); reader.close();
@ -119,7 +119,15 @@ public class JSONObjectInputStream extends InputStream implements ObjectInput, C
try { try {
DataNode root = parser.read(); DataNode root = parser.read();
if (root != null) { 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) { } catch (Exception e) {
logger.log(Level.SEVERE, null, e); logger.log(Level.SEVERE, null, e);
@ -132,7 +140,7 @@ public class JSONObjectInputStream extends InputStream implements ObjectInput, C
@SuppressWarnings({ "rawtypes", "unchecked" }) @SuppressWarnings({ "rawtypes", "unchecked" })
protected Object readType(Class<?> type, Class<?>[] genericType, Object currentValue, String key, DataNode json) 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) if (json == null || type == null)
return 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 // Only parse if json is a map
if (json == null || !json.isMap()) if (json == null || !json.isMap())
return null; return null;
// See if the Object id is in the cache before continuing // 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)); return objectCache.get(json.getInt(MD_OBJECT_ID));
// ------------------------------------------------ // ------------------------------------------------

View file

@ -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<OAuth2ClientRegister> 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();
}
}