diff --git a/.gitignore b/.gitignore
index be91110e8..56bbf5c96 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,5 +11,8 @@
# Maven
target
+# Test
+test-output
+
# Visual Studio Code project files
*.factorypath
\ No newline at end of file
diff --git a/README.md b/README.md
index 3ef3dac21..5ed547517 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,3 @@
+# Moved to [Gluu4 monorepo](https://github.com/GluuFederation/gluu4/tree/main/oxCore)
oxCore
======
diff --git a/checkstyle.xml b/checkstyle.xml
index 6fbf532cc..9281e7228 100644
--- a/checkstyle.xml
+++ b/checkstyle.xml
@@ -187,4 +187,4 @@
-
\ No newline at end of file
+
diff --git a/core-cache/pom.xml b/core-cache/pom.xml
new file mode 100644
index 000000000..68f02ee4d
--- /dev/null
+++ b/core-cache/pom.xml
@@ -0,0 +1,115 @@
+
+
+ 4.0.0
+ org.gluu
+ oxcore-cache
+ Caches support
+
+
+ org.gluu
+ oxcore
+ 4.5.6-SNAPSHOT
+
+
+
+ ${maven.min-version}
+
+
+
+
+
+ src/main/resources
+ true
+
+ **/*.xml
+ **/services/*
+ **/*.properties
+
+
+
+
+
+ src/test/resources
+ true
+
+ **/*.xml
+ **/services/*
+ **/*.properties
+
+
+
+
+
+
+
+
+ ${project.groupId}
+ gluu-orm-core
+
+
+ ${project.groupId}
+ oxcore-util
+
+
+
+
+ javax.enterprise
+ cdi-api
+ provided
+
+
+
+ javax.inject
+ javax.inject
+
+
+
+
+ net.spy
+ spymemcached
+
+
+ redis.clients
+ jedis
+
+
+ net.jodah
+ expiringmap
+
+
+ commons-io
+ commons-io
+
+
+ org.apache.httpcomponents
+ httpcore
+
+
+ org.apache.httpcomponents
+ httpclient
+
+
+
+ jakarta.xml.bind
+ jakarta.xml.bind-api
+
+
+ javax.annotation
+ javax.annotation-api
+
+
+
+
+ org.testng
+ testng
+
+
+
+ javax.annotation
+ javax.annotation-api
+
+
+
+
\ No newline at end of file
diff --git a/oxService/src/main/java/org/gluu/service/CacheService.java b/core-cache/src/main/java/org/gluu/service/BaseCacheService.java
similarity index 57%
rename from oxService/src/main/java/org/gluu/service/CacheService.java
rename to core-cache/src/main/java/org/gluu/service/BaseCacheService.java
index b831f55b7..b3ed5ae52 100644
--- a/oxService/src/main/java/org/gluu/service/CacheService.java
+++ b/core-cache/src/main/java/org/gluu/service/BaseCacheService.java
@@ -10,9 +10,7 @@
import org.gluu.service.cache.CacheProviderType;
import org.slf4j.Logger;
-import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
-import javax.inject.Named;
import java.util.Date;
import java.util.function.Supplier;
@@ -22,24 +20,25 @@
* @author Yuriy Movchan Date: 01.24.2012
* @author Yuriy Zabrovarnyy Date: 02.02.2017
*/
-@ApplicationScoped
-@Named
-public class CacheService implements CacheInterface {
+public abstract class BaseCacheService implements CacheInterface {
- private static int DEFAULT_EXPIRATION = 60;
+ public static int DEFAULT_EXPIRATION = 60;
- @Inject
- private CacheProvider cacheProvider;
-
- @Inject
+ @Inject
private Logger log;
public Object get(String key) {
+ CacheProvider cacheProvider = getCacheProvider();
if (cacheProvider == null) {
+ log.error("Cache provider is invalid!");
return null;
}
- return cacheProvider.get(key);
+ log.trace("Request data, key '{}'", key);
+ Object value = cacheProvider.get(key);
+ log.trace("Loaded data, key '{}': '{}'", key, value);
+
+ return value;
}
public T getWithPut(String key, Supplier loadFunction, int expirationInSeconds) {
@@ -47,56 +46,80 @@ public T getWithPut(String key, Supplier loadFunction, int expirationInSe
return (T) get(key);
}
- if (CacheProviderType.NATIVE_PERSISTENCE == cacheProvider.getProviderType()) {
+ CacheProvider cacheProvider = getCacheProvider();
+
+ if (CacheProviderType.NATIVE_PERSISTENCE == cacheProvider.getProviderType()) {
+ log.trace("Loading data from DB without cache, key '{}'", key);
return loadFunction.get();
}
final Object value = get(key);
if (value != null) {
- log.trace("Loaded from cache, key: " + key);
+ log.trace("Loaded from cache, key: '{}'", key);
return (T) value;
} else {
+ log.trace("Key not in cache. Searching value via load function, key: '{}'", key);
final T loaded = loadFunction.get();
if (loaded == null) {
+ log.trace("Key not in cache. There is no value, key: '{}'", key);
return null;
}
try {
put(expirationInSeconds, key, loaded);
} catch (Exception e) {
- log.error("Failed to put object into cache, key: " + key, e); // we don't want prevent returning loaded value due to failure with put
+ log.error("Failed to put object into cache, key: '{}'", key, e); // we don't want prevent returning loaded value due to failure with put
}
return loaded;
}
}
public void put(int expirationInSeconds, String key, Object object) {
- if (cacheProvider != null) {
- cacheProvider.put(expirationInSeconds, key, object);
+ CacheProvider cacheProvider = getCacheProvider();
+ if (cacheProvider == null) {
+ log.error("Cache provider is invalid!");
+ return;
}
+
+ log.trace("Put data, key '{}': '{}'", key, object);
+ cacheProvider.put(expirationInSeconds, key, object);
}
public void remove(String key) {
- if (cacheProvider == null) {
+ CacheProvider cacheProvider = getCacheProvider();
+ if (cacheProvider == null) {
+ log.error("Cache provider is invalid!");
return;
}
+ log.trace("Remove data, key '{}'", key);
cacheProvider.remove(key);
}
public void clear() {
- if (cacheProvider != null) {
- cacheProvider.clear();
+ CacheProvider cacheProvider = getCacheProvider();
+ if (cacheProvider == null) {
+ log.error("Cache provider is invalid!");
+ return;
}
+
+ log.trace("Clear cache");
+ cacheProvider.clear();
}
@Override
public void cleanup(Date now) {
- if (cacheProvider != null) {
- cacheProvider.cleanup(now);
- }
+ CacheProvider cacheProvider = getCacheProvider();
+ if (cacheProvider == null) {
+ log.error("Cache provider is invalid!");
+ return;
+ }
+
+ log.trace("Clean up cache");
+ cacheProvider.cleanup(now);
}
+ @Deprecated
public void put(String key, Object object) {
put(DEFAULT_EXPIRATION, key, object);
}
@@ -122,4 +145,7 @@ public void put(String expirationInSeconds, String key, Object object) {
public void remove(String region, String key) {
remove(key);
}
+
+ protected abstract CacheProvider getCacheProvider();
+
}
diff --git a/core-cache/src/main/java/org/gluu/service/CacheService.java b/core-cache/src/main/java/org/gluu/service/CacheService.java
new file mode 100644
index 000000000..8a7826009
--- /dev/null
+++ b/core-cache/src/main/java/org/gluu/service/CacheService.java
@@ -0,0 +1,32 @@
+/*
+ * oxCore is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
+ *
+ * Copyright (c) 2014, Gluu
+ */
+package org.gluu.service;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.gluu.service.cache.CacheProvider;
+
+/**
+ * Provides operations with cache
+ *
+ * @author Yuriy Movchan Date: 01.24.2012
+ * @author Yuriy Zabrovarnyy Date: 02.02.2017
+ */
+@ApplicationScoped
+@Named
+public class CacheService extends BaseCacheService {
+
+ @Inject
+ private CacheProvider cacheProvider;
+
+ @Override
+ protected CacheProvider getCacheProvider() {
+ return cacheProvider;
+ }
+
+}
diff --git a/oxService/src/main/java/org/gluu/service/cache/AbstractCacheProvider.java b/core-cache/src/main/java/org/gluu/service/cache/AbstractCacheProvider.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/service/cache/AbstractCacheProvider.java
rename to core-cache/src/main/java/org/gluu/service/cache/AbstractCacheProvider.java
diff --git a/oxService/src/main/java/org/gluu/service/cache/AbstractRedisProvider.java b/core-cache/src/main/java/org/gluu/service/cache/AbstractRedisProvider.java
similarity index 59%
rename from oxService/src/main/java/org/gluu/service/cache/AbstractRedisProvider.java
rename to core-cache/src/main/java/org/gluu/service/cache/AbstractRedisProvider.java
index 1de9004a5..3284b6d7b 100644
--- a/oxService/src/main/java/org/gluu/service/cache/AbstractRedisProvider.java
+++ b/core-cache/src/main/java/org/gluu/service/cache/AbstractRedisProvider.java
@@ -1,20 +1,28 @@
package org.gluu.service.cache;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import redis.clients.jedis.HostAndPort;
+import redis.clients.jedis.JedisPoolConfig;
/**
* @author yuriyz
*/
public abstract class AbstractRedisProvider {
- private final static Logger LOG = LoggerFactory.getLogger(AbstractRedisProvider.class);
protected RedisConfiguration redisConfiguration;
public AbstractRedisProvider(RedisConfiguration redisConfiguration) {
this.redisConfiguration = redisConfiguration;
+ HostAndPort.setLocalhost("127.0.0.1");
}
+ public JedisPoolConfig createPoolConfig() {
+ JedisPoolConfig poolConfig = new JedisPoolConfig();
+ poolConfig.setMaxTotal(redisConfiguration.getMaxTotalConnections());
+ poolConfig.setMaxIdle(redisConfiguration.getMaxIdleConnections());
+ poolConfig.setMinIdle(2);
+ return poolConfig;
+ }
+
public RedisConfiguration getRedisConfiguration() {
return redisConfiguration;
}
@@ -26,11 +34,21 @@ public void testConnection() {
}
}
+ public boolean isConnected() {
+ put(2, "testKey", "testValue");
+ if (!"testValue".equals(get("testKey"))) {
+ return false;
+ }
+ return true;
+ }
+
public abstract void create();
public abstract void destroy();
public abstract Object getDelegate();
+
+ public abstract boolean hasKey(String key);
public abstract Object get(String key);
diff --git a/oxService/src/main/java/org/gluu/service/cache/CacheConfiguration.java b/core-cache/src/main/java/org/gluu/service/cache/CacheConfiguration.java
similarity index 99%
rename from oxService/src/main/java/org/gluu/service/cache/CacheConfiguration.java
rename to core-cache/src/main/java/org/gluu/service/cache/CacheConfiguration.java
index 1513e8e07..ca77e4164 100644
--- a/oxService/src/main/java/org/gluu/service/cache/CacheConfiguration.java
+++ b/core-cache/src/main/java/org/gluu/service/cache/CacheConfiguration.java
@@ -1,9 +1,10 @@
package org.gluu.service.cache;
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import java.io.Serializable;
import javax.enterprise.inject.Vetoed;
-import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
/**
diff --git a/oxService/src/main/java/org/gluu/service/cache/CacheInterface.java b/core-cache/src/main/java/org/gluu/service/cache/CacheInterface.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/service/cache/CacheInterface.java
rename to core-cache/src/main/java/org/gluu/service/cache/CacheInterface.java
diff --git a/oxService/src/main/java/org/gluu/service/cache/CacheProvider.java b/core-cache/src/main/java/org/gluu/service/cache/CacheProvider.java
similarity index 90%
rename from oxService/src/main/java/org/gluu/service/cache/CacheProvider.java
rename to core-cache/src/main/java/org/gluu/service/cache/CacheProvider.java
index 461d0686d..a5769769b 100644
--- a/oxService/src/main/java/org/gluu/service/cache/CacheProvider.java
+++ b/core-cache/src/main/java/org/gluu/service/cache/CacheProvider.java
@@ -9,6 +9,11 @@ public abstract class CacheProvider implements CacheInterface {
*/
public abstract T getDelegate();
+ /*
+ * Method to check if there is key in cache
+ */
+ public abstract boolean hasKey(String key);
+
/**
* Fetches an object for the given key from the cache and returns it if found.
* Only the specified cache region will be searched.
diff --git a/oxService/src/main/java/org/gluu/service/cache/CacheProviderFactory.java b/core-cache/src/main/java/org/gluu/service/cache/CacheProviderFactory.java
similarity index 69%
rename from oxService/src/main/java/org/gluu/service/cache/CacheProviderFactory.java
rename to core-cache/src/main/java/org/gluu/service/cache/CacheProviderFactory.java
index 61c110600..cc4452604 100644
--- a/oxService/src/main/java/org/gluu/service/cache/CacheProviderFactory.java
+++ b/core-cache/src/main/java/org/gluu/service/cache/CacheProviderFactory.java
@@ -1,7 +1,5 @@
package org.gluu.service.cache;
-import org.slf4j.Logger;
-
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Instance;
@@ -9,6 +7,8 @@
import javax.inject.Inject;
import javax.inject.Named;
+import org.slf4j.Logger;
+
/**
* @author yuriyz on 02/21/2017.
*/
@@ -31,9 +31,12 @@ public class CacheProviderFactory {
public CacheProvider getCacheProvider() {
log.debug("Started to create cache provider");
- AbstractCacheProvider> cacheProvider = null;
- CacheProviderType cacheProviderType = cacheConfiguration.getCacheProviderType();
+ return getCacheProvider(cacheConfiguration);
+ }
+
+ public CacheProvider getCacheProvider(CacheConfiguration cacheConfiguration) {
+ CacheProviderType cacheProviderType = cacheConfiguration.getCacheProviderType();
if (cacheProviderType == null) {
log.error("Failed to initialize cacheProvider, cacheProviderType is null. Fallback to IN_MEMORY type.");
@@ -41,6 +44,7 @@ public CacheProvider getCacheProvider() {
}
// Create proxied bean
+ AbstractCacheProvider> cacheProvider = null;
switch (cacheProviderType) {
case IN_MEMORY:
cacheProvider = instance.select(InMemoryCacheProvider.class).get();
@@ -62,6 +66,24 @@ public CacheProvider getCacheProvider() {
cacheProvider.create();
+ return cacheProvider;
+ }
+
+ @Produces
+ @ApplicationScoped
+ @LocalCache
+ public CacheProvider getLocalCacheProvider() {
+ log.debug("Started to create local cache provider");
+
+ CacheProviderType cacheProviderType = CacheProviderType.IN_MEMORY;
+ AbstractCacheProvider> cacheProvider = instance.select(InMemoryCacheProvider.class).get();
+
+ if (cacheProvider == null) {
+ throw new RuntimeException("Failed to initialize cacheProvider, cacheProviderType is unsupported: " + cacheProviderType);
+ }
+
+ cacheProvider.create();
+
return cacheProvider;
}
diff --git a/oxService/src/main/java/org/gluu/service/cache/CacheProviderType.java b/core-cache/src/main/java/org/gluu/service/cache/CacheProviderType.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/service/cache/CacheProviderType.java
rename to core-cache/src/main/java/org/gluu/service/cache/CacheProviderType.java
diff --git a/oxService/src/main/java/org/gluu/service/cache/InMemoryCacheProvider.java b/core-cache/src/main/java/org/gluu/service/cache/InMemoryCacheProvider.java
similarity index 82%
rename from oxService/src/main/java/org/gluu/service/cache/InMemoryCacheProvider.java
rename to core-cache/src/main/java/org/gluu/service/cache/InMemoryCacheProvider.java
index f742a0512..aad2c7bb8 100644
--- a/oxService/src/main/java/org/gluu/service/cache/InMemoryCacheProvider.java
+++ b/core-cache/src/main/java/org/gluu/service/cache/InMemoryCacheProvider.java
@@ -18,7 +18,8 @@
@ApplicationScoped
public class InMemoryCacheProvider extends AbstractCacheProvider {
- private static final Logger LOG = LoggerFactory.getLogger(InMemoryCacheProvider.class);
+ @Inject
+ private Logger log;
@Inject
private CacheConfiguration cacheConfiguration;
@@ -36,23 +37,28 @@ public void init() {
}
public void create() {
- LOG.debug("Starting InMemoryCacheProvider ...");
+ log.debug("Starting InMemoryCacheProvider ...");
try {
map = ExpiringMap.builder().expirationPolicy(ExpirationPolicy.CREATED).variableExpiration().build();
- LOG.debug("InMemoryCacheProvider started.");
+ log.debug("InMemoryCacheProvider started.");
} catch (Exception e) {
throw new IllegalStateException("Error starting InMemoryCacheProvider", e);
}
}
+ public void configure(CacheConfiguration cacheConfiguration) {
+ this.log = LoggerFactory.getLogger(InMemoryCacheProvider.class);
+ this.cacheConfiguration = cacheConfiguration;
+ }
+
@PreDestroy
public void destroy() {
- LOG.debug("Destroying InMemoryCacheProvider");
+ log.debug("Destroying InMemoryCacheProvider");
map.clear();
- LOG.debug("Destroyed InMemoryCacheProvider");
+ log.debug("Destroyed InMemoryCacheProvider");
}
@Override
@@ -60,6 +66,11 @@ public ExpiringMap getDelegate() {
return map;
}
+ @Override
+ public boolean hasKey(String key) {
+ return map.containsKey(key);
+ }
+
@Override
public Object get(String key) {
return map.get(key);
diff --git a/oxService/src/main/java/org/gluu/service/cache/InMemoryConfiguration.java b/core-cache/src/main/java/org/gluu/service/cache/InMemoryConfiguration.java
similarity index 99%
rename from oxService/src/main/java/org/gluu/service/cache/InMemoryConfiguration.java
rename to core-cache/src/main/java/org/gluu/service/cache/InMemoryConfiguration.java
index 13b499fc3..84ae87567 100644
--- a/oxService/src/main/java/org/gluu/service/cache/InMemoryConfiguration.java
+++ b/core-cache/src/main/java/org/gluu/service/cache/InMemoryConfiguration.java
@@ -1,9 +1,10 @@
package org.gluu.service.cache;
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import java.io.Serializable;
import javax.xml.bind.annotation.XmlElement;
-import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
/**
diff --git a/core-cache/src/main/java/org/gluu/service/cache/LocalCache.java b/core-cache/src/main/java/org/gluu/service/cache/LocalCache.java
new file mode 100644
index 000000000..02aa96061
--- /dev/null
+++ b/core-cache/src/main/java/org/gluu/service/cache/LocalCache.java
@@ -0,0 +1,32 @@
+package org.gluu.service.cache;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.enterprise.util.AnnotationLiteral;
+import javax.inject.Qualifier;
+
+/**
+ * @author Yuriy Movchan Date: 11/12/2019
+ */
+@Qualifier
+@Retention(RUNTIME)
+@Target({ TYPE, METHOD, FIELD })
+@Documented
+public @interface LocalCache {
+
+ final class Literal extends AnnotationLiteral implements LocalCache {
+
+ public static final Literal INSTANCE = new Literal();
+
+ private static final long serialVersionUID = 1L;
+
+ }
+
+}
diff --git a/oxService/src/main/java/org/gluu/service/cache/MemcachedConfiguration.java b/core-cache/src/main/java/org/gluu/service/cache/MemcachedConfiguration.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/service/cache/MemcachedConfiguration.java
rename to core-cache/src/main/java/org/gluu/service/cache/MemcachedConfiguration.java
index 4c1f8dc80..ce91b4341 100644
--- a/oxService/src/main/java/org/gluu/service/cache/MemcachedConfiguration.java
+++ b/core-cache/src/main/java/org/gluu/service/cache/MemcachedConfiguration.java
@@ -1,9 +1,9 @@
package org.gluu.service.cache;
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-
import java.io.Serializable;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
/**
* @author yuriyz on 02/02/2017.
diff --git a/oxService/src/main/java/org/gluu/service/cache/MemcachedConnectionFactoryType.java b/core-cache/src/main/java/org/gluu/service/cache/MemcachedConnectionFactoryType.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/service/cache/MemcachedConnectionFactoryType.java
rename to core-cache/src/main/java/org/gluu/service/cache/MemcachedConnectionFactoryType.java
diff --git a/oxService/src/main/java/org/gluu/service/cache/MemcachedProvider.java b/core-cache/src/main/java/org/gluu/service/cache/MemcachedProvider.java
similarity index 85%
rename from oxService/src/main/java/org/gluu/service/cache/MemcachedProvider.java
rename to core-cache/src/main/java/org/gluu/service/cache/MemcachedProvider.java
index 25715e77d..52c785704 100644
--- a/oxService/src/main/java/org/gluu/service/cache/MemcachedProvider.java
+++ b/core-cache/src/main/java/org/gluu/service/cache/MemcachedProvider.java
@@ -4,6 +4,7 @@
import net.spy.memcached.internal.OperationFuture;
import net.spy.memcached.ops.OperationStatus;
import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@@ -27,6 +28,10 @@ public class MemcachedProvider extends AbstractCacheProvider {
public MemcachedProvider() {
}
+ public void setCacheConfiguration(CacheConfiguration cacheConfiguration) {
+ this.cacheConfiguration = cacheConfiguration;
+ }
+
@PostConstruct
public void init() {
this.memcachedConfiguration = cacheConfiguration.getMemcachedConfiguration();
@@ -54,6 +59,11 @@ public void create() {
}
}
+ public void configure(CacheConfiguration cacheConfiguration) {
+ this.log = LoggerFactory.getLogger(MemcachedProvider.class);
+ this.cacheConfiguration = cacheConfiguration;
+ }
+
private void testConnection() {
put(2, "connectionTest", "connectionTestValue");
if (!"connectionTestValue".equals(get("connectionTest"))) {
@@ -61,6 +71,14 @@ private void testConnection() {
}
}
+ public boolean isConnected() {
+ put(2, "connectionTest", "connectionTestValue");
+ if (!"connectionTestValue".equals(get("connectionTest"))) {
+ return false;
+ }
+ return true;
+ }
+
@PreDestroy
public void destroy() {
log.debug("Destroying MemcachedProvider");
@@ -78,6 +96,13 @@ public MemcachedClient getDelegate() {
return client;
}
+ @Override
+ public boolean hasKey(String key) {
+ Object value = get(key);
+
+ return value != null;
+ }
+
@Override
public Object get(String key) {
try {
diff --git a/core-cache/src/main/java/org/gluu/service/cache/NativePersistenceCacheEntity.java b/core-cache/src/main/java/org/gluu/service/cache/NativePersistenceCacheEntity.java
new file mode 100644
index 000000000..7a5dc58e1
--- /dev/null
+++ b/core-cache/src/main/java/org/gluu/service/cache/NativePersistenceCacheEntity.java
@@ -0,0 +1,60 @@
+package org.gluu.service.cache;
+
+import org.gluu.persist.annotation.*;
+import org.gluu.persist.model.base.Deletable;
+import org.gluu.persist.model.base.DeletableEntity;
+
+import java.io.Serializable;
+import java.util.Date;
+
+@DataEntry
+@ObjectClass(value = "cache")
+public class NativePersistenceCacheEntity extends DeletableEntity implements Serializable, Deletable {
+
+ @Expiration
+ private Integer ttl;
+ @AttributeName(name = "uuid")
+ private String id;
+ @AttributeName(name = "iat")
+ private Date creationDate;
+ @AttributeName(name = "dat")
+ private String data;
+
+ public Integer getTtl() {
+ return ttl;
+ }
+
+ public void setTtl(Integer ttl) {
+ this.ttl = ttl;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public Date getCreationDate() {
+ return creationDate;
+ }
+
+ public void setCreationDate(Date creationDate) {
+ this.creationDate = creationDate;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ @Override
+ public String toString() {
+ return "NativePersistenceCacheEntity [dn=" + getDn() + ", ttl=" + ttl + ", id=" + id + ", creationDate=" + creationDate + ", data="
+ + data + "]";
+ }
+}
diff --git a/oxService/src/main/java/org/gluu/service/cache/NativePersistenceCacheProvider.java b/core-cache/src/main/java/org/gluu/service/cache/NativePersistenceCacheProvider.java
similarity index 52%
rename from oxService/src/main/java/org/gluu/service/cache/NativePersistenceCacheProvider.java
rename to core-cache/src/main/java/org/gluu/service/cache/NativePersistenceCacheProvider.java
index 10647da5a..79478564d 100644
--- a/oxService/src/main/java/org/gluu/service/cache/NativePersistenceCacheProvider.java
+++ b/core-cache/src/main/java/org/gluu/service/cache/NativePersistenceCacheProvider.java
@@ -5,11 +5,14 @@
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.gluu.persist.PersistenceEntryManager;
+import org.gluu.persist.exception.EntryPersistenceException;
+import org.gluu.persist.exception.operation.DuplicateEntryException;
import org.gluu.persist.model.base.SimpleBranch;
import org.gluu.search.filter.Filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import java.io.ByteArrayInputStream;
@@ -22,7 +25,8 @@
@ApplicationScoped
public class NativePersistenceCacheProvider extends AbstractCacheProvider {
- private final static Logger log = LoggerFactory.getLogger(NativePersistenceCacheProvider.class);
+ @Inject
+ private Logger log;
@Inject
private CacheConfiguration cacheConfiguration;
@@ -32,14 +36,25 @@ public class NativePersistenceCacheProvider extends AbstractCacheProvider 0 ? expirationInSeconds : cacheConfiguration.getNativePersistenceConfiguration().getDefaultPutExpiration();
+
+ putImpl(key, object, creationDate, expirationInSeconds);
+ }
- expirationInSeconds = expirationInSeconds > 0 ? expirationInSeconds : cacheConfiguration.getNativePersistenceConfiguration().getDefaultPutExpiration();
+ private void putImpl(String key, Object object, Date creationDate, int expirationInSeconds) {
+ Calendar expirationDate = Calendar.getInstance();
+ expirationDate.setTime(creationDate);
+ expirationDate.add(Calendar.SECOND, expirationInSeconds);
- Calendar expirationDate = Calendar.getInstance();
- expirationDate.setTime(creationDate);
- expirationDate.add(Calendar.SECOND, expirationInSeconds);
+
+ String originalKey = key;
- NativePersistenceCacheEntity entity = new NativePersistenceCacheEntity();
- entity.setData(asString(object));
- entity.setId(key);
- entity.setDn(createDn(key));
- entity.setCreationDate(creationDate);
- entity.setExpirationDate(expirationDate.getTime());
- entity.setDeletable(true);
+ key = hashKey(key);
- silentlyRemoveEntityIfExists(entity.getDn());
- entryManager.persist(entity);
+ NativePersistenceCacheEntity entity = new NativePersistenceCacheEntity();
+ entity.setTtl(expirationInSeconds);
+ entity.setData(asString(object));
+ entity.setId(key);
+ entity.setDn(createDn(key));
+ entity.setCreationDate(creationDate);
+ entity.setExpirationDate(expirationDate.getTime());
+ entity.setDeletable(true);
+
+ try {
+ if (attemptUpdateBeforeInsert) {
+ entryManager.merge(entity);
+ } else {
+ if (!skipRemoveBeforePut) {
+ silentlyRemoveEntityIfExists(entity.getDn());
+ }
+ entryManager.persist(entity);
+ }
+ } catch (EntryPersistenceException e) {
+ if (e.getCause() instanceof DuplicateEntryException) { // on duplicate, remove entry and try to persist again
+ try {
+ silentlyRemoveEntityIfExists(entity.getDn());
+ entryManager.persist(entity);
+ return;
+ } catch (Exception ex) {
+ log.error("Failed to retry put entry, key: " + originalKey + ", hashedKey: " + key + ", message: " + ex.getMessage(), ex);
+ }
+ }
+
+ if (attemptUpdateBeforeInsert) {
+ try {
+ entryManager.persist(entity);
+ return;
+ } catch (Exception ex) {
+ log.error("Failed to retry put entry, key: " + originalKey + ", hashedKey: " + key + ", message: " + ex.getMessage(), ex);
+ }
+ }
+
+ log.error("Failed to put entry, key: " + originalKey + ", hashedKey: " + key + ", message: " + e.getMessage(), e);
} catch (Exception e) {
- log.trace("Failed to put entry, key: " + originalKey + ", hashedKey: " + key + ", message: " + e.getMessage(), e); // log as trace since it is perfectly valid that entry is removed by timer for example
+ log.error("Failed to put entry, key: " + originalKey + ", hashedKey: " + key + ", message: " + e.getMessage(), e); // log as trace since it is perfectly valid that entry is removed by timer for example
}
- }
+ }
private boolean silentlyRemoveEntityIfExists(String dn) {
try {
if (entryManager.find(NativePersistenceCacheEntity.class, dn) != null) {
- entryManager.removeRecursively(dn);
+ entryManager.remove(dn, NativePersistenceCacheEntity.class);
return true;
}
} catch (Exception e) {
@@ -159,7 +237,7 @@ public void clear() {
// TODO: Implement all specific application objects removal
}
- private static Object fromString(String s) {
+ private Object fromString(String s) {
try {
byte[] data = Base64.decodeBase64(s);
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data));
@@ -171,12 +249,12 @@ private static Object fromString(String s) {
IOUtils.closeQuietly(ois);
}
} catch (Exception e) {
- log.error("Failed to deserizalize cache entity, data: " + s);
+ log.error("Failed to deserizalize cache entity, data: " + s, e);
return null;
}
}
- private static String asString(Object o) {
+ private String asString(Object o) {
ObjectOutputStream oos = null;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -185,7 +263,7 @@ private static String asString(Object o) {
oos.close();
return Base64.encodeBase64String(baos.toByteArray());
} catch (Exception e) {
- log.error("Failed to serizalize cache entity to string, object: " + 0);
+ log.error("Failed to serizalize cache entity to string, object: " + 0, e);
return null;
} finally {
IOUtils.closeQuietly(oos);
@@ -194,13 +272,18 @@ private static String asString(Object o) {
@Override
public void cleanup(final Date now) {
- cleanup(now, cacheConfiguration.getNativePersistenceConfiguration().getDefaultCleanupBatchSize());
+ NativePersistenceConfiguration nativePersistenceConfiguration = cacheConfiguration.getNativePersistenceConfiguration();
+ if (!entryManager.hasExpirationSupport(nativePersistenceConfiguration.getBaseDn())) {
+ cleanup(now, cacheConfiguration.getNativePersistenceConfiguration().getDefaultCleanupBatchSize());
+ }
}
public void cleanup(final Date now, int batchSize) {
log.debug("Start NATIVE_PERSISTENCE clean up");
try {
- Filter filter = Filter.createLessOrEqualFilter("oxAuthExpiration", entryManager.encodeTime(baseDn, now));
+ Filter filter = Filter.createANDFilter(
+ Filter.createEqualityFilter("del", true),
+ Filter.createLessOrEqualFilter("exp", entryManager.encodeTime(baseDn, now)));
final int removedCount = entryManager.remove(baseDn, NativePersistenceCacheEntity.class, filter, batchSize);
log.debug("End NATIVE_PERSISTENCE clean up, items removed: " + removedCount);
@@ -229,4 +312,11 @@ public void setBaseDn(String baseDn) {
public void setCacheConfiguration(CacheConfiguration cacheConfiguration) {
this.cacheConfiguration = cacheConfiguration;
}
+
+ public static void main(String[] args) {
+ NativePersistenceCacheProvider cp = new NativePersistenceCacheProvider();
+ Object obj = cp.fromString("rO0ABXNyAClvcmcuZ2x1dS5veGF1dGgubW9kZWwuY29tbW9uLkNsaWVudFRva2Vuc/Aib54fThHVAgACTAAIY2xpZW50SWR0ABJMamF2YS9sYW5nL1N0cmluZztMAAt0b2tlbkhhc2hlc3QAD0xqYXZhL3V0aWwvU2V0O3hwdAApMTAwMS45MGQ0MGI2OS02ZDFmLTQxMmYtOTg5ZS00MThmN2E2Y2M1MTNzcgARamF2YS51dGlsLkhhc2hTZXS6RIWVlri3NAMAAHhwdwwAAAAQP0AAAAAAAAF0AEA3M2M1NDBhYjRlNzU2ZTk2ZjQ2NzU2ODZjNzU0ZDg1ZjZiOWExYmI0ZjI1ZWY5NTZjYmRkZTQ0NjlmZTA2OGVjeA==");
+
+ System.out.println(obj);
+ }
}
diff --git a/oxService/src/main/java/org/gluu/service/cache/NativePersistenceConfiguration.java b/core-cache/src/main/java/org/gluu/service/cache/NativePersistenceConfiguration.java
similarity index 60%
rename from oxService/src/main/java/org/gluu/service/cache/NativePersistenceConfiguration.java
rename to core-cache/src/main/java/org/gluu/service/cache/NativePersistenceConfiguration.java
index e258ca060..524ad832f 100644
--- a/oxService/src/main/java/org/gluu/service/cache/NativePersistenceConfiguration.java
+++ b/core-cache/src/main/java/org/gluu/service/cache/NativePersistenceConfiguration.java
@@ -1,11 +1,12 @@
package org.gluu.service.cache;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import java.io.Serializable;
import javax.xml.bind.annotation.XmlElement;
-import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true)
public class NativePersistenceConfiguration implements Serializable {
@@ -14,7 +15,10 @@ public class NativePersistenceConfiguration implements Serializable {
private int defaultPutExpiration = 60; // in seconds
@XmlElement(name = "defaultCleanupBatchSize")
- private int defaultCleanupBatchSize = 25; // 25 objects per iteration
+ private int defaultCleanupBatchSize = 1000; // 1000 objects per iteration
+
+ @XmlElement(name = "deleteExpiredOnGetRequest")
+ private boolean deleteExpiredOnGetRequest = false;
@JsonIgnore
private String baseDn;
@@ -35,7 +39,15 @@ public void setDefaultCleanupBatchSize(int defaultCleanupBatchSize) {
this.defaultCleanupBatchSize = defaultCleanupBatchSize;
}
- public String getBaseDn() {
+ public boolean isDeleteExpiredOnGetRequest() {
+ return deleteExpiredOnGetRequest;
+ }
+
+ public void setDeleteExpiredOnGetRequest(boolean deleteExpiredOnGetRequest) {
+ this.deleteExpiredOnGetRequest = deleteExpiredOnGetRequest;
+ }
+
+ public String getBaseDn() {
return baseDn;
}
@@ -44,10 +56,8 @@ public void setBaseDn(String baseDn) {
}
@Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("NativePersistenceConfiguration [defaultPutExpiration=").append(defaultPutExpiration).append(", defaultCleanupBatchSize=")
- .append(defaultCleanupBatchSize).append(", baseDn=").append(baseDn).append("]");
- return builder.toString();
- }
+ public String toString() {
+ return "NativePersistenceConfiguration [defaultPutExpiration=" + defaultPutExpiration + ", defaultCleanupBatchSize="
+ + defaultCleanupBatchSize + ", deleteExpiredOnGetRequest=" + deleteExpiredOnGetRequest + ", baseDn=" + baseDn + "]";
+ }
}
diff --git a/oxService/src/main/java/org/gluu/service/cache/RedisClusterProvider.java b/core-cache/src/main/java/org/gluu/service/cache/RedisClusterProvider.java
similarity index 73%
rename from oxService/src/main/java/org/gluu/service/cache/RedisClusterProvider.java
rename to core-cache/src/main/java/org/gluu/service/cache/RedisClusterProvider.java
index 21c5e6745..9230a4564 100644
--- a/oxService/src/main/java/org/gluu/service/cache/RedisClusterProvider.java
+++ b/core-cache/src/main/java/org/gluu/service/cache/RedisClusterProvider.java
@@ -1,19 +1,18 @@
package org.gluu.service.cache;
-import java.io.IOException;
-import java.io.Serializable;
-import java.util.HashSet;
-import java.util.Set;
-
import org.apache.commons.lang.SerializationUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
/**
* Important : keep it weld free. It's reused by oxd !
*
@@ -33,16 +32,24 @@ public void create() {
try {
LOG.debug("Starting RedisClusterProvider ... configuration:" + getRedisConfiguration());
- JedisPoolConfig poolConfig = new JedisPoolConfig();
- poolConfig.setMaxTotal(1000);
- poolConfig.setMinIdle(2);
+ JedisPoolConfig poolConfig = createPoolConfig();
+ String password = redisConfiguration.getPassword();
+
+ if (redisConfiguration.getUseSSL()) {
+ RedisProviderFactory.setSSLSystemProperties(redisConfiguration);
- pool = new JedisCluster(hosts(getRedisConfiguration().getServers()), poolConfig);
+ pool = new JedisCluster(hosts(getRedisConfiguration().getServers()), redisConfiguration.getConnectionTimeout(),
+ redisConfiguration.getSoTimeout(), redisConfiguration.getMaxRetryAttempts(),
+ password, UUID.randomUUID().toString(), poolConfig, true);
+ } else {
+ pool = new JedisCluster(hosts(getRedisConfiguration().getServers()), redisConfiguration.getConnectionTimeout(),
+ redisConfiguration.getSoTimeout(), redisConfiguration.getMaxRetryAttempts(), password, poolConfig);
+ }
testConnection();
LOG.debug("RedisClusterProvider started.");
} catch (Exception e) {
- LOG.error("Failed to start RedisClusterProvider.");
+ LOG.error("Failed to start RedisClusterProvider.", e);
throw new IllegalStateException("Error starting RedisClusterProvider", e);
}
}
@@ -63,12 +70,7 @@ public static Set hosts(String servers) {
public void destroy() {
LOG.debug("Destroying RedisClusterProvider");
- try {
- pool.close();
- } catch (IOException e) {
- LOG.error("Failed to destroy RedisClusterProvider", e);
- return;
- }
+ pool.close();
LOG.debug("Destroyed RedisClusterProvider");
}
@@ -78,6 +80,13 @@ public JedisCluster getDelegate() {
return pool;
}
+ @Override
+ public boolean hasKey(String key) {
+ Boolean hasKey = pool.exists(key);
+
+ return Boolean.TRUE.equals(hasKey);
+ }
+
@Override
public Object get(String key) {
byte[] value = pool.get(key.getBytes());
@@ -110,4 +119,5 @@ public void remove(String key) {
public void clear() {
LOG.trace("clear not allowed for cluster deployments");
}
+
}
diff --git a/core-cache/src/main/java/org/gluu/service/cache/RedisConfiguration.java b/core-cache/src/main/java/org/gluu/service/cache/RedisConfiguration.java
new file mode 100644
index 000000000..bd4ac11b0
--- /dev/null
+++ b/core-cache/src/main/java/org/gluu/service/cache/RedisConfiguration.java
@@ -0,0 +1,198 @@
+package org.gluu.service.cache;
+
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+import java.io.Serializable;
+
+/**
+ * @author yuriyz on 02/23/2017.
+ */
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class RedisConfiguration implements Serializable {
+
+ private static final long serialVersionUID = 5513197227832695471L;
+
+ private RedisProviderType redisProviderType = RedisProviderType.STANDALONE;
+
+ private String servers = "localhost:6379"; // server1:11211 server2:11211
+
+ private int defaultPutExpiration = 60; // in seconds
+
+ private String sentinelMasterGroupName = "";
+
+ private String password;
+
+ private Boolean useSSL = false;
+
+ private String sslTrustStoreFilePath = "";
+
+ private String sslTrustStorePassword = "";
+
+ private String sslKeyStoreFilePath = "";
+
+ private String sslKeyStorePassword = "";
+
+ /**
+ * The cap on the number of "idle" instances in the pool. If maxIdle
+ * is set too low on heavily loaded systems it is possible you will see
+ * objects being destroyed and almost immediately new objects being created.
+ * This is a result of the active threads momentarily returning objects
+ * faster than they are requesting them, causing the number of idle
+ * objects to rise above maxIdle. The best value for maxIdle for heavily
+ * loaded system will vary but the default is a good starting point.
+ */
+ private int maxIdleConnections = 10;
+
+ private int maxTotalConnections = 500;
+
+ private int connectionTimeout = 3000;
+
+ /**
+ * With this option set to a non-zero timeout, a read() call on the InputStream associated with this Socket will block for only this amount of time.
+ * If the timeout expires, a java.net.SocketTimeoutException is raised, though the Socket is still valid.
+ * The option must be enabled prior to entering the blocking operation to have effect. The timeout must be > 0.
+ * A timeout of zero is interpreted as an infinite timeout.
+ */
+ private int soTimeout = 3000;
+
+ private int maxRetryAttempts = 5;
+
+ public int getMaxIdleConnections() {
+ return maxIdleConnections;
+ }
+
+ public void setMaxIdleConnections(int maxIdleConnections) {
+ this.maxIdleConnections = maxIdleConnections;
+ }
+
+ public int getConnectionTimeout() {
+ return connectionTimeout;
+ }
+
+ public void setConnectionTimeout(int connectionTimeout) {
+ this.connectionTimeout = connectionTimeout;
+ }
+
+ public int getSoTimeout() {
+ return soTimeout;
+ }
+
+ public void setSoTimeout(int soTimeout) {
+ this.soTimeout = soTimeout;
+ }
+
+ public int getMaxRetryAttempts() {
+ return maxRetryAttempts;
+ }
+
+ public void setMaxRetryAttempts(int maxRetryAttempts) {
+ this.maxRetryAttempts = maxRetryAttempts;
+ }
+
+ public int getMaxTotalConnections() {
+ return maxTotalConnections;
+ }
+
+ public void setMaxTotalConnections(int maxTotalConnections) {
+ this.maxTotalConnections = maxTotalConnections;
+ }
+
+ public String getServers() {
+ return servers;
+ }
+
+ public void setServers(String servers) {
+ this.servers = servers;
+ }
+
+ public int getDefaultPutExpiration() {
+ return defaultPutExpiration;
+ }
+
+ public void setDefaultPutExpiration(int defaultPutExpiration) {
+ this.defaultPutExpiration = defaultPutExpiration;
+ }
+
+ public RedisProviderType getRedisProviderType() {
+ return redisProviderType;
+ }
+
+ public void setRedisProviderType(RedisProviderType redisProviderType) {
+ this.redisProviderType = redisProviderType;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public Boolean getUseSSL() {
+ return useSSL != null ? useSSL : false;
+ }
+
+ public void setUseSSL(Boolean useSSL) {
+ this.useSSL = useSSL;
+ }
+
+ public String getSslTrustStoreFilePath() {
+ return sslTrustStoreFilePath;
+ }
+
+ public void setSslTrustStoreFilePath(String sslTrustStoreFilePath) {
+ this.sslTrustStoreFilePath = sslTrustStoreFilePath;
+ }
+
+ public String getSslTrustStorePassword() {
+ return sslTrustStorePassword;
+ }
+
+ public void setSslTrustStorePassword(String sslTrustStorePassword) {
+ this.sslTrustStorePassword = sslTrustStorePassword;
+ }
+
+ public String getSslKeyStoreFilePath() {
+ return sslKeyStoreFilePath;
+ }
+
+ public void setSslKeyStoreFilePath(String sslKeyStoreFilePath) {
+ this.sslKeyStoreFilePath = sslKeyStoreFilePath;
+ }
+
+ public String getSslKeyStorePassword() {
+ return sslKeyStorePassword;
+ }
+
+ public void setSslKeyStorePassword(String sslKeyStorePassword) {
+ this.sslKeyStorePassword = sslKeyStorePassword;
+ }
+
+ public String getSentinelMasterGroupName() {
+ return sentinelMasterGroupName;
+ }
+
+ public void setSentinelMasterGroupName(String sentinelMasterGroupName) {
+ this.sentinelMasterGroupName = sentinelMasterGroupName;
+ }
+
+ @Override
+ public String toString() {
+ return "RedisConfiguration{" +
+ "servers='" + servers + '\'' +
+ ", defaultPutExpiration=" + defaultPutExpiration +
+ ", redisProviderType=" + redisProviderType +
+ ", useSSL=" + useSSL +
+ ", sslTrustStoreFilePath=" + sslTrustStoreFilePath +
+ ", sslKeyStoreFilePath=" + sslKeyStoreFilePath +
+ ", sentinelMasterGroupName=" + sentinelMasterGroupName +
+ ", maxIdleConnections=" + maxIdleConnections +
+ ", maxTotalConnections=" + maxTotalConnections +
+ ", connectionTimeout=" + connectionTimeout +
+ ", soTimeout=" + soTimeout +
+ ", maxRetryAttempts=" + maxRetryAttempts +
+ '}';
+ }
+}
diff --git a/oxService/src/main/java/org/gluu/service/cache/RedisProvider.java b/core-cache/src/main/java/org/gluu/service/cache/RedisProvider.java
similarity index 79%
rename from oxService/src/main/java/org/gluu/service/cache/RedisProvider.java
rename to core-cache/src/main/java/org/gluu/service/cache/RedisProvider.java
index cca38a76c..eb43cc6ef 100644
--- a/oxService/src/main/java/org/gluu/service/cache/RedisProvider.java
+++ b/core-cache/src/main/java/org/gluu/service/cache/RedisProvider.java
@@ -3,6 +3,7 @@
import org.apache.commons.lang.StringUtils;
import org.gluu.util.security.StringEncrypter;
import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@@ -41,25 +42,33 @@ public void create() {
RedisConfiguration redisConfiguration = cacheConfiguration.getRedisConfiguration();
decryptPassword(redisConfiguration);
log.debug("Starting RedisProvider ... configuration:" + redisConfiguration);
-
defaultPutExpiration = redisConfiguration.getDefaultPutExpiration() > 0 ? redisConfiguration.getDefaultPutExpiration()
: DEFAULT_PUT_EXPIRATION_IN_SECONDS;
-
redisProvider = RedisProviderFactory.create(cacheConfiguration.getRedisConfiguration());
redisProvider.create();
-
log.debug("RedisProvider started.");
} catch (Exception e) {
log.error("Failed to start RedisProvider.");
+ log.error("Log Error",e);
throw new IllegalStateException("Error starting RedisProvider", e);
}
}
+ public void configure(CacheConfiguration cacheConfiguration, StringEncrypter stringEncrypter) {
+ this.log = LoggerFactory.getLogger(RedisProvider.class);
+ this.cacheConfiguration = cacheConfiguration;
+ this.stringEncrypter = stringEncrypter;
+ }
+
+ public void setCacheConfiguration(CacheConfiguration cacheConfiguration){
+ this.cacheConfiguration=cacheConfiguration;
+ }
+
private void decryptPassword(RedisConfiguration redisConfiguration) {
try {
String encryptedPassword = redisConfiguration.getPassword();
if (StringUtils.isNotBlank(encryptedPassword)) {
- redisConfiguration.setDecryptedPassword(stringEncrypter.decrypt(encryptedPassword));
+ redisConfiguration.setPassword(stringEncrypter.decrypt(encryptedPassword));
log.trace("Decrypted redis password successfully.");
}
} catch (StringEncrypter.EncryptionException e) {
@@ -67,6 +76,10 @@ private void decryptPassword(RedisConfiguration redisConfiguration) {
}
}
+ public boolean isConnected(){
+ return redisProvider.isConnected();
+ }
+
@PreDestroy
public void destroy() {
@@ -80,6 +93,14 @@ public AbstractRedisProvider getDelegate() {
return redisProvider;
}
+ @Override
+ public boolean hasKey(String key) {
+ if (key == null) {
+ return false;
+ }
+ return redisProvider.hasKey(key);
+ }
+
@Override
public Object get(String key) {
if (key == null) {
diff --git a/core-cache/src/main/java/org/gluu/service/cache/RedisProviderFactory.java b/core-cache/src/main/java/org/gluu/service/cache/RedisProviderFactory.java
new file mode 100644
index 000000000..ea19df735
--- /dev/null
+++ b/core-cache/src/main/java/org/gluu/service/cache/RedisProviderFactory.java
@@ -0,0 +1,96 @@
+package org.gluu.service.cache;
+
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManagerFactory;
+import java.io.FileInputStream;
+import java.security.KeyStore;
+import java.security.SecureRandom;
+
+/**
+ * Important : keep it weld free. It's reused by oxd !
+ *
+ * @author yuriyz
+ */
+public final class RedisProviderFactory {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RedisProviderFactory.class);
+
+ private RedisProviderFactory() {
+ }
+
+ public static AbstractRedisProvider create(RedisConfiguration redisConfiguration) {
+ try {
+ LOG.debug("Creating RedisProvider ... configuration:" + redisConfiguration);
+
+ switch (redisConfiguration.getRedisProviderType()) {
+ case STANDALONE:
+ return new RedisStandaloneProvider(redisConfiguration);
+ case CLUSTER:
+ return new RedisClusterProvider(redisConfiguration);
+ case SHARDED:
+ return new RedisShardedProvider(redisConfiguration);
+ case SENTINEL:
+ return new RedisSentinelProvider(redisConfiguration);
+ default:
+ LOG.error("Failed to create RedisProvider. RedisProviderType is not supported by current version of oxcore: "
+ + redisConfiguration.getRedisProviderType() + ", redisConfiguration:" + redisConfiguration);
+ throw new RuntimeException(
+ "RedisProviderType is not supported by current version of oxcore: " + redisConfiguration.getRedisProviderType());
+ }
+ } catch (Exception e) {
+ LOG.error("Failed to create RedisProvider.");
+ throw new RuntimeException("Error creating RedisProvider", e);
+ }
+ }
+
+ public static void destroy(AbstractRedisProvider provider) {
+ if (provider != null) {
+ provider.destroy();
+ }
+ }
+
+ public static void destroySilently(AbstractRedisProvider provider) {
+ try {
+ destroy(provider);
+ } catch (Exception e) {
+ LOG.error("Failed to destroy redis provider.", e);
+ }
+ }
+
+ public static SSLSocketFactory createSslSocketFactory(RedisConfiguration redisConfiguration) throws Exception {
+ KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ trustStore.load(new FileInputStream(redisConfiguration.getSslTrustStoreFilePath()),
+ redisConfiguration.getSslTrustStorePassword().toCharArray());
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ trustManagerFactory.init(trustStore);
+
+ KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ keyStore.load(new FileInputStream(redisConfiguration.getSslKeyStoreFilePath()),
+ redisConfiguration.getSslKeyStorePassword().toCharArray());
+ KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+ keyManagerFactory.init(keyStore, redisConfiguration.getSslKeyStorePassword().toCharArray());
+
+ SSLContext sslContext = SSLContext.getInstance("TLS");
+ sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
+
+ return sslContext.getSocketFactory();
+ }
+
+ public static void setSSLSystemProperties(RedisConfiguration redisConfiguration) {
+ if (StringUtils.isNotBlank(redisConfiguration.getSslKeyStoreFilePath())) {
+ System.setProperty("javax.net.ssl.keyStore", redisConfiguration.getSslKeyStoreFilePath());
+ System.setProperty("javax.net.ssl.keyStorePassword", redisConfiguration.getSslKeyStorePassword());
+ }
+
+ if (StringUtils.isNotBlank(redisConfiguration.getSslTrustStoreFilePath())) {
+ System.setProperty("javax.net.ssl.trustStore", redisConfiguration.getSslTrustStoreFilePath());
+ System.setProperty("javax.net.ssl.trustStorePassword", redisConfiguration.getSslTrustStorePassword());
+ }
+ }
+}
diff --git a/oxService/src/main/java/org/gluu/service/cache/RedisProviderType.java b/core-cache/src/main/java/org/gluu/service/cache/RedisProviderType.java
similarity index 78%
rename from oxService/src/main/java/org/gluu/service/cache/RedisProviderType.java
rename to core-cache/src/main/java/org/gluu/service/cache/RedisProviderType.java
index be5a3f1ad..fc6fd20ce 100644
--- a/oxService/src/main/java/org/gluu/service/cache/RedisProviderType.java
+++ b/core-cache/src/main/java/org/gluu/service/cache/RedisProviderType.java
@@ -7,5 +7,5 @@
*/
@XmlEnum(String.class)
public enum RedisProviderType {
- STANDALONE, CLUSTER, SHARDED
+ STANDALONE, CLUSTER, SHARDED, SENTINEL
}
diff --git a/core-cache/src/main/java/org/gluu/service/cache/RedisSentinelProvider.java b/core-cache/src/main/java/org/gluu/service/cache/RedisSentinelProvider.java
new file mode 100644
index 000000000..3cd572188
--- /dev/null
+++ b/core-cache/src/main/java/org/gluu/service/cache/RedisSentinelProvider.java
@@ -0,0 +1,123 @@
+package org.gluu.service.cache;
+
+import org.apache.commons.lang.SerializationUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import redis.clients.jedis.*;
+
+import java.io.Serializable;
+
+import static org.gluu.service.cache.RedisClusterProvider.hosts;
+
+/**
+ * Important : keep it weld free. It's reused by oxd !
+ *
+ * @author Yuriy Zabrovarnyy
+ */
+public class RedisSentinelProvider extends AbstractRedisProvider {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RedisSentinelProvider.class);
+
+ private JedisSentinelPool pool;
+
+ public RedisSentinelProvider(RedisConfiguration redisConfiguration) {
+ super(redisConfiguration);
+ }
+
+ public void create() {
+ try {
+ LOG.debug("Starting RedisSentinelProvider ... configuration:" + getRedisConfiguration());
+
+ String password = redisConfiguration.getPassword();
+ JedisPoolConfig poolConfig = createPoolConfig();
+ JedisClientConfig jedisClientConfig;
+
+ if (redisConfiguration.getUseSSL()) {
+ RedisProviderFactory.setSSLSystemProperties(redisConfiguration);
+ jedisClientConfig = DefaultJedisClientConfig.builder().ssl(true).password(password).build();
+ } else {
+ jedisClientConfig = DefaultJedisClientConfig.builder().ssl(false).password(password).build();
+ }
+
+ pool = new JedisSentinelPool(getRedisConfiguration().getSentinelMasterGroupName(),
+ hosts(getRedisConfiguration().getServers()), poolConfig, jedisClientConfig, jedisClientConfig);
+
+ testConnection();
+ LOG.debug("RedisSentinelProvider started.");
+ } catch (Exception e) {
+ LOG.error("Failed to start RedisSentinelProvider.", e);
+ throw new IllegalStateException("Error starting RedisSentinelProvider", e);
+ }
+ }
+
+ public void destroy() {
+ LOG.debug("Destroying RedisSentinelProvider");
+
+ try {
+ pool.close();
+ } catch (Exception e) {
+ LOG.error("Failed to destroy RedisSentinelProvider", e);
+ return;
+ }
+
+ LOG.debug("Destroyed RedisSentinelProvider");
+ }
+
+ @Override
+ public JedisSentinelPool getDelegate() {
+ return pool;
+ }
+
+ @Override
+ public boolean hasKey(String key) {
+ try (final Jedis resource = pool.getResource()) {
+ Boolean hasKey = resource.exists(key);
+
+ return Boolean.TRUE.equals(hasKey);
+ }
+ }
+
+ @Override
+ public Object get(String key) {
+ try (final Jedis resource = pool.getResource()) {
+ byte[] value = resource.get(key.getBytes());
+ Object deserialized = null;
+ if (value != null && value.length > 0) {
+ deserialized = SerializationUtils.deserialize(value);
+ }
+ return deserialized;
+ }
+ }
+
+ @Override
+ public void put(int expirationInSeconds, String key, Object object) {
+ try (final Jedis resource = pool.getResource()) {
+ String status = resource.setex(key.getBytes(), expirationInSeconds, SerializationUtils.serialize((Serializable) object));
+ LOG.trace("put - key: " + key + ", status: " + status);
+ }
+ }
+
+ @Override
+ public void put(String key, Object object) {
+ try (final Jedis resource = pool.getResource()) {
+ String status = resource.set(key.getBytes(), SerializationUtils.serialize((Serializable) object));
+ LOG.trace("put - key: " + key + ", status: " + status);
+ }
+ }
+
+ @Override
+ public void remove(String key) {
+ try (final Jedis resource = pool.getResource()) {
+ Long entriesRemoved = resource.del(key.getBytes());
+ LOG.trace("remove - key: " + key + ", entriesRemoved: " + entriesRemoved);
+ }
+ }
+
+ @Override
+ public void clear() {
+ try (final Jedis resource = pool.getResource()) {
+ resource.flushAll();
+ LOG.trace("clear");
+ }
+ }
+}
diff --git a/oxService/src/main/java/org/gluu/service/cache/RedisSetParams.java b/core-cache/src/main/java/org/gluu/service/cache/RedisSetParams.java
similarity index 98%
rename from oxService/src/main/java/org/gluu/service/cache/RedisSetParams.java
rename to core-cache/src/main/java/org/gluu/service/cache/RedisSetParams.java
index a3f51125a..22cb32a88 100644
--- a/oxService/src/main/java/org/gluu/service/cache/RedisSetParams.java
+++ b/core-cache/src/main/java/org/gluu/service/cache/RedisSetParams.java
@@ -3,7 +3,7 @@
import java.util.ArrayList;
import redis.clients.jedis.params.Params;
-import redis.clients.util.SafeEncoder;
+import redis.clients.jedis.util.SafeEncoder;
/**
* Taken from here
diff --git a/oxService/src/main/java/org/gluu/service/cache/RedisShardedProvider.java b/core-cache/src/main/java/org/gluu/service/cache/RedisShardedProvider.java
similarity index 85%
rename from oxService/src/main/java/org/gluu/service/cache/RedisShardedProvider.java
rename to core-cache/src/main/java/org/gluu/service/cache/RedisShardedProvider.java
index b69e754d6..e25fd6564 100644
--- a/oxService/src/main/java/org/gluu/service/cache/RedisShardedProvider.java
+++ b/core-cache/src/main/java/org/gluu/service/cache/RedisShardedProvider.java
@@ -2,16 +2,15 @@
import org.apache.commons.lang.SerializationUtils;
import org.apache.commons.lang.StringUtils;
+import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;
import javax.net.ssl.SSLParameters;
-import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
@@ -35,8 +34,9 @@ public void create() {
try {
LOG.debug("Starting RedisShardedProvider ... configuration:" + redisConfiguration);
- JedisPoolConfig poolConfig = new JedisPoolConfig();
- poolConfig.setMaxTotal(1000);
+ GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig<>();
+ poolConfig.setMaxTotal(redisConfiguration.getMaxTotalConnections());
+ poolConfig.setMaxIdle(redisConfiguration.getMaxIdleConnections());
poolConfig.setMinIdle(2);
pool = new ShardedJedisPool(poolConfig, shards(redisConfiguration));
@@ -44,7 +44,7 @@ public void create() {
testConnection();
LOG.debug("RedisShardedProvider started.");
} catch (Exception e) {
- LOG.error("Failed to start RedisShardedProvider.");
+ LOG.error("Failed to start RedisShardedProvider.", e);
throw new IllegalStateException("Error starting RedisShardedProvider", e);
}
}
@@ -63,9 +63,10 @@ private static List shards(RedisConfiguration configuration) {
try {
final JedisShardInfo shardInfo;
if (configuration.getUseSSL()) {
- if (StringUtils.isNotBlank(configuration.getSslTrustStoreFilePath())) {
+ if (StringUtils.isNotBlank(configuration.getSslTrustStoreFilePath())
+ && StringUtils.isNotBlank(configuration.getSslKeyStoreFilePath())) {
shardInfo = new JedisShardInfo(host, port, true,
- RedisProviderFactory.createTrustStoreSslSocketFactory(new File(configuration.getSslTrustStoreFilePath())),
+ RedisProviderFactory.createSslSocketFactory(configuration),
new SSLParameters(), new DefaultHostnameVerifier());
} else {
shardInfo = new JedisShardInfo(host, port, true);
@@ -97,6 +98,15 @@ public ShardedJedisPool getDelegate() {
return pool;
}
+ @Override
+ public boolean hasKey(String key) {
+ try (final ShardedJedis resource = pool.getResource()) {
+ Boolean hasKey = resource.exists(key);
+
+ return Boolean.TRUE.equals(hasKey);
+ }
+ }
+
@Override
public Object get(String key) {
ShardedJedis jedis = pool.getResource();
diff --git a/oxService/src/main/java/org/gluu/service/cache/RedisStandaloneProvider.java b/core-cache/src/main/java/org/gluu/service/cache/RedisStandaloneProvider.java
similarity index 66%
rename from oxService/src/main/java/org/gluu/service/cache/RedisStandaloneProvider.java
rename to core-cache/src/main/java/org/gluu/service/cache/RedisStandaloneProvider.java
index 0910d056f..d980ba62a 100644
--- a/oxService/src/main/java/org/gluu/service/cache/RedisStandaloneProvider.java
+++ b/core-cache/src/main/java/org/gluu/service/cache/RedisStandaloneProvider.java
@@ -5,11 +5,14 @@
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import redis.clients.jedis.*;
+import redis.clients.jedis.HostAndPort;
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.JedisPool;
+import redis.clients.jedis.JedisPoolConfig;
import javax.annotation.PreDestroy;
import javax.net.ssl.SSLParameters;
-import java.io.File;
+import javax.net.ssl.SSLSocketFactory;
import java.io.Serializable;
/**
@@ -22,7 +25,6 @@ public class RedisStandaloneProvider extends AbstractRedisProvider {
private static final Logger LOG = LoggerFactory.getLogger(RedisStandaloneProvider.class);
private JedisPool pool;
-
public RedisStandaloneProvider(RedisConfiguration redisConfiguratio) {
super(redisConfiguratio);
}
@@ -31,39 +33,29 @@ public void create() {
LOG.debug("Starting RedisStandaloneProvider ...");
try {
- JedisPoolConfig poolConfig = new JedisPoolConfig();
- poolConfig.setMaxTotal(1000);
- poolConfig.setMinIdle(2);
+ JedisPoolConfig poolConfig = createPoolConfig();
HostAndPort hostAndPort = RedisClusterProvider.hosts(redisConfiguration.getServers()).iterator().next();
-
+ String password = redisConfiguration.getPassword();
if (redisConfiguration.getUseSSL()) {
- if (StringUtils.isNotBlank(redisConfiguration.getSslTrustStoreFilePath())) {
- if (StringUtils.isBlank(redisConfiguration.getDecryptedPassword())) {
- pool = new JedisPool(poolConfig, hostAndPort.getHost(), hostAndPort.getPort(), true,
- RedisProviderFactory.createTrustStoreSslSocketFactory(new File(redisConfiguration.getSslTrustStoreFilePath())), new SSLParameters(), new DefaultHostnameVerifier());
- } else {
- pool = new JedisPool(poolConfig, hostAndPort.getHost(), hostAndPort.getPort(), Protocol.DEFAULT_TIMEOUT, redisConfiguration.getDecryptedPassword(), true,
- RedisProviderFactory.createTrustStoreSslSocketFactory(new File(redisConfiguration.getSslTrustStoreFilePath())), new SSLParameters(), new DefaultHostnameVerifier());
- }
+ if (StringUtils.isNotBlank(redisConfiguration.getSslTrustStoreFilePath())
+ && StringUtils.isNotBlank(redisConfiguration.getSslKeyStoreFilePath())) {
+ SSLSocketFactory sslSocketFactory = RedisProviderFactory.createSslSocketFactory(redisConfiguration);
+
+ pool = new JedisPool(poolConfig, hostAndPort.getHost(), hostAndPort.getPort(), true,
+ sslSocketFactory, new SSLParameters(), new DefaultHostnameVerifier());
} else {
- if (StringUtils.isBlank(redisConfiguration.getDecryptedPassword())) {
- pool = new JedisPool(poolConfig, hostAndPort.getHost(), hostAndPort.getPort(), true);
- } else {
- pool = new JedisPool(poolConfig, hostAndPort.getHost(), hostAndPort.getPort(), Protocol.DEFAULT_TIMEOUT, redisConfiguration.getDecryptedPassword(), true);
- }
+ pool = new JedisPool(poolConfig, hostAndPort.getHost(), hostAndPort.getPort(),
+ redisConfiguration.getConnectionTimeout(), password, true);
}
} else {
- if (StringUtils.isBlank(redisConfiguration.getDecryptedPassword())) {
- pool = new JedisPool(poolConfig, hostAndPort.getHost(), hostAndPort.getPort());
- } else {
- pool = new JedisPool(poolConfig, hostAndPort.getHost(), hostAndPort.getPort(), Protocol.DEFAULT_TIMEOUT, redisConfiguration.getDecryptedPassword());
- }
+ pool = new JedisPool(poolConfig, hostAndPort.getHost(), hostAndPort.getPort(), redisConfiguration.getConnectionTimeout(), password);
}
testConnection();
LOG.debug("RedisStandaloneProvider started.");
} catch (Exception e) {
+ LOG.error("Problems connecting with Redis", e);
throw new IllegalStateException("Error starting RedisStandaloneProvider", e);
}
}
@@ -82,6 +74,13 @@ public JedisPool getDelegate() {
return pool;
}
+ @Override
+ public boolean hasKey(String key) {
+ Boolean hasKey = pool.getResource().exists(key);
+
+ return Boolean.TRUE.equals(hasKey);
+ }
+
@Override
public Object get(String key) {
Jedis jedis = pool.getResource();
diff --git a/core-cache/src/main/java/org/gluu/service/cache/StandaloneCacheProviderFactory.java b/core-cache/src/main/java/org/gluu/service/cache/StandaloneCacheProviderFactory.java
new file mode 100644
index 000000000..209a0e709
--- /dev/null
+++ b/core-cache/src/main/java/org/gluu/service/cache/StandaloneCacheProviderFactory.java
@@ -0,0 +1,88 @@
+package org.gluu.service.cache;
+
+import org.gluu.persist.PersistenceEntryManager;
+import org.gluu.util.StringHelper;
+import org.gluu.util.security.StringEncrypter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Yuriy Movchan Date: 01/15/2020
+ */
+public class StandaloneCacheProviderFactory {
+
+ private static final Logger LOG = LoggerFactory.getLogger(StandaloneCacheProviderFactory.class);
+
+ private PersistenceEntryManager entryManager;
+ private StringEncrypter stringEncrypter;
+
+ public StandaloneCacheProviderFactory(PersistenceEntryManager entryManager, StringEncrypter stringEncrypter) {
+ this.entryManager = entryManager;
+ this.stringEncrypter = stringEncrypter;
+ }
+
+ public CacheProvider> getCacheProvider(CacheConfiguration cacheConfiguration) {
+ CacheProviderType cacheProviderType = cacheConfiguration.getCacheProviderType();
+
+ if (cacheProviderType == null) {
+ LOG.error("Failed to initialize cacheProvider, cacheProviderType is null. Fallback to IN_MEMORY type.");
+ cacheProviderType = CacheProviderType.IN_MEMORY;
+ }
+
+ // Create bean
+ AbstractCacheProvider> cacheProvider = null;
+ switch (cacheProviderType) {
+ case IN_MEMORY:
+ InMemoryCacheProvider inMemoryCacheProvider = new InMemoryCacheProvider();
+ inMemoryCacheProvider.configure(cacheConfiguration);
+ inMemoryCacheProvider.init();
+
+ cacheProvider = inMemoryCacheProvider;
+ break;
+ case MEMCACHED:
+ MemcachedProvider memcachedProvider = new MemcachedProvider();
+ memcachedProvider.configure(cacheConfiguration);
+ memcachedProvider.init();
+
+ cacheProvider = memcachedProvider;
+ break;
+ case REDIS:
+ if (stringEncrypter == null) {
+ throw new RuntimeException("Factory is not initialized properly. stringEncrypter is not specified");
+ }
+
+ RedisProvider redisProvider = new RedisProvider();
+ redisProvider.configure(cacheConfiguration, stringEncrypter);
+ redisProvider.init();
+
+ cacheProvider = redisProvider;
+ break;
+ case NATIVE_PERSISTENCE:
+ if (entryManager == null) {
+ throw new RuntimeException("Factory is not initialized properly. entryManager is not specified");
+ }
+
+ NativePersistenceCacheProvider nativePersistenceCacheProvider = new NativePersistenceCacheProvider();
+ nativePersistenceCacheProvider.configure(cacheConfiguration, entryManager);
+
+ // TODO: Remove after configuration fix
+ if (StringHelper.isEmpty(cacheConfiguration.getNativePersistenceConfiguration().getBaseDn())) {
+ cacheConfiguration.getNativePersistenceConfiguration().setBaseDn("o=gluu");
+ }
+
+ nativePersistenceCacheProvider.init();
+
+ cacheProvider = nativePersistenceCacheProvider;
+ break;
+ }
+
+ if (cacheProvider == null) {
+ throw new RuntimeException("Failed to initialize cacheProvider, cacheProviderType is unsupported: " + cacheProviderType);
+ }
+
+ cacheProvider.create();
+
+ return cacheProvider;
+ }
+
+}
diff --git a/persistence-cdi/src/main/resources/META-INF/beans.xml b/core-cache/src/main/resources/META-INF/beans.xml
similarity index 100%
rename from persistence-cdi/src/main/resources/META-INF/beans.xml
rename to core-cache/src/main/resources/META-INF/beans.xml
diff --git a/persistence-standalone/pom.xml b/core-cdi/pom.xml
similarity index 64%
rename from persistence-standalone/pom.xml
rename to core-cdi/pom.xml
index 1da83e906..91dbff937 100644
--- a/persistence-standalone/pom.xml
+++ b/core-cdi/pom.xml
@@ -2,14 +2,13 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
- org.gluu
- oxcore-persistence-standalone
- Persistence standalone services
+ oxcore-cdi
+ Reusable CDI classes which not depend on specific framework
org.gluu
oxcore
- 4.0.0-SNAPSHOT
+ 4.5.6-SNAPSHOT
@@ -31,24 +30,25 @@
+
- org.gluu
- oxcore-persistence-cdi
- ${project.version}
+ org.slf4j
+ slf4j-api
+ provided
+
+
javax.enterprise
cdi-api
+ provided
+
+
- org.reflections
- reflections
+ org.quartz-scheduler
+ quartz
-
- com.google.guava
- guava
- 20.0
-
\ No newline at end of file
diff --git a/oxService/src/main/java/org/gluu/service/cdi/async/Asynchronous.java b/core-cdi/src/main/java/org/gluu/service/cdi/async/Asynchronous.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/service/cdi/async/Asynchronous.java
rename to core-cdi/src/main/java/org/gluu/service/cdi/async/Asynchronous.java
diff --git a/oxService/src/main/java/org/gluu/service/cdi/event/Scheduled.java b/core-cdi/src/main/java/org/gluu/service/cdi/event/Scheduled.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/service/cdi/event/Scheduled.java
rename to core-cdi/src/main/java/org/gluu/service/cdi/event/Scheduled.java
diff --git a/oxService/src/main/java/org/gluu/service/timer/event/TimerEvent.java b/core-cdi/src/main/java/org/gluu/service/timer/event/TimerEvent.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/service/timer/event/TimerEvent.java
rename to core-cdi/src/main/java/org/gluu/service/timer/event/TimerEvent.java
diff --git a/oxService/src/main/java/org/gluu/service/timer/schedule/JobShedule.java b/core-cdi/src/main/java/org/gluu/service/timer/schedule/JobShedule.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/service/timer/schedule/JobShedule.java
rename to core-cdi/src/main/java/org/gluu/service/timer/schedule/JobShedule.java
diff --git a/oxService/src/main/java/org/gluu/service/timer/schedule/TimerSchedule.java b/core-cdi/src/main/java/org/gluu/service/timer/schedule/TimerSchedule.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/service/timer/schedule/TimerSchedule.java
rename to core-cdi/src/main/java/org/gluu/service/timer/schedule/TimerSchedule.java
diff --git a/persistence-couchbase/src/main/resources/META-INF/beans.xml b/core-cdi/src/main/resources/META-INF/beans.xml
similarity index 100%
rename from persistence-couchbase/src/main/resources/META-INF/beans.xml
rename to core-cdi/src/main/resources/META-INF/beans.xml
diff --git a/core-document-store/pom.xml b/core-document-store/pom.xml
new file mode 100644
index 000000000..65fe04010
--- /dev/null
+++ b/core-document-store/pom.xml
@@ -0,0 +1,112 @@
+
+
+ 4.0.0
+ oxcore-document-store
+ Caches support
+
+
+ org.gluu
+ oxcore
+ 4.5.6-SNAPSHOT
+
+
+
+ ${maven.min-version}
+
+
+
+
+
+ src/main/resources
+ true
+
+ **/*.xml
+ **/services/*
+ **/*.properties
+
+
+
+
+
+ src/test/resources
+ true
+
+ **/*.xml
+ **/services/*
+ **/*.properties
+
+
+
+
+
+
+
+
+ org.gluu
+ oxcore-util
+ ${project.version}
+
+
+ org.gluu
+ gluu-orm-core
+ ${project.version}
+
+
+ org.gluu
+ gluu-orm-annotation
+ ${project.version}
+
+
+
+ javax.enterprise
+ cdi-api
+ provided
+
+
+
+ javax.inject
+ javax.inject
+
+
+
+
+ javax.jcr
+ jcr
+
+
+ org.apache.jackrabbit
+ jackrabbit-core
+
+
+ org.apache.jackrabbit
+ jackrabbit-jcr-rmi
+
+
+ org.apache.jackrabbit
+ jackrabbit-webdav
+
+
+ com.github.lookfirst
+ sardine
+
+
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+
+
+
+
+ org.testng
+ testng
+
+
+ javax.annotation
+ javax.annotation-api
+
+
+
+
\ No newline at end of file
diff --git a/core-document-store/src/main/java/org/gluu/service/document/store/LocalDocumentStore.java b/core-document-store/src/main/java/org/gluu/service/document/store/LocalDocumentStore.java
new file mode 100644
index 000000000..f637652c4
--- /dev/null
+++ b/core-document-store/src/main/java/org/gluu/service/document/store/LocalDocumentStore.java
@@ -0,0 +1,32 @@
+package org.gluu.service.document.store;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.enterprise.util.AnnotationLiteral;
+import javax.inject.Qualifier;
+
+/**
+ * @author Yuriy Movchan on 04/10/2020
+ */
+@Qualifier
+@Retention(RUNTIME)
+@Target({ TYPE, METHOD, FIELD })
+@Documented
+public @interface LocalDocumentStore {
+
+ final class Literal extends AnnotationLiteral implements LocalDocumentStore {
+
+ public static final Literal INSTANCE = new Literal();
+
+ private static final long serialVersionUID = 1L;
+
+ }
+
+}
diff --git a/core-document-store/src/main/java/org/gluu/service/document/store/StandaloneDocumentStoreProviderFactory.java b/core-document-store/src/main/java/org/gluu/service/document/store/StandaloneDocumentStoreProviderFactory.java
new file mode 100644
index 000000000..c1bb573b3
--- /dev/null
+++ b/core-document-store/src/main/java/org/gluu/service/document/store/StandaloneDocumentStoreProviderFactory.java
@@ -0,0 +1,96 @@
+package org.gluu.service.document.store;
+
+import org.gluu.persist.PersistenceEntryManager;
+import org.gluu.service.document.store.conf.DocumentStoreConfiguration;
+import org.gluu.service.document.store.conf.DocumentStoreType;
+import org.gluu.service.document.store.provider.DBDocumentStoreProvider;
+import org.gluu.service.document.store.provider.DocumentStoreProvider;
+import org.gluu.service.document.store.provider.JcaDocumentStoreProvider;
+import org.gluu.service.document.store.provider.LocalDocumentStoreProvider;
+import org.gluu.service.document.store.provider.WebDavDocumentStoreProvider;
+import org.gluu.util.security.StringEncrypter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Yuriy Movchan on 04/10/2020
+ */
+public class StandaloneDocumentStoreProviderFactory {
+
+ private static final Logger LOG = LoggerFactory.getLogger(StandaloneDocumentStoreProviderFactory.class);
+
+ private StringEncrypter stringEncrypter;
+ private PersistenceEntryManager persistenceEntryManager;
+
+ public StandaloneDocumentStoreProviderFactory() {
+ }
+
+ public StandaloneDocumentStoreProviderFactory(StringEncrypter stringEncrypter) {
+ this.stringEncrypter = stringEncrypter;
+ }
+
+ public StandaloneDocumentStoreProviderFactory(PersistenceEntryManager persistenceEntryManager) {
+ this.persistenceEntryManager = persistenceEntryManager;
+ }
+
+ public DocumentStoreProvider getDocumentStoreProvider(DocumentStoreConfiguration documentStoreConfiguration) {
+ DocumentStoreType documentStoreType = documentStoreConfiguration.getDocumentStoreType();
+
+ if (documentStoreType == null) {
+ LOG.error("Failed to initialize documentStoreProvider, documentStoreProviderType is null. Fallback to LOCAL type.");
+ documentStoreType = DocumentStoreType.LOCAL;
+ }
+
+ // Create bean
+ DocumentStoreProvider documentStoreProvider = null;
+ switch (documentStoreType) {
+ case LOCAL:
+ LocalDocumentStoreProvider localDocumentStoreProvider = new LocalDocumentStoreProvider();
+ localDocumentStoreProvider.configure(documentStoreConfiguration);
+ localDocumentStoreProvider.init();
+
+ documentStoreProvider = localDocumentStoreProvider;
+ break;
+ case JCA:
+ if (stringEncrypter == null) {
+ throw new RuntimeException("Factory is not initialized properly. stringEncrypter is not specified");
+ }
+
+ JcaDocumentStoreProvider jcaDocumentStoreProvider = new JcaDocumentStoreProvider();
+ jcaDocumentStoreProvider.configure(documentStoreConfiguration, stringEncrypter);
+ jcaDocumentStoreProvider.init();
+
+ documentStoreProvider = jcaDocumentStoreProvider;
+ break;
+ case WEB_DAV:
+ if (stringEncrypter == null) {
+ throw new RuntimeException("Factory is not initialized properly. stringEncrypter is not specified");
+ }
+
+ WebDavDocumentStoreProvider webDavDocumentStoreProvider = new WebDavDocumentStoreProvider();
+ webDavDocumentStoreProvider.configure(documentStoreConfiguration, stringEncrypter);
+ webDavDocumentStoreProvider.init();
+
+ documentStoreProvider = webDavDocumentStoreProvider;
+ break;
+ case DB:
+ DBDocumentStoreProvider dbDocumentStoreProvider = new DBDocumentStoreProvider();
+ dbDocumentStoreProvider.configure(documentStoreConfiguration, persistenceEntryManager);
+ dbDocumentStoreProvider.init();
+
+ documentStoreProvider = dbDocumentStoreProvider;
+ break;
+ }
+
+
+ if (documentStoreProvider == null) {
+ throw new RuntimeException(
+ "Failed to initialize documentStoreProvider, documentStoreProviderType is unsupported: " + documentStoreType);
+ }
+
+ documentStoreProvider.create();
+
+ return documentStoreProvider;
+ }
+
+}
diff --git a/core-document-store/src/main/java/org/gluu/service/document/store/conf/DBDocumentStoreConfiguration.java b/core-document-store/src/main/java/org/gluu/service/document/store/conf/DBDocumentStoreConfiguration.java
new file mode 100644
index 000000000..1dbd11b05
--- /dev/null
+++ b/core-document-store/src/main/java/org/gluu/service/document/store/conf/DBDocumentStoreConfiguration.java
@@ -0,0 +1,20 @@
+package org.gluu.service.document.store.conf;
+
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+/**
+ * @author shekhar L. on 27/04/2022
+ */
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class DBDocumentStoreConfiguration implements Serializable {
+
+ private static final long serialVersionUID = 3380170170265842538L;
+
+ @Override
+ public String toString() {
+ return "DBDocumentStoreConfiguration []";
+ }
+
+}
diff --git a/core-document-store/src/main/java/org/gluu/service/document/store/conf/DocumentStoreConfiguration.java b/core-document-store/src/main/java/org/gluu/service/document/store/conf/DocumentStoreConfiguration.java
new file mode 100644
index 000000000..54d1aa36e
--- /dev/null
+++ b/core-document-store/src/main/java/org/gluu/service/document/store/conf/DocumentStoreConfiguration.java
@@ -0,0 +1,72 @@
+package org.gluu.service.document.store.conf;
+
+import java.io.Serializable;
+
+import javax.enterprise.inject.Vetoed;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+/**
+ * @author Yuriy Movchan on 04/10/2020
+ */
+@JsonIgnoreProperties(ignoreUnknown = true)
+@Vetoed
+public class DocumentStoreConfiguration implements Serializable {
+
+ private static final long serialVersionUID = 2519892725606554887L;
+
+ private DocumentStoreType documentStoreType;
+
+ private LocalDocumentStoreConfiguration localConfiguration;
+
+ private JcaDocumentStoreConfiguration jcaConfiguration;
+
+ private WebDavDocumentStoreConfiguration webDavConfiguration;
+ private DBDocumentStoreConfiguration dbConfiguration;
+
+ public DocumentStoreType getDocumentStoreType() {
+ return documentStoreType;
+ }
+
+ public void setDocumentStoreType(DocumentStoreType documentStoreType) {
+ this.documentStoreType = documentStoreType;
+ }
+
+ public LocalDocumentStoreConfiguration getLocalConfiguration() {
+ return localConfiguration;
+ }
+
+ public void setLocalConfiguration(LocalDocumentStoreConfiguration localConfiguration) {
+ this.localConfiguration = localConfiguration;
+ }
+
+ public JcaDocumentStoreConfiguration getJcaConfiguration() {
+ return jcaConfiguration;
+ }
+
+ public void setJcaConfiguration(JcaDocumentStoreConfiguration jcaConfiguration) {
+ this.jcaConfiguration = jcaConfiguration;
+ }
+
+ public WebDavDocumentStoreConfiguration getWebDavConfiguration() {
+ return webDavConfiguration;
+ }
+
+ public void setWebDavConfiguration(WebDavDocumentStoreConfiguration webDavConfiguration) {
+ this.webDavConfiguration = webDavConfiguration;
+ }
+
+ public DBDocumentStoreConfiguration getDbConfiguration() {
+ return dbConfiguration;
+ }
+
+ public void setDbConfiguration(DBDocumentStoreConfiguration dbDavConfiguration) {
+ this.dbConfiguration = dbDavConfiguration;
+ }
+
+ @Override
+ public String toString() {
+ return "DocumentStoreConfiguration [documentStoreType=" + documentStoreType + ", localConfiguration=" + localConfiguration
+ + ", jcaConfiguration=" + jcaConfiguration + ", webDavConfiguration=" + webDavConfiguration + ", DBConfiguration=" + dbConfiguration + "]";
+ }
+}
diff --git a/core-document-store/src/main/java/org/gluu/service/document/store/conf/DocumentStoreType.java b/core-document-store/src/main/java/org/gluu/service/document/store/conf/DocumentStoreType.java
new file mode 100644
index 000000000..e941823f9
--- /dev/null
+++ b/core-document-store/src/main/java/org/gluu/service/document/store/conf/DocumentStoreType.java
@@ -0,0 +1,11 @@
+package org.gluu.service.document.store.conf;
+
+import javax.xml.bind.annotation.XmlEnum;
+
+/**
+ * @author Yuriy Movchan on 04/10/2020
+ */
+@XmlEnum(String.class)
+public enum DocumentStoreType {
+ LOCAL, JCA, WEB_DAV, DB
+}
diff --git a/core-document-store/src/main/java/org/gluu/service/document/store/conf/JcaDocumentStoreConfiguration.java b/core-document-store/src/main/java/org/gluu/service/document/store/conf/JcaDocumentStoreConfiguration.java
new file mode 100644
index 000000000..65da3a34c
--- /dev/null
+++ b/core-document-store/src/main/java/org/gluu/service/document/store/conf/JcaDocumentStoreConfiguration.java
@@ -0,0 +1,80 @@
+package org.gluu.service.document.store.conf;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+import java.io.Serializable;
+
+/**
+ * @author Yuriy Movchan on 04/10/2020
+ */
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class JcaDocumentStoreConfiguration implements Serializable {
+
+ private static final long serialVersionUID = 3380170170265842427L;
+
+ private String serverUrl; // http://localhost:8080/rmi
+ private String workspaceName;
+ private int connectionTimeout;
+
+ private String userId;
+ private String password;
+
+ @JsonIgnore
+ private String decryptedPassword;
+
+ public String getServerUrl() {
+ return serverUrl;
+ }
+
+ public void setServerUrl(String serverUrl) {
+ this.serverUrl = serverUrl;
+ }
+
+ public String getWorkspaceName() {
+ return workspaceName;
+ }
+
+ public void setWorkspaceName(String workspaceName) {
+ this.workspaceName = workspaceName;
+ }
+
+ public int getConnectionTimeout() {
+ return connectionTimeout;
+ }
+
+ public void setConnectionTimeout(int connectionTimeout) {
+ this.connectionTimeout = connectionTimeout;
+ }
+
+ public String getUserId() {
+ return userId;
+ }
+
+ public void setUserId(String userId) {
+ this.userId = userId;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public String getDecryptedPassword() {
+ return decryptedPassword;
+ }
+
+ public void setDecryptedPassword(String decryptedPassword) {
+ this.decryptedPassword = decryptedPassword;
+ }
+
+ @Override
+ public String toString() {
+ return "JcaDocumentStoreConfiguration [serverUrl=" + serverUrl + ", workspaceName=" + workspaceName + ", connectionTimeout="
+ + connectionTimeout + ", userId=" + userId + "]";
+ }
+
+}
diff --git a/core-document-store/src/main/java/org/gluu/service/document/store/conf/LocalDocumentStoreConfiguration.java b/core-document-store/src/main/java/org/gluu/service/document/store/conf/LocalDocumentStoreConfiguration.java
new file mode 100644
index 000000000..1229a0d34
--- /dev/null
+++ b/core-document-store/src/main/java/org/gluu/service/document/store/conf/LocalDocumentStoreConfiguration.java
@@ -0,0 +1,32 @@
+package org.gluu.service.document.store.conf;
+
+import java.io.Serializable;
+
+import javax.xml.bind.annotation.XmlElement;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+/**
+ * @author Yuriy Movchan on 04/10/2020
+ */
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class LocalDocumentStoreConfiguration implements Serializable {
+
+ private static final long serialVersionUID = -2403247753790576983L;
+
+ @XmlElement(name = "baseLocation")
+ private String baseLocation = "/";
+
+ public String getBaseLocation() {
+ return baseLocation;
+ }
+
+ public void setBaseLocation(String baseLocation) {
+ this.baseLocation = baseLocation;
+ }
+
+ @Override
+ public String toString() {
+ return "LocalConfiguration [baseLocation=" + baseLocation + "]";
+ }
+}
diff --git a/core-document-store/src/main/java/org/gluu/service/document/store/conf/WebDavDocumentStoreConfiguration.java b/core-document-store/src/main/java/org/gluu/service/document/store/conf/WebDavDocumentStoreConfiguration.java
new file mode 100644
index 000000000..81b22fd5f
--- /dev/null
+++ b/core-document-store/src/main/java/org/gluu/service/document/store/conf/WebDavDocumentStoreConfiguration.java
@@ -0,0 +1,77 @@
+package org.gluu.service.document.store.conf;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+import java.io.Serializable;
+
+/**
+ * @author Yuriy Movchan on 04/10/2020
+ */
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class WebDavDocumentStoreConfiguration implements Serializable {
+
+ private static final long serialVersionUID = 3380170170265842538L;
+
+ private String serverUrl; // http://localhost:8080
+ private String workspaceName;
+ private int connectionTimeout;
+
+ private String userId;
+ private String password;
+ private String decryptedPassword;
+
+ public String getServerUrl() {
+ return serverUrl;
+ }
+
+ public void setServerUrl(String serverUrl) {
+ this.serverUrl = serverUrl;
+ }
+
+ public String getWorkspaceName() {
+ return workspaceName;
+ }
+
+ public void setWorkspaceName(String workspaceName) {
+ this.workspaceName = workspaceName;
+ }
+
+ public int getConnectionTimeout() {
+ return connectionTimeout;
+ }
+
+ public void setConnectionTimeout(int connectionTimeout) {
+ this.connectionTimeout = connectionTimeout;
+ }
+
+ public String getUserId() {
+ return userId;
+ }
+
+ public void setUserId(String userId) {
+ this.userId = userId;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public String getDecryptedPassword() {
+ return decryptedPassword;
+ }
+
+ public void setDecryptedPassword(String decryptedPassword) {
+ this.decryptedPassword = decryptedPassword;
+ }
+
+ @Override
+ public String toString() {
+ return "WebDavDocumentStoreConfiguration [serverUrl=" + serverUrl + ", workspaceName=" + workspaceName + ", connectionTimeout="
+ + connectionTimeout + ", userId=" + userId + "]";
+ }
+
+}
diff --git a/core-document-store/src/main/java/org/gluu/service/document/store/provider/DBDocumentStoreProvider.java b/core-document-store/src/main/java/org/gluu/service/document/store/provider/DBDocumentStoreProvider.java
new file mode 100644
index 000000000..ed1b8209b
--- /dev/null
+++ b/core-document-store/src/main/java/org/gluu/service/document/store/provider/DBDocumentStoreProvider.java
@@ -0,0 +1,236 @@
+package org.gluu.service.document.store.provider;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.List;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+
+import org.apache.commons.io.IOUtils;
+import org.gluu.persist.PersistenceEntryManager;
+import org.gluu.service.document.store.conf.DBDocumentStoreConfiguration;
+import org.gluu.service.document.store.conf.DocumentStoreConfiguration;
+import org.gluu.service.document.store.conf.DocumentStoreType;
+import org.gluu.service.document.store.service.DBDocumentService;
+import org.gluu.service.document.store.service.OxDocument;
+import org.gluu.util.StringHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Shekhar L. on 26/04/2022
+ */
+@ApplicationScoped
+public class DBDocumentStoreProvider extends DocumentStoreProvider {
+
+ @Inject
+ private Logger log;
+
+ @Inject
+ private DBDocumentService documentService;
+
+ @Inject
+ private DocumentStoreConfiguration documentStoreConfiguration;
+
+ private DBDocumentStoreConfiguration dbDocumentStoreConfiguration;
+
+ public DocumentStoreType getProviderType() {
+ return DocumentStoreType.DB;
+ }
+
+ @PostConstruct
+ public void init() {
+ this.dbDocumentStoreConfiguration = documentStoreConfiguration.getDbConfiguration();
+ }
+
+ public void configure(DocumentStoreConfiguration documentStoreConfiguration, PersistenceEntryManager persistenceEntryManager) {
+ this.log = LoggerFactory.getLogger(DBDocumentStoreProvider.class);
+ this.documentStoreConfiguration = documentStoreConfiguration;
+ if(documentService == null) {
+ this.documentService = new DBDocumentService(persistenceEntryManager);
+ }
+ }
+
+ @Override
+ public void create() {
+
+ }
+
+ @Override
+ public void destroy() {
+
+ }
+
+ @Override
+ public boolean hasDocument(String DisplayName) {
+ log.debug("Has document: '{}'", DisplayName);
+ if (StringHelper.isEmpty(DisplayName)) {
+ throw new IllegalArgumentException("Specified path should not be empty!");
+ }
+ OxDocument oxDocument = null;
+ try {
+ oxDocument = documentService.getOxDocumentByDisplayName(DisplayName);
+ if(oxDocument != null) {
+ return true;
+ }
+ } catch (Exception e) {
+ log.error("Failed to check if path '" + DisplayName + "' exists in repository", e);
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean saveDocument(String name, String documentContent, Charset charset, List moduleList) {
+ log.debug("Save document: '{}'", name);
+ try {
+ boolean update = true;
+ OxDocument oxDocument = documentService.getOxDocumentByDisplayName(name);
+ if (oxDocument == null) {
+ update = false;
+ oxDocument = new OxDocument();
+ oxDocument.setDisplayName(name);
+ oxDocument.setInum(documentService.generateInumForNewOxDocument());
+ String dn = "inum=" + oxDocument.getInum() + ",ou=document,o=gluu";
+ oxDocument.setDn(dn);
+ }
+
+ oxDocument.setDocument(documentContent);
+ oxDocument.setDescription(name);
+ oxDocument.setOxEnabled(true);
+ oxDocument.setOxModuleProperty(moduleList);
+
+ if (update)
+ documentService.updateOxDocument(oxDocument);
+ else
+ documentService.addOxDocument(oxDocument);
+ return true;
+
+ } catch (Exception ex) {
+ log.error("Failed to write document to file '{}'", name, ex);
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean saveDocumentStream(String name, InputStream documentStream, List moduleList) {
+ try {
+ // log.debug("Save document from stream: '{}'", name);
+ boolean update = true;
+ OxDocument oxDocument = documentService.getOxDocumentByDisplayName(name);
+ if (oxDocument == null) {
+ update = false;
+ oxDocument = new OxDocument();
+ oxDocument.setDisplayName(name);
+
+ String inum = documentService.generateInumForNewOxDocument();
+ oxDocument.setInum(inum);
+
+ String dn = "inum=" + oxDocument.getInum() + ",ou=document,o=gluu";
+ oxDocument.setDn(dn);
+ }
+ String documentContent = new String(documentStream.readAllBytes(), StandardCharsets.UTF_8);
+ oxDocument.setDocument(documentContent);
+ oxDocument.setDescription(name);
+ oxDocument.setOxEnabled(true);
+ oxDocument.setOxModuleProperty(moduleList);
+
+ if(update)
+ documentService.updateOxDocument(oxDocument);
+ else
+ documentService.addOxDocument(oxDocument);
+
+ return true;
+ } catch (IOException e) {
+ log.error("Failed to write document from stream to file '{}'", name, e);
+ } catch (Exception e) {
+ log.error("Failed to write document from stream to file '{}'", name, e);
+ }
+
+ return false;
+ }
+
+
+ @Override
+ public String readDocument(String name, Charset charset) {
+ log.debug("Read document: '{}'", name);
+ OxDocument oxDocument;
+ try {
+ oxDocument = documentService.getOxDocumentByDisplayName(name);
+ if(oxDocument != null) {
+ return oxDocument.getDocument();
+ }
+ } catch (Exception e) {
+ log.error("Failed to read document as stream from file '{}'", name, e);
+ }
+ return null;
+ }
+
+ @Override
+ public InputStream readDocumentAsStream(String name) {
+ log.debug("Read document as stream: '{}'", name);
+ String filecontecnt = readDocument(name, null);
+ if (filecontecnt == null) {
+ log.error("Document file '{}' isn't exist", name);
+ return null;
+ }
+
+ InputStream InputStream = new ByteArrayInputStream(filecontecnt.getBytes());
+ return InputStream;
+ }
+
+ @Override
+ public boolean renameDocument(String currentDisplayName, String destinationDisplayName) {
+ log.debug("Rename document: '{}' -> '{}'", currentDisplayName, destinationDisplayName);
+ OxDocument oxDocument;
+ try {
+ oxDocument = documentService.getOxDocumentByDisplayName(currentDisplayName);
+ if (oxDocument == null) {
+ log.error("Document doesn't Exist with the name '{}'", currentDisplayName);
+ return false;
+ }
+ oxDocument.setDisplayName(destinationDisplayName);
+ documentService.updateOxDocument(oxDocument);
+ OxDocument oxDocumentDestination = documentService.getOxDocumentByDisplayName(destinationDisplayName);
+ if(oxDocumentDestination == null) {
+ log.error("Failed to rename to destination file '{}'", destinationDisplayName);
+ return false;
+ }
+ } catch (Exception e) {
+ log.error("Failed to rename to destination file '{}'", destinationDisplayName);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean removeDocument(String inum) {
+ log.debug("Remove document: '{}'", inum);
+ OxDocument oxDocument;
+ try {
+ oxDocument = documentService.getOxDocumentByInum(inum);
+ if(oxDocument == null) {
+ log.error(" document not exist file '{}'", inum);
+ return false;
+ }
+
+ documentService.removeOxDocument(oxDocument);
+ OxDocument checkOxDocument = documentService.getOxDocumentByInum(inum);
+ if(checkOxDocument == null) {
+ return true;
+ }
+ return false;
+ } catch (Exception e) {
+ log.error("Failed to remove document file '{}'", inum, e);
+ }
+ return false;
+ }
+
+}
diff --git a/core-document-store/src/main/java/org/gluu/service/document/store/provider/DocumentStore.java b/core-document-store/src/main/java/org/gluu/service/document/store/provider/DocumentStore.java
new file mode 100644
index 000000000..72cc51ddf
--- /dev/null
+++ b/core-document-store/src/main/java/org/gluu/service/document/store/provider/DocumentStore.java
@@ -0,0 +1,52 @@
+package org.gluu.service.document.store.provider;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.util.List;
+
+import org.gluu.service.document.store.conf.DocumentStoreType;
+
+/**
+ * @author Yuriy Movchan on 04/10/2020
+ */
+public interface DocumentStore {
+
+ /**
+ * Method to check if there is key in cache
+ */
+ boolean hasDocument(String path);
+
+ /**
+ * Save document into store
+ */
+ boolean saveDocument(String path, String documentContent, Charset charset, List moduleList);
+
+ /**
+ * Save document stream into store
+ */
+ boolean saveDocumentStream(String path, InputStream documentStream, List moduleList);
+
+ /**
+ * Load document from store
+ */
+ String readDocument(String path, Charset charset);
+
+ /**
+ * Load document from store as stream
+ */
+ public InputStream readDocumentAsStream(String path) ;
+
+ /**
+ * Removes an object document from store
+ */
+ boolean removeDocument(String path);
+
+ /**
+ * Rename an object in document store
+ */
+ boolean renameDocument(String currentPath, String destinationPath);
+
+ public abstract DocumentStoreType getProviderType();
+
+}
\ No newline at end of file
diff --git a/core-document-store/src/main/java/org/gluu/service/document/store/provider/DocumentStoreProvider.java b/core-document-store/src/main/java/org/gluu/service/document/store/provider/DocumentStoreProvider.java
new file mode 100644
index 000000000..71364d7bf
--- /dev/null
+++ b/core-document-store/src/main/java/org/gluu/service/document/store/provider/DocumentStoreProvider.java
@@ -0,0 +1,12 @@
+package org.gluu.service.document.store.provider;
+
+/**
+ * @author Yuriy Movchan on 04/10/2020
+ */
+public abstract class DocumentStoreProvider implements DocumentStore {
+
+ public abstract void create();
+
+ public abstract void destroy();
+
+}
diff --git a/core-document-store/src/main/java/org/gluu/service/document/store/provider/DocumentStoreProviderFactory.java b/core-document-store/src/main/java/org/gluu/service/document/store/provider/DocumentStoreProviderFactory.java
new file mode 100644
index 000000000..01b9cbf9c
--- /dev/null
+++ b/core-document-store/src/main/java/org/gluu/service/document/store/provider/DocumentStoreProviderFactory.java
@@ -0,0 +1,92 @@
+package org.gluu.service.document.store.provider;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.Any;
+import javax.enterprise.inject.Instance;
+import javax.enterprise.inject.Produces;
+import javax.inject.Inject;
+
+import org.gluu.service.document.store.LocalDocumentStore;
+import org.gluu.service.document.store.conf.DocumentStoreConfiguration;
+import org.gluu.service.document.store.conf.DocumentStoreType;
+import org.slf4j.Logger;
+
+/**
+ * @author Yuriy Movchan on 04/10/2020
+ */
+@ApplicationScoped
+public class DocumentStoreProviderFactory {
+
+ @Inject
+ private Logger log;
+
+ @Inject
+ private DocumentStoreConfiguration documentStoreConfiguration;
+
+ @Inject
+ @Any
+ private Instance instance;
+
+ @Produces
+ @ApplicationScoped
+ public DocumentStoreProvider getDocumentStoreProvider() {
+ log.debug("Started to create document store provider");
+
+
+ return getDocumentStoreProvider(documentStoreConfiguration);
+ }
+
+ public DocumentStoreProvider getDocumentStoreProvider(DocumentStoreConfiguration documentStoreConfiguration) {
+ DocumentStoreType documentStoreType = documentStoreConfiguration.getDocumentStoreType();
+
+ if (documentStoreType == null) {
+ log.error("Failed to initialize DocumentStoreProvider, DocumentStoreProviderType is null. Fallback to LOCAL type.");
+ documentStoreType = DocumentStoreType.LOCAL;
+ }
+
+ // Create proxied bean
+ DocumentStoreProvider documentStoreProvider = null;
+ switch (documentStoreType) {
+ case LOCAL:
+ documentStoreProvider = instance.select(LocalDocumentStoreProvider.class).get();
+ break;
+ case JCA:
+ documentStoreProvider = instance.select(JcaDocumentStoreProvider.class).get();
+ break;
+ case WEB_DAV:
+ documentStoreProvider = instance.select(WebDavDocumentStoreProvider.class).get();
+ break;
+ case DB:
+ documentStoreProvider = instance.select(DBDocumentStoreProvider.class).get();
+ break;
+
+ }
+
+ if (documentStoreProvider == null) {
+ throw new RuntimeException("Failed to initialize DocumentStoreProvider, DocumentStoreProviderType is unsupported: " + documentStoreType);
+ }
+
+ documentStoreProvider.create();
+
+ return documentStoreProvider;
+ }
+
+ @Produces
+ @ApplicationScoped
+ @LocalDocumentStore
+ public DocumentStoreProvider getLocalDocumentStoreProvider() {
+ log.debug("Started to create local document store provider");
+
+ DocumentStoreType documentStoreType = DocumentStoreType.LOCAL;
+ DocumentStoreProvider documentStoreProvider = instance.select(LocalDocumentStoreProvider.class).get();
+
+ if (documentStoreProvider == null) {
+ throw new RuntimeException("Failed to initialize DocumentStoreProvider, DocumentStoreProviderType is unsupported: " + documentStoreType);
+ }
+
+ documentStoreProvider.create();
+
+ return documentStoreProvider;
+ }
+
+}
diff --git a/core-document-store/src/main/java/org/gluu/service/document/store/provider/JcaDocumentStoreProvider.java b/core-document-store/src/main/java/org/gluu/service/document/store/provider/JcaDocumentStoreProvider.java
new file mode 100644
index 000000000..30af4248a
--- /dev/null
+++ b/core-document-store/src/main/java/org/gluu/service/document/store/provider/JcaDocumentStoreProvider.java
@@ -0,0 +1,408 @@
+package org.gluu.service.document.store.provider;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.jcr.AccessDeniedException;
+import javax.jcr.Binary;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import javax.jcr.Value;
+import javax.jcr.lock.LockException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.version.VersionException;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.commons.JcrUtils;
+import org.apache.jackrabbit.rmi.repository.URLRemoteRepository;
+import org.gluu.service.document.store.conf.DocumentStoreConfiguration;
+import org.gluu.service.document.store.conf.DocumentStoreType;
+import org.gluu.service.document.store.conf.JcaDocumentStoreConfiguration;
+import org.gluu.util.StringHelper;
+import org.gluu.util.security.StringEncrypter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Yuriy Movchan on 04/10/2020
+ */
+@ApplicationScoped
+public class JcaDocumentStoreProvider extends DocumentStoreProvider {
+
+ @Inject
+ private Logger log;
+
+
+ @Inject
+ private DocumentStoreConfiguration documentStoreConfiguration;
+
+ @Inject
+ private StringEncrypter stringEncrypter;
+
+ private JcaDocumentStoreConfiguration jcaDocumentStoreConfiguration;
+
+ private URLRemoteRepository repository;
+ private SimpleCredentials credentials;
+ private String workspaceName;
+ private long connectionTimeout;
+
+ public JcaDocumentStoreProvider() {
+ }
+
+ @PostConstruct
+ public void init() {
+ this.jcaDocumentStoreConfiguration = documentStoreConfiguration.getJcaConfiguration();
+ }
+
+ public void create() {
+ try {
+ log.debug("Starting JcaDocumentStoreProvider ...");
+ decryptPassword(jcaDocumentStoreConfiguration);
+ this.repository = new URLRemoteRepository(jcaDocumentStoreConfiguration.getServerUrl());
+
+ String password = StringUtils.isBlank(jcaDocumentStoreConfiguration.getDecryptedPassword()) ? "" : jcaDocumentStoreConfiguration.getDecryptedPassword();
+
+ this.credentials = new SimpleCredentials(jcaDocumentStoreConfiguration.getUserId(),
+ password.toCharArray());
+
+ this.workspaceName = jcaDocumentStoreConfiguration.getWorkspaceName();
+ this.connectionTimeout = jcaDocumentStoreConfiguration.getConnectionTimeout();
+ } catch (Exception ex) {
+ throw new IllegalStateException("Error starting JcaDocumentStoreProvider", ex);
+ }
+ }
+
+ public void configure(DocumentStoreConfiguration documentStoreConfiguration, StringEncrypter stringEncrypter) {
+ this.log = LoggerFactory.getLogger(DocumentStoreConfiguration.class);
+ this.documentStoreConfiguration = documentStoreConfiguration;
+ this.stringEncrypter = stringEncrypter;
+ }
+
+ @PreDestroy
+ public void destroy() {
+ log.debug("Destroying JcaDocumentStoreProvider");
+
+ this.repository = null;
+
+ log.debug("Destroyed JcaDocumentStoreProvider");
+ }
+
+ public void setJcaDocumentStoreConfiguration(JcaDocumentStoreConfiguration jcaDocumentStoreConfiguration) {
+ this.jcaDocumentStoreConfiguration = jcaDocumentStoreConfiguration;
+ }
+
+ public DocumentStoreType getProviderType() {
+ return DocumentStoreType.JCA;
+ }
+
+ @Override
+ public boolean hasDocument(String path) {
+ log.debug("Has document: '{}'", path);
+
+ if (StringHelper.isEmpty(path)) {
+ throw new IllegalArgumentException("Specified path should not be empty!");
+ }
+
+ Node fileNode = null;
+ Session session;
+ try {
+ session = getSessionWithTimeout();
+ try {
+ fileNode = JcrUtils.getNodeIfExists(getNormalizedPath(path), session);
+ } finally {
+ closeSession(session);
+ }
+ } catch (RepositoryException ex) {
+ log.error("Failed to check if path '" + path + "' exists in repository", ex);
+ }
+
+ return fileNode != null;
+ }
+
+ @Override
+ public boolean saveDocument(String path, String documentContent, Charset charset, List moduleList) {
+ log.debug("Save document: '{}'", path);
+
+ String normalizedPath = getNormalizedPath(path);
+ try {
+ Session session = getSessionWithTimeout();
+ try {
+ Node contentNode = getOrCreateContentNode(normalizedPath, session);
+ Value value = session.getValueFactory().createValue(documentContent);
+ contentNode.setProperty("jcr:data", value);
+
+ session.save();
+ return true;
+ } finally {
+ closeSession(session);
+ }
+ } catch (RepositoryException ex) {
+ log.error("Failed to write document to file '{}'", path, ex);
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean saveDocumentStream(String path, InputStream documentStream, List moduleList) {
+ log.debug("Save document from stream: '{}'", path);
+
+ String normalizedPath = getNormalizedPath(path);
+ try {
+ Session session = getSessionWithTimeout();
+ try {
+ Node contentNode = getOrCreateContentNode(normalizedPath, session);
+ Binary value = session.getValueFactory().createBinary(documentStream);
+ contentNode.setProperty("jcr:data", value);
+
+ session.save();
+ return true;
+ } finally {
+ closeSession(session);
+ }
+ } catch (RepositoryException ex) {
+ log.error("Failed to write document from stream to file '{}'", path, ex);
+ }
+
+ return false;
+ }
+
+
+ @Override
+ public String readDocument(String path, Charset charset) {
+ log.debug("Read document: '{}'", path);
+
+ String normalizedPath = getNormalizedPath(path);
+ try {
+ Session session = getSessionWithTimeout();
+ try {
+ Node fileNode = JcrUtils.getNodeIfExists(normalizedPath, session);
+ if (fileNode == null) {
+ log.error("Document file '{}' isn't exist", path);
+ return null;
+ }
+
+ Node contentNode = fileNode.getNode(JcrConstants.JCR_CONTENT);
+ Property property = contentNode.getProperty("jcr:data");
+ try (InputStream in = property.getBinary().getStream()) {
+ return IOUtils.toString(in, charset);
+ }
+ } finally {
+ closeSession(session);
+ }
+ } catch (IOException ex) {
+ } catch (RepositoryException ex) {
+ log.error("Failed to read document from file '{}'", path, ex);
+ }
+
+ return null;
+ }
+
+ @Override
+ public InputStream readDocumentAsStream(String path) {
+ log.debug("Read document as stream: '{}'", path);
+
+ String normalizedPath = getNormalizedPath(path);
+ try {
+ Session session = getSessionWithTimeout();
+ try {
+ Node fileNode = JcrUtils.getNodeIfExists(normalizedPath, session);
+ if (fileNode == null) {
+ log.error("Document file '{}' isn't exist", path);
+ return null;
+ }
+
+ Node contentNode = fileNode.getNode(JcrConstants.JCR_CONTENT);
+ Property property = contentNode.getProperty("jcr:data");
+ try (InputStream in = property.getBinary().getStream()) {
+ // Note: We can't return real input stream because we need to make sure that we close session
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ IOUtils.copy(in, bos);
+
+ return new ByteArrayInputStream(bos.toByteArray());
+ }
+ } finally {
+ closeSession(session);
+ }
+ } catch (IOException ex) {
+ } catch (RepositoryException ex) {
+ log.error("Failed to read document as stream from file '{}'", path, ex);
+ }
+
+ return null;
+ }
+
+ @Override
+ public boolean renameDocument(String currentPath, String destinationPath) {
+ log.debug("Rename document: '{}' -> '{}'", currentPath, destinationPath);
+
+ String normalizedCurrentPath = getNormalizedPath(currentPath);
+ String normalizedDestinationPath = getNormalizedPath(destinationPath);
+
+ try {
+ Session session = getSessionWithTimeout();
+ try {
+ removeDocument(normalizedDestinationPath, session);
+
+ createPath(normalizedDestinationPath, session);
+ session.move(normalizedCurrentPath, normalizedDestinationPath);
+
+ session.save();
+ return true;
+ } finally {
+ closeSession(session);
+ }
+ } catch (RepositoryException ex) {
+ log.error("Failed to rename to destination file '{}'", destinationPath, ex);
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean removeDocument(String path) {
+ log.debug("Remove document: '{}'", path);
+
+ try {
+ Session session = getSessionWithTimeout();
+ try {
+ removeDocument(path, session);
+
+ session.save();
+ return true;
+ } finally {
+ closeSession(session);
+ }
+ } catch (RepositoryException ex) {
+ log.error("Failed to remove document file '{}'", path, ex);
+ }
+
+ return false;
+ }
+
+ private void removeDocument(String path, Session session)
+ throws RepositoryException, VersionException, LockException, ConstraintViolationException, AccessDeniedException {
+ Node fileNode = JcrUtils.getNodeIfExists(getNormalizedPath(path), session);
+ if (fileNode != null) {
+ fileNode.remove();
+ }
+ }
+
+ private void decryptPassword(JcaDocumentStoreConfiguration jcaDocumentStoreConfiguration) {
+ try {
+ String encryptedPassword = jcaDocumentStoreConfiguration.getPassword();
+ if (StringUtils.isNotBlank(encryptedPassword)) {
+ jcaDocumentStoreConfiguration.setDecryptedPassword(stringEncrypter.decrypt(encryptedPassword));
+ log.trace("Decrypted JCA password successfully.");
+ }
+ } catch (StringEncrypter.EncryptionException ex) {
+ jcaDocumentStoreConfiguration.setDecryptedPassword(jcaDocumentStoreConfiguration.getPassword());
+ log.error("Error during JCA password decryption", ex);
+ }
+ }
+
+ private Session getSession() throws RepositoryException {
+ return repository.login(credentials, workspaceName);
+ }
+
+ public Session getSessionWithTimeout() throws RepositoryException {
+ try {
+ CallableSession cs = new CallableSession(repository, credentials, workspaceName);
+ FutureTask future = new FutureTask(cs);
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ executor.execute(future);
+ return future.get(connectionTimeout * 1000, TimeUnit.MILLISECONDS);
+ } catch (Exception ex) {
+ throw new RepositoryException("Failed to get session", ex);
+ }
+ }
+
+ private void closeSession(Session session) {
+ if (session != null && session.isLive()) {
+ session.logout();
+ }
+ }
+
+ private String getNormalizedPath(String path) {
+ return path.replace("\\", "/").replace(" ", "");
+ }
+
+ private Node getOrCreateContentNode(String path, Session session) throws RepositoryException {
+ Node fileNode = JcrUtils.getNodeIfExists(getNormalizedPath(path), session);
+ Node contentNode = null;
+ if (fileNode == null) {
+ fileNode = JcrUtils.getOrCreateByPath(path, NodeType.NT_FOLDER, NodeType.NT_FILE, session, false);
+ contentNode = fileNode.addNode(JcrConstants.JCR_CONTENT, NodeType.NT_RESOURCE);
+ } else {
+ contentNode = fileNode.getNode(JcrConstants.JCR_CONTENT);
+ }
+
+ return contentNode;
+ }
+
+ private void createPath(String path, Session session) throws RepositoryException {
+ File filePath = new File(path);
+ String folderPath = filePath.getParentFile().getPath();
+
+ String normalizedFolderPath = getNormalizedPath(folderPath);
+ JcrUtils.getOrCreateByPath(normalizedFolderPath, NodeType.NT_FOLDER, session);
+ }
+
+ class CallableSession implements Callable {
+
+ private URLRemoteRepository repository;
+ private SimpleCredentials credentials;
+ private String workspaceName;
+
+ public CallableSession(URLRemoteRepository repository, SimpleCredentials credentials, String workspaceName) {
+ this.repository = repository;
+ this.credentials = credentials;
+ this.workspaceName = workspaceName;
+ }
+
+ @Override
+ public Session call() throws Exception {
+ return repository.login(credentials, workspaceName);
+ }
+ }
+
+ public boolean isConnected() {
+ log.debug("Check if server available");
+
+ Node fileNode = null;
+ Session session;
+ try {
+ session = getSessionWithTimeout();
+ try {
+ fileNode = JcrUtils.getNodeIfExists(getNormalizedPath("/"), session);
+ } finally {
+ closeSession(session);
+ }
+ } catch (RepositoryException ex) {
+ log.error("Failed to check if server available", ex);
+ }
+
+ return fileNode != null;
+ }
+
+}
diff --git a/core-document-store/src/main/java/org/gluu/service/document/store/provider/LocalDocumentStoreProvider.java b/core-document-store/src/main/java/org/gluu/service/document/store/provider/LocalDocumentStoreProvider.java
new file mode 100644
index 000000000..0ee4e4b40
--- /dev/null
+++ b/core-document-store/src/main/java/org/gluu/service/document/store/provider/LocalDocumentStoreProvider.java
@@ -0,0 +1,224 @@
+package org.gluu.service.document.store.provider;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.util.List;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.gluu.service.document.store.conf.DocumentStoreConfiguration;
+import org.gluu.service.document.store.conf.DocumentStoreType;
+import org.gluu.service.document.store.conf.LocalDocumentStoreConfiguration;
+import org.gluu.util.StringHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Yuriy Movchan on 04/10/2020
+ */
+@ApplicationScoped
+public class LocalDocumentStoreProvider extends DocumentStoreProvider {
+
+ @Inject
+ private Logger log;
+
+ @Inject
+ private DocumentStoreConfiguration documentStoreConfiguration;
+
+ private LocalDocumentStoreConfiguration localDocumentStoreConfiguration;
+
+ private String baseLocation;
+
+ public LocalDocumentStoreProvider() {
+ }
+
+ @PostConstruct
+ public void init() {
+ this.localDocumentStoreConfiguration = documentStoreConfiguration.getLocalConfiguration();
+ }
+
+ @Override
+ public void create() {
+ log.debug("Starting LocalDocumentStoreProvider ...");
+
+ if (StringHelper.isEmpty(localDocumentStoreConfiguration.getBaseLocation())) {
+ String osName = System.getProperty("os.name");
+ if (StringHelper.isNotEmpty(osName) && osName.toLowerCase().startsWith("windows")) {
+ baseLocation = "";
+ return;
+ }
+ throw new IllegalArgumentException("Base location should not be empty");
+ }
+
+ baseLocation = new File(localDocumentStoreConfiguration.getBaseLocation()).getAbsolutePath();
+ }
+
+ public void configure(DocumentStoreConfiguration documentStoreConfiguration) {
+ this.log = LoggerFactory.getLogger(DocumentStoreConfiguration.class);
+ this.documentStoreConfiguration = documentStoreConfiguration;
+ }
+
+ @PreDestroy
+ @Override
+ public void destroy() {
+ log.debug("Destroying LocalDocumentStoreProvider");
+
+ log.debug("Destroyed LocalDocumentStoreProvider");
+ }
+
+ @Override
+ public DocumentStoreType getProviderType() {
+ return DocumentStoreType.LOCAL;
+ }
+
+ @Override
+ public boolean hasDocument(String path) {
+ log.debug("Has document: '{}'", path);
+
+ if (StringHelper.isEmpty(path)) {
+ throw new IllegalArgumentException("Specified path should not be empty!");
+ }
+
+ File file = buildFilePath(path);
+
+ return file.exists();
+ }
+
+ @Override
+ public boolean saveDocument(String path, String documentContent, Charset charset, List moduleList) {
+ log.debug("Save document: '{}'", path);
+
+ File file = buildFilePath(path);
+ if (!createParentPath(file)) {
+ return false;
+ }
+
+ try (FileOutputStream os = FileUtils.openOutputStream(file)) {
+ IOUtils.write(documentContent, os, charset);
+ os.flush();
+
+ return true;
+ } catch (IOException ex) {
+ log.error("Failed to write document to file '{}'", file.getAbsolutePath(), ex);
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean saveDocumentStream(String path, InputStream documentStream, List moduleList) {
+ log.debug("Save document from stream: '{}'", path);
+
+ File file = buildFilePath(path);
+ if (!createParentPath(file)) {
+ return false;
+ }
+
+ try (FileOutputStream os = FileUtils.openOutputStream(file)) {
+ IOUtils.copy(documentStream, os);
+ os.flush();
+
+ return true;
+ } catch (IOException ex) {
+ log.error("Failed to write document from stream to file '{}'", file.getAbsolutePath(), ex);
+ }
+
+ return false;
+ }
+
+ @Override
+ public String readDocument(String path, Charset charset) {
+ log.debug("Read document: '{}'", path);
+
+ File file = buildFilePath(path);
+ if (!createParentPath(file)) {
+ return null;
+ }
+
+ try {
+ return FileUtils.readFileToString(file, charset);
+ } catch (IOException ex) {
+ log.error("Failed to read document from file '{}'", file.getAbsolutePath(), ex);
+ }
+
+ return null;
+ }
+
+ @Override
+ public InputStream readDocumentAsStream(String path) {
+ log.debug("Read document as stream: '{}'", path);
+
+ File file = buildFilePath(path);
+
+ try {
+ return new BufferedInputStream(FileUtils.openInputStream(file));
+ } catch (IOException ex) {
+ log.error("Failed to read document as stream from file '{}'", file.getAbsolutePath(), ex);
+ }
+
+ return null;
+ }
+
+ @Override
+ public boolean renameDocument(String currentPath, String destinationPath) {
+ log.debug("Rename document: '{}' -> '{}'", currentPath, destinationPath);
+
+ File currentFile = buildFilePath(currentPath);
+ File destinationFile = buildFilePath(destinationPath);
+
+ if (!removeDocument(destinationPath)) {
+ log.error("Failed to remove destination file '{}'", destinationFile.getAbsolutePath());
+ }
+
+ try {
+ currentFile.renameTo(destinationFile);
+ return true;
+ } catch (Exception ex) {
+ log.error("Failed to rename to destination file '{}'", destinationFile.getAbsolutePath(), ex);
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean removeDocument(String path) {
+ log.debug("Remove document: '{}'", path);
+
+ if (!hasDocument(path)) {
+ return true;
+ }
+
+ File file = buildFilePath(path);
+ if (!createParentPath(file)) {
+ return false;
+ }
+
+ return FileUtils.deleteQuietly(file);
+ }
+
+ private boolean createParentPath(File file) {
+ try {
+ FileUtils.forceMkdirParent(file);
+ return true;
+ } catch (IOException ex) {
+ log.error("Failed to create path to file '{}'", file.getAbsolutePath(), ex);
+ }
+
+ return false;
+ }
+
+ private File buildFilePath(String path) {
+ String filePath = baseLocation + File.separator + path;
+ return new File(filePath);
+ }
+
+}
diff --git a/core-document-store/src/main/java/org/gluu/service/document/store/provider/WebDavDocumentStoreProvider.java b/core-document-store/src/main/java/org/gluu/service/document/store/provider/WebDavDocumentStoreProvider.java
new file mode 100644
index 000000000..c09c079af
--- /dev/null
+++ b/core-document-store/src/main/java/org/gluu/service/document/store/provider/WebDavDocumentStoreProvider.java
@@ -0,0 +1,302 @@
+package org.gluu.service.document.store.provider;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.util.List;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.jcr.RepositoryException;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.config.AuthSchemes;
+import org.apache.http.client.config.CookieSpecs;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.HttpPut;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.conn.SchemePortResolver;
+import org.apache.http.conn.UnsupportedSchemeException;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.InputStreamEntity;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.impl.conn.DefaultSchemePortResolver;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.http.protocol.BasicHttpContext;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.util.Args;
+import org.apache.jackrabbit.webdav.client.methods.HttpMkcol;
+import org.gluu.service.document.store.conf.DocumentStoreConfiguration;
+import org.gluu.service.document.store.conf.DocumentStoreType;
+import org.gluu.service.document.store.conf.WebDavDocumentStoreConfiguration;
+import org.gluu.util.security.StringEncrypter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.github.sardine.Sardine;
+import com.github.sardine.SardineFactory;
+
+/**
+ * @author Yuriy Movchan on 04/10/2020
+ */
+@ApplicationScoped
+public class WebDavDocumentStoreProvider extends DocumentStoreProvider {
+
+ @Inject
+ private Logger log;
+
+ @Inject
+ private DocumentStoreConfiguration documentStoreConfiguration;
+
+ @Inject
+ private StringEncrypter stringEncrypter;
+
+ /**
+ * Local context with authentication cache. Make sure the same context is used to execute
+ * logically related requests.
+ */
+ protected HttpClientContext context = HttpClientContext.create();
+
+ private WebDavDocumentStoreConfiguration webDavDocumentStoreConfiguration;
+
+ private Sardine client;
+ private HttpClient httpClient;
+ private String baseServerUrl;
+ private int connectionTimeout;
+
+ public WebDavDocumentStoreProvider() {
+ }
+
+ @PostConstruct
+ public void init() {
+ this.webDavDocumentStoreConfiguration = documentStoreConfiguration.getWebDavConfiguration();
+ }
+
+ public void create() {
+ try {
+ log.debug("Starting WebDavDocumentStoreProvider ...");
+ decryptPassword(webDavDocumentStoreConfiguration);
+
+ String password = StringUtils.isBlank(webDavDocumentStoreConfiguration.getDecryptedPassword()) ? "" : webDavDocumentStoreConfiguration.getDecryptedPassword();
+
+ UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(
+ webDavDocumentStoreConfiguration.getUserId(), password);
+
+ this.connectionTimeout = webDavDocumentStoreConfiguration.getConnectionTimeout();
+
+ this.httpClient = createHttpClient(credentials, connectionTimeout * 1000);
+
+ this.baseServerUrl = webDavDocumentStoreConfiguration.getServerUrl() + "/" +
+ webDavDocumentStoreConfiguration.getWorkspaceName();
+/*
+ * Sardine
+*/
+
+ this.client = SardineFactory.begin(webDavDocumentStoreConfiguration.getUserId(), password);
+ } catch (Exception ex) {
+ throw new IllegalStateException("Error starting JcaDocumentStoreProvider", ex);
+ }
+ }
+
+ public void configure(DocumentStoreConfiguration documentStoreConfiguration, StringEncrypter stringEncrypter) {
+ this.log = LoggerFactory.getLogger(WebDavDocumentStoreProvider.class);
+ this.documentStoreConfiguration = documentStoreConfiguration;
+ this.stringEncrypter = stringEncrypter;
+ }
+
+ @PreDestroy
+ public void destroy() {
+ log.debug("Destroying WebDavDocumentStoreProvider");
+
+ this.client = null;
+
+ log.debug("Destroyed WebDavDocumentStoreProvider");
+ }
+
+ @Override
+ public DocumentStoreType getProviderType() {
+ return DocumentStoreType.WEB_DAV;
+ }
+
+ @Override
+ public boolean hasDocument(String path) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean saveDocument(String path, String documentContent, Charset charset, List moduleList) {
+ if (true) {
+ log.debug("Save document: '{}'", path);
+
+ String normalizedPath = getNormalizedPath(path);
+ try {
+ HttpPut method = new HttpPut(baseServerUrl + "/" + normalizedPath);
+ HttpEntity entity = new StringEntity(documentContent, charset);
+ method.setEntity(entity);
+
+ HttpContext requestLocalContext = new BasicHttpContext(context);
+ HttpResponse response = httpClient.execute(method, requestLocalContext);
+
+ int statusCode = response.getStatusLine().getStatusCode();
+ return statusCode == HttpStatus.SC_CREATED || statusCode == HttpStatus.SC_NO_CONTENT;
+ } catch (IOException ex) {
+ log.error("Failed to write document to file '{}'", path, ex);
+ }
+
+ return false;
+ } else {
+
+ log.debug("Save document: '{}'", path);
+
+ String normalizedPath = getNormalizedPath(path);
+ try {
+ String url = baseServerUrl + "/" + normalizedPath;
+ client.put(url, IOUtils.toInputStream(documentContent));
+
+ return true;
+ } catch (IOException ex) {
+ log.error("Failed to write document to file '{}'", path, ex);
+ }
+
+ return false;
+ }
+ }
+
+ @Override
+ public boolean saveDocumentStream(String path, InputStream documentStream, List moduleList) {
+ log.debug("Save document from stream: '{}'", path);
+ String normalizedPath = getNormalizedPath(path);
+ try {
+ HttpPut method = new HttpPut(baseServerUrl + "/" + normalizedPath);
+ HttpEntity entity = new InputStreamEntity(documentStream);
+ method.setEntity(entity);
+
+ HttpContext requestLocalContext = new BasicHttpContext(context);
+ HttpResponse response = httpClient.execute(method, requestLocalContext);
+
+ return response.getStatusLine().getStatusCode() == HttpStatus.SC_CREATED;
+ } catch (IOException ex) {
+ log.error("Failed to write document from stream to file '{}'", path, ex);
+ }
+
+ return false;
+ }
+
+ @Override
+ public String readDocument(String path, Charset charset) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public InputStream readDocumentAsStream(String path) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public boolean renameDocument(String currentPath, String destinationPath) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean removeDocument(String path) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ private void createPath(String path) throws RepositoryException {
+/*
+ HttpMkcol mkcol = new HttpMkcol("");
+ this.client.executeMethod(mkcol, )
+
+ File filePath = new File(path);
+ String folderPath = filePath.getParentFile().getPath();
+
+ String normalizedFolderPath = getNormalizedPath(folderPath);
+ JcrUtils.getOrCreateByPath(normalizedFolderPath, NodeType.NT_FOLDER, session);
+*/
+ }
+ private HttpClient createHttpClient(UsernamePasswordCredentials credentials, int timeoutInMillis) {
+ CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
+// credentialsProvider.setCredentials(AuthScope.ANY, credentials);
+ credentialsProvider.setCredentials(
+ new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM, AuthSchemes.BASIC),
+ credentials);
+
+ SchemePortResolver portResolver = new DefaultSchemePortResolver() {
+ @Override
+ public int resolve(final HttpHost host) throws UnsupportedSchemeException {
+ Args.notNull(host, "HTTP host");
+ final int port = host.getPort();
+ if (port > 0) {
+ return port;
+ }
+ final String name = host.getSchemeName();
+ if (name.equalsIgnoreCase("http")) {
+ return 8080;
+ } else if (name.equalsIgnoreCase("https")) {
+ return 8443;
+ }
+
+ return super.resolve(host);
+ }
+ };
+
+ PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
+ CloseableHttpClient httpClient = HttpClients.custom()
+ .setDefaultRequestConfig(RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD)
+ .setSocketTimeout(timeoutInMillis).setExpectContinueEnabled(false).build())
+ .setDefaultCredentialsProvider(credentialsProvider)
+ .setConnectionManager(cm)
+/* .setRetryHandler(new DefaultHttpRequestRetryHandler(0, false))*/
+/* .setSchemePortResolver(portResolver)*/
+
+ .build();
+ cm.setMaxTotal(50); // Increase max total connection to 50
+ cm.setDefaultMaxPerRoute(10); // Increase default max connection per route to 10
+
+ context.setCredentialsProvider(credentialsProvider);
+
+ return httpClient;
+ }
+
+ private void decryptPassword(WebDavDocumentStoreConfiguration webDocumentStoreConfiguration) {
+ try {
+ String encryptedPassword = webDocumentStoreConfiguration.getPassword();
+ if (StringUtils.isNotBlank(encryptedPassword)) {
+ webDocumentStoreConfiguration.setDecryptedPassword(stringEncrypter.decrypt(encryptedPassword));
+ log.trace("Decrypted WebDAV password successfully.");
+ }
+ } catch (StringEncrypter.EncryptionException ex) {
+ log.error("Error during WebDAV password decryption", ex);
+ }
+ }
+
+ private String getNormalizedPath(String path) {
+ String resultPath = path.replace("\\", "/").replace(" ", "");
+ if (resultPath.startsWith("/")) {
+ resultPath = resultPath.substring(1);
+ }
+
+ return resultPath;
+ }
+
+}
diff --git a/core-document-store/src/main/java/org/gluu/service/document/store/service/BaseDocumentStoreService.java b/core-document-store/src/main/java/org/gluu/service/document/store/service/BaseDocumentStoreService.java
new file mode 100644
index 000000000..def1d0b59
--- /dev/null
+++ b/core-document-store/src/main/java/org/gluu/service/document/store/service/BaseDocumentStoreService.java
@@ -0,0 +1,86 @@
+/*
+ * oxCore is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
+ *
+ * Copyright (c) 2014, Gluu
+ */
+package org.gluu.service.document.store.service;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.gluu.service.document.store.conf.DocumentStoreType;
+import org.gluu.service.document.store.provider.DocumentStore;
+import org.gluu.service.document.store.provider.DocumentStoreProvider;
+import org.slf4j.Logger;
+
+/**
+ * @author Yuriy Movchan on 04/10/2020
+ */
+@SuppressWarnings("rawtypes")
+public abstract class BaseDocumentStoreService implements DocumentStore {
+
+ @Inject
+ private Logger log;
+
+ public boolean hasDocument(String path) {
+ DocumentStoreProvider documentStoreProvider = getDocumentStoreProvider();
+
+ return documentStoreProvider.hasDocument(path);
+ }
+
+ @Override
+ public boolean saveDocument(String path, String documentContent, Charset charset, List moduleList) {
+ DocumentStoreProvider documentStoreProvider = getDocumentStoreProvider();
+
+ return documentStoreProvider.saveDocument(path, documentContent, charset, moduleList);
+ }
+
+ @Override
+ public boolean saveDocumentStream(String path, InputStream documentStream, List moduleList) {
+ DocumentStoreProvider documentStoreProvider = getDocumentStoreProvider();
+
+ return documentStoreProvider.saveDocumentStream(path, documentStream, moduleList);
+ }
+
+ @Override
+ public String readDocument(String path, Charset charset) {
+ DocumentStoreProvider documentStoreProvider = getDocumentStoreProvider();
+
+ return documentStoreProvider.readDocument(path, charset);
+ }
+
+ @Override
+ public InputStream readDocumentAsStream(String path) {
+ DocumentStoreProvider documentStoreProvider = getDocumentStoreProvider();
+
+ return documentStoreProvider.readDocumentAsStream(path);
+ }
+
+ @Override
+ public boolean renameDocument(String currentPath, String destinationPath) {
+ DocumentStoreProvider documentStoreProvider = getDocumentStoreProvider();
+
+ return documentStoreProvider.renameDocument(currentPath, destinationPath);
+ }
+
+ @Override
+ public boolean removeDocument(String path) {
+ DocumentStoreProvider documentStoreProvider = getDocumentStoreProvider();
+
+ return documentStoreProvider.removeDocument(path);
+ }
+
+ @Override
+ public DocumentStoreType getProviderType() {
+ DocumentStoreProvider documentStoreProvider = getDocumentStoreProvider();
+
+ return documentStoreProvider.getProviderType();
+ }
+
+ protected abstract DocumentStoreProvider getDocumentStoreProvider();
+
+}
diff --git a/core-document-store/src/main/java/org/gluu/service/document/store/service/DBDocumentService.java b/core-document-store/src/main/java/org/gluu/service/document/store/service/DBDocumentService.java
new file mode 100644
index 000000000..b2713e422
--- /dev/null
+++ b/core-document-store/src/main/java/org/gluu/service/document/store/service/DBDocumentService.java
@@ -0,0 +1,219 @@
+/*
+ * oxTrust is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
+ *
+ * Copyright (c) 2014, Gluu
+ */
+
+package org.gluu.service.document.store.service;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.Instance;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.gluu.persist.PersistenceEntryManager;
+import org.gluu.search.filter.Filter;
+import org.gluu.util.StringHelper;
+import org.slf4j.Logger;
+
+/**
+ * Provides operations with OxDocument
+ *
+ * @author Shekhar L. Date : 04 April 2022
+ */
+@ApplicationScoped
+@Named("DBDocumentService")
+public class DBDocumentService implements Serializable {
+
+ private static final long serialVersionUID = 65734145678106186L;
+
+ @Inject
+ private Logger logger;
+
+ @Inject
+ private Instance persistenceEntryManagerInstance;
+
+ private PersistenceEntryManager persistenceEntryManager;
+
+ public DBDocumentService() {}
+
+ public DBDocumentService(PersistenceEntryManager persistenceEntryManager) {
+ this.persistenceEntryManager = persistenceEntryManager;
+ }
+
+ public static final String inum = "inum";
+ public static final String displayName = "displayName";
+ public static final String description = "description";
+
+ @PostConstruct
+ public void init() {
+ if (persistenceEntryManagerInstance.isResolvable()) {
+ this.persistenceEntryManager = persistenceEntryManagerInstance.get();
+ } else {
+ this.persistenceEntryManager = null;
+ }
+ }
+
+ /**
+ * Add new OxDocument entry
+ *
+ * @param OxDocument
+ * OxDocument
+ */
+ public void addOxDocument(OxDocument oxDocument) throws Exception {
+ oxDocument.setCreationDate(new Date());
+ persistenceEntryManager.persist(oxDocument);
+ }
+
+ /**
+ * Remove OxDocument entry
+ *
+ * @param OxDocument
+ * OxDocument
+ */
+ public void removeOxDocument(OxDocument oxDocument) throws Exception {
+
+ persistenceEntryManager.remove(oxDocument);
+ }
+
+ /**
+ * Get OxDocument by inum
+ *
+ * @param inum
+ * OxDocument Inum
+ * @return OxDocument
+ */
+ public OxDocument getOxDocumentByInum(String inum) throws Exception {
+ OxDocument result = null;
+ try {
+ result = persistenceEntryManager.find(OxDocument.class, getDnForOxDocument(inum));
+ } catch (Exception e) {
+ logger.error("Not able to find the oxDocument. Here is the exception message ", e);
+ }
+ return result;
+ }
+
+ /**
+ * Build DN string for OxDocument
+ *
+ * @param inum
+ * OxDocument Inum
+ * @return DN string for specified scope or DN for OxDocument branch if inum is null
+ * @throws Exception
+ */
+ public String getDnForOxDocument(String inum) throws Exception {
+ if (StringHelper.isEmpty(inum)) {
+ return String.format("ou=document,%s", "o=gluu");
+ }
+ return String.format("inum=%s,ou=document,%s", inum, "o=gluu");
+ }
+
+ /**
+ * Update OxDocument entry
+ *
+ * @param OxDocument
+ * OxDocument
+ */
+ public void updateOxDocument(OxDocument oxDocument) throws Exception {
+ persistenceEntryManager.merge(oxDocument);
+ }
+
+ /**
+ * Generate new inum for OxDocument
+ *
+ * @return New inum for OxDocument
+ */
+ public String generateInumForNewOxDocument() throws Exception {
+ OxDocument oxDocument = new OxDocument();
+ String newInum = null;
+ String newDn = null;
+ newInum = generateInumForNewOxDocumentImpl();
+ newDn = getDnForOxDocument(newInum);
+ oxDocument.setDn(newDn);
+ return newInum;
+ }
+
+ /**
+ * Search scopes by pattern
+ *
+ * @param pattern
+ * Pattern
+ * @param sizeLimit
+ * Maximum count of results
+ * @return List of OxDocument
+ * @throws Exception
+ */
+ public List searchOxDocuments(String pattern, int sizeLimit) {
+ Filter searchFilter = null;
+ if (StringHelper.isNotEmpty(pattern)) {
+ String[] targetArray = new String[] { pattern };
+ Filter displayNameFilter = Filter.createSubstringFilter(displayName, null, targetArray,
+ null);
+ Filter descriptionFilter = Filter.createSubstringFilter(description, null, targetArray,
+ null);
+ searchFilter = Filter.createORFilter(displayNameFilter, descriptionFilter);
+ }
+ List result = new ArrayList<>();
+ try {
+ result = persistenceEntryManager.findEntries(getDnForOxDocument(null), OxDocument.class, searchFilter, sizeLimit);
+ return result;
+ } catch (Exception e) {
+ logger.error("Failed to find OxDocument : ", e);
+ }
+ return result;
+ }
+
+ /**
+ * Generate new inum for oxDocument
+ *
+ * @return New inum for oxDocument
+ * @throws Exception
+ */
+ private String generateInumForNewOxDocumentImpl() throws Exception {
+ return UUID.randomUUID().toString();
+ }
+
+ public List getAllOxDocumentsList(int size) {
+ try {
+ List oxDocuments = persistenceEntryManager.findEntries(getDnForOxDocument(null), OxDocument.class, null, size);
+ return oxDocuments;
+ } catch (Exception e) {
+ logger.error("Failed to find OxDocument: ", e);
+ return new ArrayList<>();
+ }
+ }
+
+ /**
+ * returns oxDocuments by Dn
+ *
+ * @return oxDocuments
+ */
+
+ public OxDocument getOxDocumentByDn(String Dn) throws Exception {
+ return persistenceEntryManager.find(OxDocument.class, Dn);
+ }
+
+ /**
+ * Get oxDocuments by DisplayName
+ *
+ * @param DisplayName
+ * @return oxDocuments
+ */
+ public OxDocument getOxDocumentByDisplayName(String DisplayName) throws Exception {
+ OxDocument oxDocument = new OxDocument();
+ oxDocument.setDisplayName(DisplayName);
+ oxDocument.setDn(getDnForOxDocument(null));;
+ List oxDocuments = persistenceEntryManager.findEntries(oxDocument);
+ if ((oxDocuments != null) && (oxDocuments.size() > 0)) {
+ return oxDocuments.get(0);
+ }
+ return null;
+ }
+}
diff --git a/core-document-store/src/main/java/org/gluu/service/document/store/service/DocumentStoreService.java b/core-document-store/src/main/java/org/gluu/service/document/store/service/DocumentStoreService.java
new file mode 100644
index 000000000..fc5574f0c
--- /dev/null
+++ b/core-document-store/src/main/java/org/gluu/service/document/store/service/DocumentStoreService.java
@@ -0,0 +1,27 @@
+/*
+ * oxCore is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
+ *
+ * Copyright (c) 2014, Gluu
+ */
+package org.gluu.service.document.store.service;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+
+import org.gluu.service.document.store.provider.DocumentStoreProvider;
+
+/**
+ * @author Yuriy Movchan on 04/10/2020
+ */
+@ApplicationScoped
+public class DocumentStoreService extends BaseDocumentStoreService {
+
+ @Inject
+ private DocumentStoreProvider documentStoreProvider;
+
+ @Override
+ protected DocumentStoreProvider getDocumentStoreProvider() {
+ return documentStoreProvider;
+ }
+
+}
diff --git a/core-document-store/src/main/java/org/gluu/service/document/store/service/LocalDocumentStoreService.java b/core-document-store/src/main/java/org/gluu/service/document/store/service/LocalDocumentStoreService.java
new file mode 100644
index 000000000..2ed054149
--- /dev/null
+++ b/core-document-store/src/main/java/org/gluu/service/document/store/service/LocalDocumentStoreService.java
@@ -0,0 +1,30 @@
+/*
+ * oxCore is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
+ *
+ * Copyright (c) 2014, Gluu
+ */
+package org.gluu.service.document.store.service;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+
+import org.gluu.service.document.store.LocalDocumentStore;
+import org.gluu.service.document.store.provider.DocumentStoreProvider;
+
+/**
+ * @author Yuriy Movchan on 04/10/2020
+ */
+@ApplicationScoped
+public class LocalDocumentStoreService extends BaseDocumentStoreService {
+
+ @Inject
+ @LocalDocumentStore
+ private DocumentStoreProvider documentStoreProvider;
+
+ @Override
+ protected DocumentStoreProvider getDocumentStoreProvider() {
+ return documentStoreProvider;
+ }
+
+
+}
diff --git a/core-document-store/src/main/java/org/gluu/service/document/store/service/OxDocument.java b/core-document-store/src/main/java/org/gluu/service/document/store/service/OxDocument.java
new file mode 100644
index 000000000..f78c96629
--- /dev/null
+++ b/core-document-store/src/main/java/org/gluu/service/document/store/service/OxDocument.java
@@ -0,0 +1,154 @@
+/*
+ * oxTrust is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
+ *
+ * Copyright (c) 2014, Gluu
+ */
+
+package org.gluu.service.document.store.service;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+import org.gluu.persist.model.base.Entry;
+import org.gluu.persist.annotation.AttributeName;
+import org.gluu.persist.annotation.DataEntry;
+import org.gluu.persist.annotation.ObjectClass;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+
+/**
+ * Group
+ *
+ * @author Yuriy Movchan Date: 11.02.2010
+ */
+@DataEntry(sortBy = { "displayName" })
+@ObjectClass(value = "oxDocument")
+@JsonInclude(Include.NON_NULL)
+public class OxDocument extends Entry implements Serializable {
+
+ private static final long serialVersionUID = -2812480357430436503L;
+
+ private transient boolean selected;
+//inum $ displayName $ description $ document $ oxModuleProperty $ oxLevel $ oxRevision $ oxEnabled $ oxAlias )
+ @AttributeName(ignoreDuringUpdate = true)
+ private String inum;
+
+
+ @AttributeName
+ private String displayName;
+
+ @AttributeName
+ private String description;
+
+ @AttributeName
+ private String document;
+
+ @AttributeName
+ private Date creationDate;
+
+ @AttributeName
+ private List oxModuleProperty;
+
+ @AttributeName
+ private String oxLevel;
+
+ @AttributeName
+ private String oxRevision;
+
+ @AttributeName
+ private Boolean oxEnabled;
+
+ @AttributeName
+ private String oxAlias;
+
+ public String getInum() {
+ return inum;
+ }
+
+ public void setInum(String inum) {
+ this.inum = inum;
+ }
+
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public void setDisplayName(String displayName) {
+ this.displayName = displayName;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public boolean isSelected() {
+ return selected;
+ }
+
+ public void setSelected(boolean selected) {
+ this.selected = selected;
+ }
+
+ public String getDocument() {
+ return document;
+ }
+
+ public void setDocument(String document) {
+ this.document = document;
+ }
+
+ public List getOxModuleProperty() {
+ return oxModuleProperty;
+ }
+
+ public void setOxModuleProperty(List oxModuleProperty) {
+ this.oxModuleProperty = oxModuleProperty;
+ }
+
+ public String getOxLevel() {
+ return oxLevel;
+ }
+
+ public void setOxLevel(String oxLevel) {
+ this.oxLevel = oxLevel;
+ }
+
+ public String getOxRevision() {
+ return oxRevision;
+ }
+
+ public void setOxRevision(String oxRevision) {
+ this.oxRevision = oxRevision;
+ }
+
+ public Boolean getOxEnabled() {
+ return oxEnabled;
+ }
+
+ public void setOxEnabled(Boolean oxEnabled) {
+ this.oxEnabled = oxEnabled;
+ }
+
+ public String getOxAlias() {
+ return oxAlias;
+ }
+
+ public void setOxAlias(String oxAlias) {
+ this.oxAlias = oxAlias;
+ }
+
+ public Date getCreationDate() {
+ return creationDate;
+ }
+
+ public void setCreationDate(Date creationDate) {
+ this.creationDate = creationDate;
+ }
+
+}
diff --git a/persistence-hybrid/src/main/resources/META-INF/beans.xml b/core-document-store/src/main/resources/META-INF/beans.xml
similarity index 100%
rename from persistence-hybrid/src/main/resources/META-INF/beans.xml
rename to core-document-store/src/main/resources/META-INF/beans.xml
diff --git a/core-document-store/src/test/java/org/gluu/service/document/store/manual/JcaDocumentStoreManualTest.java b/core-document-store/src/test/java/org/gluu/service/document/store/manual/JcaDocumentStoreManualTest.java
new file mode 100644
index 000000000..61d1a84a4
--- /dev/null
+++ b/core-document-store/src/test/java/org/gluu/service/document/store/manual/JcaDocumentStoreManualTest.java
@@ -0,0 +1,97 @@
+package org.gluu.service.document.store.manual;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.gluu.service.document.store.StandaloneDocumentStoreProviderFactory;
+import org.gluu.service.document.store.conf.DocumentStoreConfiguration;
+import org.gluu.service.document.store.conf.DocumentStoreType;
+import org.gluu.service.document.store.conf.JcaDocumentStoreConfiguration;
+import org.gluu.service.document.store.conf.LocalDocumentStoreConfiguration;
+import org.gluu.service.document.store.provider.DocumentStoreProvider;
+import org.gluu.util.security.StringEncrypter;
+import org.gluu.util.security.StringEncrypter.EncryptionException;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class JcaDocumentStoreManualTest {
+
+ public JcaDocumentStoreManualTest() {
+
+ }
+
+ public static void main(String[] args) throws RepositoryException, IOException, EncryptionException {
+ StringEncrypter se = new StringEncrypter(StringEncrypter.DESEDE_ENCRYPTION_SCHEME, "Zqvw62DEFdhxoL4csi9hpVI4");
+ DocumentStoreConfiguration dsc = new DocumentStoreConfiguration();
+ dsc.setDocumentStoreType(DocumentStoreType.JCA);
+
+ JcaDocumentStoreConfiguration jca = new JcaDocumentStoreConfiguration();
+ jca.setServerUrl("http://localhost:8080/rmi");
+ jca.setWorkspaceName("default");
+ jca.setUserId("admin");
+ jca.setPassword(se.encrypt("admin"));
+ jca.setConnectionTimeout(15);
+
+ dsc.setJcaConfiguration(jca);
+
+ LocalDocumentStoreConfiguration lca = new LocalDocumentStoreConfiguration();
+
+ dsc.setLocalConfiguration(lca);
+
+ ObjectMapper om = new ObjectMapper();
+ System.out.println(om.writeValueAsString(dsc));
+
+ StandaloneDocumentStoreProviderFactory pf = new StandaloneDocumentStoreProviderFactory(se);
+ DocumentStoreProvider dsp = pf.getDocumentStoreProvider(dsc);
+
+ String doc1 = FileUtils.readFileToString(new File("V:/authorization_code.jmx"), "UTF-8");
+ byte[] doc2 = FileUtils.readFileToByteArray(new File("V:/scim_requests.zip"));
+
+ System.out.print("Has document: " + "/test2/test2/test.jmx: ");
+ System.out.println(dsp.hasDocument("/test2/test2/test.jmx"));
+
+ System.out.print("Has document: " + "/test2/test3/test3.jmx: ");
+ System.out.println(dsp.hasDocument("/test2/test3/test3.jmx"));
+
+ System.out.print("Write document: " + "/test2/test3/test4/test5.jmx: ");
+ System.out.println(dsp.saveDocumentStream("/test2/test3/test4/test5.jmx", new ByteArrayInputStream(doc2), List.of("oxtrust-server","Shibboleth")));
+
+ System.out.print("Has document: " + "/test2/test3/test4/test5.jmx: ");
+ System.out.println(dsp.hasDocument("/test2/test3/test4/test5.jmx"));
+
+ System.out.print("Write document: " + "/test2/test3/test4/test5.jmx: ");
+ System.out.println(dsp.saveDocument("/test2/test3/test4/test5.jmx", doc1, StandardCharsets.UTF_8, List.of("oxtrust-server","Shibboleth")));
+
+ System.out.print("Has document: " + "/test2/test3/test4/test5.jmx: ");
+ System.out.println(dsp.hasDocument("/test2/test3/test4/test5.jmx"));
+
+ System.out.print("Read document: " + "/test2/test3/test4/test5.jmx: ");
+ System.out.println(dsp.readDocument("/test2/test3/test4/test5.jmx", StandardCharsets.UTF_8));
+
+ System.out.print("Read document: " + "/test2/test3/test4/test5.jmx: ");
+ System.out.println(IOUtils.toString(dsp.readDocumentAsStream("/test2/test3/test4/test5.jmx"), StandardCharsets.UTF_8));
+
+ System.out.print("Rename document: " + "/test2/test3/test4/test5.jmx: ");
+ System.out.println(dsp.renameDocument("/test2/test3/test4/test5.jmx", "/test2/test4/test5.jmx"));
+
+ System.out.print("Has document: " + "/test2/test3/test4/test5.jmx: ");
+ System.out.println(dsp.hasDocument("/test2/test3/test4/test5.jmx"));
+
+ System.out.print("Has document: " + "/test2/test4/test5.jmx: ");
+ System.out.println(dsp.hasDocument("/test2/test4/test5.jmx"));
+
+ System.out.print("Remove document: " + "test2/test4/test5.jmx: ");
+ System.out.println(dsp.removeDocument("/test2/test4/test5.jmx"));
+
+ System.out.print("Has document: " + "/test2/test4/test5.jmx: ");
+ System.out.println(dsp.hasDocument("/test2/test4/test5.jmx"));
+ }
+
+}
diff --git a/core-document-store/src/test/java/org/gluu/service/document/store/manual/WebDavDocumentStoreManualTest.java b/core-document-store/src/test/java/org/gluu/service/document/store/manual/WebDavDocumentStoreManualTest.java
new file mode 100644
index 000000000..7692c60ba
--- /dev/null
+++ b/core-document-store/src/test/java/org/gluu/service/document/store/manual/WebDavDocumentStoreManualTest.java
@@ -0,0 +1,98 @@
+package org.gluu.service.document.store.manual;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.gluu.service.document.store.StandaloneDocumentStoreProviderFactory;
+import org.gluu.service.document.store.conf.DocumentStoreConfiguration;
+import org.gluu.service.document.store.conf.DocumentStoreType;
+import org.gluu.service.document.store.conf.WebDavDocumentStoreConfiguration;
+import org.gluu.service.document.store.conf.LocalDocumentStoreConfiguration;
+import org.gluu.service.document.store.provider.DocumentStoreProvider;
+import org.gluu.util.security.StringEncrypter;
+import org.gluu.util.security.StringEncrypter.EncryptionException;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class WebDavDocumentStoreManualTest {
+
+ public WebDavDocumentStoreManualTest() {
+
+ }
+
+ public static void main(String[] args) throws RepositoryException, IOException, EncryptionException {
+ StringEncrypter se = new StringEncrypter(StringEncrypter.DESEDE_ENCRYPTION_SCHEME, "Zqvw62DEFdhxoL4csi9hpVI4");
+ DocumentStoreConfiguration dsc = new DocumentStoreConfiguration();
+ dsc.setDocumentStoreType(DocumentStoreType.WEB_DAV);
+
+ WebDavDocumentStoreConfiguration jca = new WebDavDocumentStoreConfiguration();
+ jca.setServerUrl("http://localhost:8080/repository");
+ jca.setWorkspaceName("default");
+ jca.setUserId("admin");
+ jca.setPassword(se.encrypt("admin"));
+ jca.setConnectionTimeout(15);
+
+ dsc.setWebDavConfiguration(jca);
+
+ LocalDocumentStoreConfiguration lca = new LocalDocumentStoreConfiguration();
+
+ dsc.setLocalConfiguration(lca);
+
+ ObjectMapper om = new ObjectMapper();
+ System.out.println(om.writeValueAsString(dsc));
+
+ StandaloneDocumentStoreProviderFactory pf = new StandaloneDocumentStoreProviderFactory(se);
+ DocumentStoreProvider dsp = pf.getDocumentStoreProvider(dsc);
+
+ String doc1 = FileUtils.readFileToString(new File("V:/test.log"), "UTF-8");
+ byte[] doc2 = FileUtils.readFileToByteArray(new File("V:/test.zip"));
+/*
+ System.out.print("Has document: " + "/test2/test2/test.jmx: ");
+ System.out.println(dsp.hasDocument("/test2/test2/test.jmx"));
+*/
+ System.out.print("Has document: " + "/test2/test3/test3.jmx: ");
+ System.out.println(dsp.hasDocument("/test2/test3/test3.jmx"));
+
+ System.out.print("Write document: " + "/test2/test3/test4/test5.jmx: ");
+ System.out.println(dsp.saveDocumentStream("/test-1.jmx", new ByteArrayInputStream(doc2), List.of("oxtrust-server","Shibboleth")));
+/*
+ System.out.print("Has document: " + "/test2/test3/test4/test5.jmx: ");
+ System.out.println(dsp.hasDocument("/test2/test3/test4/test5.jmx"));
+*/
+ System.out.print("Write document: " + "/test2/test3/test4/test5.jmx: ");
+ System.out.println(dsp.saveDocument("/test7.jmx", doc1, StandardCharsets.UTF_8, List.of("oxtrust-server","Shibboleth")));
+/*
+ System.out.print("Has document: " + "/test2/test3/test4/test5.jmx: ");
+ System.out.println(dsp.hasDocument("/test2/test3/test4/test5.jmx"));
+
+ System.out.print("Read document: " + "/test2/test3/test4/test5.jmx: ");
+ System.out.println(dsp.readDocument("/test2/test3/test4/test5.jmx", StandardCharsets.UTF_8));
+
+ System.out.print("Read document: " + "/test2/test3/test4/test5.jmx: ");
+ System.out.println(IOUtils.toString(dsp.readDocumentAsStream("/test2/test3/test4/test5.jmx"), StandardCharsets.UTF_8));
+
+ System.out.print("Rename document: " + "/test2/test3/test4/test5.jmx: ");
+ System.out.println(dsp.renameDocument("/test2/test3/test4/test5.jmx", "/test2/test4/test5.jmx"));
+
+ System.out.print("Has document: " + "/test2/test3/test4/test5.jmx: ");
+ System.out.println(dsp.hasDocument("/test2/test3/test4/test5.jmx"));
+
+ System.out.print("Has document: " + "/test2/test4/test5.jmx: ");
+ System.out.println(dsp.hasDocument("/test2/test4/test5.jmx"));
+
+ System.out.print("Remove document: " + "test2/test4/test5.jmx: ");
+ System.out.println(dsp.removeDocument("/test2/test4/test5.jmx"));
+
+ System.out.print("Has document: " + "/test2/test4/test5.jmx: ");
+ System.out.println(dsp.hasDocument("/test2/test4/test5.jmx"));
+*/
+ }
+
+}
diff --git a/core-java-ext/pom.xml b/core-java-ext/pom.xml
new file mode 100644
index 000000000..064f83e3d
--- /dev/null
+++ b/core-java-ext/pom.xml
@@ -0,0 +1,32 @@
+
+
+ 4.0.0
+ oxcore-java-ext
+ jar
+ Java extensions
+
+
+ org.gluu
+ oxcore
+ 4.5.6-SNAPSHOT
+
+
+
+
+
+ src/main/resources
+ true
+
+ **/*.xml
+ **/services/*
+ **/*.properties
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core-java-ext/src/main/java/org/gluu/i18n/ExtendedResourceBundle.java b/core-java-ext/src/main/java/org/gluu/i18n/ExtendedResourceBundle.java
new file mode 100644
index 000000000..00a5dcc31
--- /dev/null
+++ b/core-java-ext/src/main/java/org/gluu/i18n/ExtendedResourceBundle.java
@@ -0,0 +1,116 @@
+package org.gluu.i18n;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.StandardWatchEventKinds;
+import java.nio.file.WatchKey;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Properties;
+import java.util.ResourceBundle;
+import java.util.Set;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * Custom i18n resource bundle with realod support
+ *
+ * @author Yuriy Movchan
+ * @version 02/07/2020
+ */
+public class ExtendedResourceBundle extends ResourceBundle {
+
+ private WatchKey watcher = null;
+ private Date watcherLastUpdate = new Date();
+
+ private String baseName;
+ private Path externalResource;
+ private Properties properties;
+ private Date lastUpdate;
+
+ private final ReentrantLock updateLock = new ReentrantLock();
+
+ public ExtendedResourceBundle(String baseName, Path externalResource, Properties properties) throws IOException {
+ this.baseName = baseName;
+ this.externalResource = externalResource;
+ this.properties = properties;
+
+ this.lastUpdate = new Date();
+
+ Path baseFolder = externalResource.getParent();
+ this.watcher = baseFolder.register(FileSystems.getDefault().newWatchService(), StandardWatchEventKinds.ENTRY_MODIFY);
+ }
+
+ @Override
+ protected Object handleGetObject(String key) {
+ if (properties != null) {
+ if ((externalResource != null) && (watcher != null)) {
+ checkWatcher();
+
+ updateLock.lock();
+ try {
+ if (watcherLastUpdate.after(this.lastUpdate)) {
+ loadPropertiesFromFile(properties, externalResource);
+ this.lastUpdate = new Date();
+ }
+ } catch (IOException ex) {
+ System.err.println("Failed to reload message bundle:" + externalResource);
+ } finally {
+ updateLock.unlock();
+ }
+ }
+
+ return properties.get(key);
+ }
+
+ return parent.getObject(key);
+ }
+
+ private void checkWatcher() {
+ if (!watcher.pollEvents().isEmpty()) {
+ watcherLastUpdate = new Date();
+ }
+ }
+
+ @Override
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public Enumeration getKeys() {
+ if (properties != null) {
+ Set keys = properties.keySet();
+ return Collections.enumeration(keys);
+ }
+
+ return parent.getKeys();
+ }
+
+ public String getBaseName() {
+ return baseName;
+ }
+
+ protected static void loadPropertiesFromFile(Properties properties, Path externalResource) throws IOException {
+ if (externalResource == null) {
+ return;
+ }
+
+ InputStreamReader input = null;
+ try {
+ File file = externalResource.toFile();
+ if (file.exists()) {
+ input = new FileReader(externalResource.toFile());
+ properties.load(input); // External bundle (will overwrite same keys).
+ }
+ } catch (IOException ex) {
+ System.err.println("Failed to load message bundle:" + externalResource);
+ throw ex;
+ } finally {
+ try {
+ input.close();
+ } catch (Exception ex) {}
+ }
+ }
+
+}
diff --git a/core-java-ext/src/main/java/org/gluu/i18n/ExtendedResourceBundleControlProvider.java b/core-java-ext/src/main/java/org/gluu/i18n/ExtendedResourceBundleControlProvider.java
new file mode 100644
index 000000000..d22ed6e95
--- /dev/null
+++ b/core-java-ext/src/main/java/org/gluu/i18n/ExtendedResourceBundleControlProvider.java
@@ -0,0 +1,75 @@
+package org.gluu.i18n;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Locale;
+import java.util.Properties;
+import java.util.ResourceBundle;
+import java.util.ResourceBundle.Control;
+import java.util.spi.ResourceBundleControlProvider;
+
+/**
+ * Custom resource bundle loader java extension
+ *
+ * @author Yuriy Movchan
+ * @version 02/07/2020
+ */
+public class ExtendedResourceBundleControlProvider implements ResourceBundleControlProvider {
+
+ private static Path EXTERNAL_PATH;
+
+ static {
+ if (System.getProperty("server.base") != null) {
+ Path customPath = Paths.get(System.getProperty("server.base") + "/custom/i18n");
+ File file = customPath.toFile();
+ if (file.exists() && file.isDirectory()) {
+ EXTERNAL_PATH = customPath;
+ }
+ }
+ }
+
+ public ResourceBundle.Control getControl(String baseName) {
+ if (baseName.equals("javax.faces.Messages")) {
+ System.out.println("Preparing control to load bundle with baseName: " + baseName);
+ return new CustomControl();
+ }
+
+// System.out.println("Using default control to load bundle with baseName: " + baseName);
+
+ return null;
+ }
+
+ protected static class CustomControl extends Control {
+ @Override
+ public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload)
+ throws IllegalAccessException, InstantiationException, IOException {
+
+ String resourceName = toResourceName(toBundleName(baseName, locale), "properties");
+ Properties properties = new Properties();
+
+ try (InputStream input = loader.getResourceAsStream(resourceName)) {
+ InputStreamReader inputReader = new InputStreamReader(input, "UTF-8");
+ properties.load(inputReader); // Default (internal) bundle.
+ }
+
+ if (properties.isEmpty()) {
+ System.out.println("Using default control to load bundle with baseName: " + baseName);
+ return null;
+ }
+
+ Path externalResource = null;
+ if (EXTERNAL_PATH != null) {
+ externalResource = EXTERNAL_PATH.resolve(resourceName);
+ }
+ ExtendedResourceBundle.loadPropertiesFromFile(properties, externalResource);
+
+ return new ExtendedResourceBundle(baseName, externalResource, properties);
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/core-java-ext/src/main/resources/META-INF/services/java.util.spi.ResourceBundleControlProvider b/core-java-ext/src/main/resources/META-INF/services/java.util.spi.ResourceBundleControlProvider
new file mode 100644
index 000000000..7dd9f6737
--- /dev/null
+++ b/core-java-ext/src/main/resources/META-INF/services/java.util.spi.ResourceBundleControlProvider
@@ -0,0 +1 @@
+org.gluu.i18n.ExtendedResourceBundleControlProvider
\ No newline at end of file
diff --git a/core-script/pom.xml b/core-script/pom.xml
new file mode 100644
index 000000000..f7d11cb2b
--- /dev/null
+++ b/core-script/pom.xml
@@ -0,0 +1,105 @@
+
+
+ 4.0.0
+ oxcore-script
+ Reusable CDI Script implementation
+
+
+ org.gluu
+ oxcore
+ 4.5.6-SNAPSHOT
+
+
+
+ ${maven.min-version}
+
+
+
+
+
+ src/main/resources
+ true
+
+ **/*.xml
+ **/services/*
+ **/*.properties
+
+
+
+
+
+
+
+
+ ${project.groupId}
+ oxcore-cdi
+
+
+ ${project.groupId}
+ gluu-orm-core
+
+
+ ${project.groupId}
+ gluu-orm-model
+
+
+ ${project.groupId}
+ oxcore-model
+
+
+ ${project.groupId}
+ oxcore-util
+
+
+
+
+ org.gluufederation
+ jython-standalone
+
+
+
+
+ javax.enterprise
+ cdi-api
+ provided
+
+
+ javax.validation
+ validation-api
+ provided
+
+
+ javax.servlet
+ javax.servlet-api
+ provided
+
+
+
+
+ com.google.guava
+ guava
+
+
+
+
+ org.slf4j
+ slf4j-api
+ provided
+
+
+
+ javax.ws.rs
+ javax.ws.rs-api
+ provided
+
+
+
+
+ ${project.groupId}
+ gluu-orm-ldap
+ test
+
+
+
+
\ No newline at end of file
diff --git a/oxService/src/main/java/org/gluu/exception/PythonException.java b/core-script/src/main/java/org/gluu/exception/PythonException.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/exception/PythonException.java
rename to core-script/src/main/java/org/gluu/exception/PythonException.java
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/CustomScriptType.java b/core-script/src/main/java/org/gluu/model/custom/script/CustomScriptType.java
similarity index 66%
rename from oxService/src/main/java/org/gluu/model/custom/script/CustomScriptType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/CustomScriptType.java
index 131e5e0b0..9f29d5165 100644
--- a/oxService/src/main/java/org/gluu/model/custom/script/CustomScriptType.java
+++ b/core-script/src/main/java/org/gluu/model/custom/script/CustomScriptType.java
@@ -6,9 +6,6 @@
package org.gluu.model.custom.script;
-import java.util.HashMap;
-import java.util.Map;
-
import org.gluu.model.custom.script.model.CustomScript;
import org.gluu.model.custom.script.model.auth.AuthenticationCustomScript;
import org.gluu.model.custom.script.type.BaseExternalType;
@@ -16,24 +13,41 @@
import org.gluu.model.custom.script.type.auth.PersonAuthenticationType;
import org.gluu.model.custom.script.type.authz.ConsentGatheringType;
import org.gluu.model.custom.script.type.authz.DummyConsentGatheringType;
+import org.gluu.model.custom.script.type.authzchallenge.AuthorizationChallengeType;
+import org.gluu.model.custom.script.type.authzchallenge.DummyAuthorizationChallengeType;
+import org.gluu.model.custom.script.type.ciba.DummyEndUserNotificationType;
+import org.gluu.model.custom.script.type.ciba.EndUserNotificationType;
import org.gluu.model.custom.script.type.client.ClientRegistrationType;
import org.gluu.model.custom.script.type.client.DummyClientRegistrationType;
+import org.gluu.model.custom.script.type.fido2.DummyFido2ExtensionType;
+import org.gluu.model.custom.script.type.fido2.Fido2ExtensionType;
import org.gluu.model.custom.script.type.id.DummyIdGeneratorType;
import org.gluu.model.custom.script.type.id.IdGeneratorType;
+import org.gluu.model.custom.script.type.idp.DummyIdpType;
+import org.gluu.model.custom.script.type.idp.IdpType;
import org.gluu.model.custom.script.type.introspection.DummyIntrospectionType;
import org.gluu.model.custom.script.type.introspection.IntrospectionType;
+import org.gluu.model.custom.script.type.logout.DummyEndSessionType;
+import org.gluu.model.custom.script.type.logout.EndSessionType;
import org.gluu.model.custom.script.type.owner.DummyResourceOwnerPasswordCredentialsType;
import org.gluu.model.custom.script.type.owner.ResourceOwnerPasswordCredentialsType;
+import org.gluu.model.custom.script.type.persistence.DummyPeristenceType;
+import org.gluu.model.custom.script.type.persistence.PersistenceType;
+import org.gluu.model.custom.script.type.postauthn.DummyPostAuthnType;
+import org.gluu.model.custom.script.type.postauthn.PostAuthnType;
+import org.gluu.model.custom.script.type.revoke.DummyRevokeTokenType;
+import org.gluu.model.custom.script.type.revoke.RevokeTokenType;
import org.gluu.model.custom.script.type.scim.DummyScimType;
import org.gluu.model.custom.script.type.scim.ScimType;
import org.gluu.model.custom.script.type.scope.DummyDynamicScopeType;
import org.gluu.model.custom.script.type.scope.DynamicScopeType;
import org.gluu.model.custom.script.type.session.ApplicationSessionType;
import org.gluu.model.custom.script.type.session.DummyApplicationSessionType;
-import org.gluu.model.custom.script.type.uma.UmaClaimsGatheringType;
-import org.gluu.model.custom.script.type.uma.UmaDummyClaimsGatheringType;
-import org.gluu.model.custom.script.type.uma.UmaDummyRptPolicyType;
-import org.gluu.model.custom.script.type.uma.UmaRptPolicyType;
+import org.gluu.model.custom.script.type.spontaneous.DummySpontaneousScopeType;
+import org.gluu.model.custom.script.type.spontaneous.SpontaneousScopeType;
+import org.gluu.model.custom.script.type.token.DummyUpdateTokenType;
+import org.gluu.model.custom.script.type.token.UpdateTokenType;
+import org.gluu.model.custom.script.type.uma.*;
import org.gluu.model.custom.script.type.user.*;
import org.gluu.persist.annotation.AttributeEnum;
@@ -49,6 +63,7 @@ public enum CustomScriptType implements AttributeEnum {
PERSON_AUTHENTICATION("person_authentication", "Person Authentication", PersonAuthenticationType.class, AuthenticationCustomScript.class,
"PersonAuthentication", new DummyPersonAuthenticationType()),
+ AUTHORIZATION_CHALLENGE("authorization_challenge", "Authorization Challenge", AuthorizationChallengeType.class, CustomScript.class, "AuthorizationChallenge", new DummyAuthorizationChallengeType()),
INTROSPECTION("introspection", "Introspection", IntrospectionType.class, CustomScript.class, "Introspection", new DummyIntrospectionType()),
RESOURCE_OWNER_PASSWORD_CREDENTIALS("resource_owner_password_credentials", "Resource Owner Password Credentials", ResourceOwnerPasswordCredentialsType.class, CustomScript.class, "ResourceOwnerPasswordCredentials", new DummyResourceOwnerPasswordCredentialsType()),
APPLICATION_SESSION("application_session", "Application Session", ApplicationSessionType.class, CustomScript.class, "ApplicationSession",
@@ -64,13 +79,24 @@ public enum CustomScriptType implements AttributeEnum {
new DummyIdGeneratorType()),
UMA_RPT_POLICY("uma_rpt_policy", "UMA RPT Policies", UmaRptPolicyType.class, CustomScript.class, "UmaRptPolicy",
new UmaDummyRptPolicyType()),
+ UMA_RPT_CLAIMS("uma_rpt_claims", "UMA RPT Claims", UmaRptClaimsType.class, CustomScript.class, "UmaRptClaims", new UmaDummyRptClaimsType()),
UMA_CLAIMS_GATHERING("uma_claims_gathering", "UMA Claims Gathering", UmaClaimsGatheringType.class, CustomScript.class, "UmaClaimsGathering",
new UmaDummyClaimsGatheringType()),
CONSENT_GATHERING("consent_gathering", "Consent Gathering", ConsentGatheringType.class, CustomScript.class, "ConsentGathering",
new DummyConsentGatheringType()),
DYNAMIC_SCOPE("dynamic_scope", "Dynamic Scopes", DynamicScopeType.class, CustomScript.class, "DynamicScope",
new DummyDynamicScopeType()),
- SCIM("scim", "SCIM", ScimType.class, CustomScript.class, "ScimEventHandler", new DummyScimType());
+ SPONTANEOUS_SCOPE("spontaneous_scope", "Spontaneous Scopes", SpontaneousScopeType.class, CustomScript.class, "SpontaneousScope", new DummySpontaneousScopeType()),
+ END_SESSION("end_session", "End Session", EndSessionType.class, CustomScript.class, "EndSession", new DummyEndSessionType()),
+ POST_AUTHN("post_authn", "Post Authentication", PostAuthnType.class, CustomScript.class, "PostAuthn", new DummyPostAuthnType()),
+ SCIM("scim", "SCIM", ScimType.class, CustomScript.class, "ScimEventHandler", new DummyScimType()),
+ CIBA_END_USER_NOTIFICATION("ciba_end_user_notification", "CIBA End User Notification", EndUserNotificationType.class,
+ CustomScript.class, "EndUserNotification", new DummyEndUserNotificationType()),
+ REVOKE_TOKEN("revoke_token", "Revoke Token", RevokeTokenType.class, CustomScript.class, "RevokeToken", new DummyRevokeTokenType()),
+ PERSISTENCE_EXTENSION("persistence_extension", "Persistence Extension", PersistenceType.class, CustomScript.class, "PersistenceExtension", new DummyPeristenceType()),
+ IDP("idp", "Idp Extension", IdpType.class, CustomScript.class, "IdpExtension", new DummyIdpType()),
+ UPDATE_TOKEN("update_token", "Update Token", UpdateTokenType.class, CustomScript.class, "UpdateToken", new DummyUpdateTokenType()),
+ FIDO2_EXTENSION("fido2_extension", "Fido2 Extension", Fido2ExtensionType.class, CustomScript.class, "Fido2Extension", new DummyFido2ExtensionType());
private String value;
private String displayName;
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/conf/CustomScriptConfiguration.java b/core-script/src/main/java/org/gluu/model/custom/script/conf/CustomScriptConfiguration.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/model/custom/script/conf/CustomScriptConfiguration.java
rename to core-script/src/main/java/org/gluu/model/custom/script/conf/CustomScriptConfiguration.java
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/model/CustomScript.java b/core-script/src/main/java/org/gluu/model/custom/script/model/CustomScript.java
similarity index 90%
rename from oxService/src/main/java/org/gluu/model/custom/script/model/CustomScript.java
rename to core-script/src/main/java/org/gluu/model/custom/script/model/CustomScript.java
index a03d2f5cb..8e698cb2e 100644
--- a/oxService/src/main/java/org/gluu/model/custom/script/model/CustomScript.java
+++ b/core-script/src/main/java/org/gluu/model/custom/script/model/CustomScript.java
@@ -17,11 +17,11 @@
import org.gluu.model.SimpleCustomProperty;
import org.gluu.model.SimpleExtendedCustomProperty;
import org.gluu.model.custom.script.CustomScriptType;
-import org.gluu.persist.model.base.BaseEntry;
import org.gluu.persist.annotation.AttributeName;
import org.gluu.persist.annotation.DataEntry;
import org.gluu.persist.annotation.JsonObject;
import org.gluu.persist.annotation.ObjectClass;
+import org.gluu.persist.model.base.BaseEntry;
import org.gluu.util.StringHelper;
/**
@@ -29,10 +29,12 @@
*
* @author Yuriy Movchan Date: 12/03/2014
*/
-@DataEntry(sortBy = "level")
+@DataEntry(sortBy = "level", sortByName = "oxLevel")
@ObjectClass("oxCustomScript")
public class CustomScript extends BaseEntry {
+ private static final long serialVersionUID = -7507701887397812523L;
+
public static final String LOCATION_TYPE_MODEL_PROPERTY = "location_type";
public static final String LOCATION_PATH_MODEL_PROPERTY = "location_path";
@@ -61,12 +63,16 @@ public class CustomScript extends BaseEntry {
@JsonObject
@AttributeName(name = "oxModuleProperty")
- private List moduleProperties;
+ private List moduleProperties = new ArrayList<>();
@JsonObject
@AttributeName(name = "oxConfigurationProperty")
private List configurationProperties;
+ @JsonObject
+ @AttributeName(name = "gluuPrivateProperty")
+ private List privateProperties;
+
@AttributeName(name = "oxLevel")
private int level;
@@ -105,6 +111,7 @@ public CustomScript(CustomScript customScript) {
this.programmingLanguage = customScript.programmingLanguage;
this.moduleProperties = customScript.moduleProperties;
this.configurationProperties = customScript.configurationProperties;
+ this.privateProperties = customScript.privateProperties;
this.level = customScript.level;
this.revision = customScript.revision;
this.enabled = customScript.enabled;
@@ -149,6 +156,13 @@ public void setDescription(String description) {
}
public String getScript() {
+
+ if(script==null && scriptType==CustomScriptType.PERSON_AUTHENTICATION){
+ script=ScriptTemplate.AUTHEN.getValue();
+ }
+ else if(script==null && scriptType!=CustomScriptType.PERSON_AUTHENTICATION){
+ script=ScriptTemplate.NO_AUTHEN.getValue();
+ }
return script;
}
@@ -188,6 +202,14 @@ public void setConfigurationProperties(List proper
this.configurationProperties = properties;
}
+ public List getPrivateProperties() {
+ return privateProperties;
+ }
+
+ public void setPrivateProperties(List properties) {
+ this.privateProperties = properties;
+ }
+
public int getLevel() {
return level;
}
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/model/ScriptError.java b/core-script/src/main/java/org/gluu/model/custom/script/model/ScriptError.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/model/custom/script/model/ScriptError.java
rename to core-script/src/main/java/org/gluu/model/custom/script/model/ScriptError.java
diff --git a/core-script/src/main/java/org/gluu/model/custom/script/model/ScriptTemplate.java b/core-script/src/main/java/org/gluu/model/custom/script/model/ScriptTemplate.java
new file mode 100644
index 000000000..06aa3920d
--- /dev/null
+++ b/core-script/src/main/java/org/gluu/model/custom/script/model/ScriptTemplate.java
@@ -0,0 +1,94 @@
+package org.gluu.model.custom.script.model;
+
+public enum ScriptTemplate {
+
+ AUTHEN( "from org.gluu.service.cdi.util import CdiUtil\n" +
+ "from org.gluu.model.custom.script.type.auth import PersonAuthenticationType\n" +
+ "\n" +
+ "import java\n" +
+ "\n" +
+ "class PersonAuthentication(PersonAuthenticationType):\n" +
+ " def __init__(self, currentTimeMillis):\n" +
+ " self.currentTimeMillis = currentTimeMillis\n" +
+ "\n" +
+ " def init(self, configurationAttributes):\n" +
+ " return True \n" +
+ "\n" +
+ " def destroy(self, configurationAttributes):\n" +
+ " return True\n" +
+ "\n" +
+ " def getApiVersion(self):\n" +
+ " return 1\n" +
+ "\n" +
+ " def isValidAuthenticationMethod(self, usageType, configurationAttributes):\n" +
+ " return True\n" +
+ "\n" +
+ " def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes):\n" +
+ " return None\n" +
+ "\n" +
+ " def authenticate(self, configurationAttributes, requestParameters, step):\n" +
+ " return True\n" +
+ "\n" +
+ " def prepareForStep(self, configurationAttributes, requestParameters, step):\n" +
+ " return True\n" +
+ "\n" +
+ " def getExtraParametersForStep(self, configurationAttributes, step):\n" +
+ " return None\n" +
+ "\n" +
+ " def getCountAuthenticationSteps(self, configurationAttributes):\n" +
+ " return 1\n" +
+ "\n" +
+ " def getPageForStep(self, configurationAttributes, step):\n" +
+ " return \"\"\n" +
+ "\n" +
+ " def logout(self, configurationAttributes, requestParameters):\n" +
+ " return True\n"),
+ NO_AUTHEN("from org.gluu.service.cdi.util import CdiUtil\n" +
+ "from org.gluu.oxauth.security import Identity\n" +
+ "from org.gluu.model.custom.script.type.authz import ConsentGatheringType\n" +
+ "from org.gluu.util import StringHelper\n" +
+ "\n" +
+ "import java\n" +
+ "import random\n" +
+ "\n" +
+ "class SampleScript(ConsentGatheringType):\n" +
+ "\n" +
+ " def __init__(self, currentTimeMillis):\n" +
+ "\n" +
+ " def init(self, configurationAttributes):\n" +
+ " return True\n" +
+ "\n" +
+ " def destroy(self, configurationAttributes):\n" +
+ " return True\n" +
+ "\n" +
+ " def getApiVersion(self):\n" +
+ " return 1\n" +
+ "\n" +
+ " \n" +
+ " def authorize(self, step, context): \n" +
+ " return True\n" +
+ "\n" +
+ " def getNextStep(self, step, context):\n" +
+ " return -1\n" +
+ "\n" +
+ " def prepareForStep(self, step, context):\n" +
+ " return True\n" +
+ "\n" +
+ " def getStepsCount(self, context):\n" +
+ " return 2\n" +
+ "\n" +
+ " def getPageForStep(self, step, context):\n" +
+ " return \"\"\n");
+
+
+ private final String value;
+
+
+ ScriptTemplate(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return this.value;
+ }
+}
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/model/auth/AuthenticationCustomScript.java b/core-script/src/main/java/org/gluu/model/custom/script/model/auth/AuthenticationCustomScript.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/model/custom/script/model/auth/AuthenticationCustomScript.java
rename to core-script/src/main/java/org/gluu/model/custom/script/model/auth/AuthenticationCustomScript.java
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/model/bind/BindCredentials.java b/core-script/src/main/java/org/gluu/model/custom/script/model/bind/BindCredentials.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/model/custom/script/model/bind/BindCredentials.java
rename to core-script/src/main/java/org/gluu/model/custom/script/model/bind/BindCredentials.java
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/BaseExternalType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/BaseExternalType.java
similarity index 77%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/BaseExternalType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/BaseExternalType.java
index db4773c4e..59557c646 100644
--- a/oxService/src/main/java/org/gluu/model/custom/script/type/BaseExternalType.java
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/BaseExternalType.java
@@ -7,7 +7,7 @@
import java.util.Map;
import org.gluu.model.SimpleCustomProperty;
-
+import org.gluu.model.custom.script.model.CustomScript;
/**
* Base interface for external python script
*
@@ -16,6 +16,8 @@
public interface BaseExternalType {
boolean init(Map configurationAttributes);
+
+ boolean init(CustomScript customScript, Map configurationAttributes);
boolean destroy(Map configurationAttributes);
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/auth/DummyPersonAuthenticationType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/auth/DummyPersonAuthenticationType.java
similarity index 85%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/auth/DummyPersonAuthenticationType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/auth/DummyPersonAuthenticationType.java
index 5b73f53bd..7a481ce7f 100644
--- a/oxService/src/main/java/org/gluu/model/custom/script/type/auth/DummyPersonAuthenticationType.java
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/auth/DummyPersonAuthenticationType.java
@@ -11,7 +11,7 @@
import org.gluu.model.AuthenticationScriptUsageType;
import org.gluu.model.SimpleCustomProperty;
-
+import org.gluu.model.custom.script.model.CustomScript;
/**
* Dummy implementation of interface PersonAuthenticationType
*
@@ -23,7 +23,10 @@ public class DummyPersonAuthenticationType implements PersonAuthenticationType {
public boolean init(Map configurationAttributes) {
return true;
}
-
+ @Override
+ public boolean init(CustomScript customScript, Map configurationAttributes) {
+ return true;
+ }
@Override
public boolean destroy(Map configurationAttributes) {
return true;
@@ -85,7 +88,7 @@ public int getApiVersion() {
}
@Override
- public Map getAuthenticationMethodClaims() {
+ public Map getAuthenticationMethodClaims(Map configurationAttribute) {
return null;
}
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/auth/PersonAuthenticationType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/auth/PersonAuthenticationType.java
similarity index 92%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/auth/PersonAuthenticationType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/auth/PersonAuthenticationType.java
index fbd285e7d..fcb478ac6 100644
--- a/oxService/src/main/java/org/gluu/model/custom/script/type/auth/PersonAuthenticationType.java
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/auth/PersonAuthenticationType.java
@@ -6,13 +6,13 @@
package org.gluu.model.custom.script.type.auth;
+import java.util.List;
+import java.util.Map;
+
import org.gluu.model.AuthenticationScriptUsageType;
import org.gluu.model.SimpleCustomProperty;
import org.gluu.model.custom.script.type.BaseExternalType;
-import java.util.List;
-import java.util.Map;
-
/**
* Base interface for external authentication python script
*
@@ -41,5 +41,5 @@ String getAlternativeAuthenticationMethod(AuthenticationScriptUsageType usageTyp
String getLogoutExternalUrl(Map configurationAttributes, Map requestParameters);
- Map getAuthenticationMethodClaims();
+ Map getAuthenticationMethodClaims(Map configurationAttributes);
}
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/authz/ConsentGatheringType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/authz/ConsentGatheringType.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/authz/ConsentGatheringType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/authz/ConsentGatheringType.java
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/authz/DummyConsentGatheringType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/authz/DummyConsentGatheringType.java
similarity index 84%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/authz/DummyConsentGatheringType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/authz/DummyConsentGatheringType.java
index ae5217021..fd2434973 100644
--- a/oxService/src/main/java/org/gluu/model/custom/script/type/authz/DummyConsentGatheringType.java
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/authz/DummyConsentGatheringType.java
@@ -3,7 +3,7 @@
import java.util.Map;
import org.gluu.model.SimpleCustomProperty;
-
+import org.gluu.model.custom.script.model.CustomScript;
/**
* Dummy implementation of interface AuthorizationType
*
@@ -15,7 +15,10 @@ public class DummyConsentGatheringType implements ConsentGatheringType {
public boolean init(Map configurationAttributes) {
return false;
}
-
+ @Override
+ public boolean init(CustomScript customScript, Map configurationAttributes) {
+ return true;
+ }
@Override
public boolean destroy(Map configurationAttributes) {
return false;
diff --git a/core-script/src/main/java/org/gluu/model/custom/script/type/authzchallenge/AuthorizationChallengeType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/authzchallenge/AuthorizationChallengeType.java
new file mode 100644
index 000000000..f9f3f0be8
--- /dev/null
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/authzchallenge/AuthorizationChallengeType.java
@@ -0,0 +1,11 @@
+package org.gluu.model.custom.script.type.authzchallenge;
+
+import org.gluu.model.custom.script.type.BaseExternalType;
+
+/**
+ * @author Yuriy Z
+ */
+public interface AuthorizationChallengeType extends BaseExternalType {
+
+ boolean authorize(Object context);
+}
diff --git a/core-script/src/main/java/org/gluu/model/custom/script/type/authzchallenge/DummyAuthorizationChallengeType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/authzchallenge/DummyAuthorizationChallengeType.java
new file mode 100644
index 000000000..e33d5213a
--- /dev/null
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/authzchallenge/DummyAuthorizationChallengeType.java
@@ -0,0 +1,37 @@
+package org.gluu.model.custom.script.type.authzchallenge;
+
+import org.gluu.model.SimpleCustomProperty;
+import org.gluu.model.custom.script.model.CustomScript;
+
+import java.util.Map;
+
+/**
+ * @author Yuriy Z
+ */
+public class DummyAuthorizationChallengeType implements AuthorizationChallengeType {
+
+ @Override
+ public boolean authorize(Object context) {
+ return false;
+ }
+
+ @Override
+ public boolean init(Map configurationAttributes) {
+ return false;
+ }
+
+ @Override
+ public boolean init(CustomScript customScript, Map configurationAttributes) {
+ return false;
+ }
+
+ @Override
+ public boolean destroy(Map configurationAttributes) {
+ return false;
+ }
+
+ @Override
+ public int getApiVersion() {
+ return 1;
+ }
+}
diff --git a/core-script/src/main/java/org/gluu/model/custom/script/type/ciba/DummyEndUserNotificationType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/ciba/DummyEndUserNotificationType.java
new file mode 100644
index 000000000..d496a97c6
--- /dev/null
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/ciba/DummyEndUserNotificationType.java
@@ -0,0 +1,44 @@
+/*
+ * oxCore is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
+ *
+ * Copyright (c) 2014, Gluu
+ */
+
+package org.gluu.model.custom.script.type.ciba;
+
+import java.util.Map;
+
+import org.gluu.model.SimpleCustomProperty;
+import org.gluu.model.custom.script.model.CustomScript;
+
+/**
+ * Dummy implementation of interface EndUserNotificationType
+ *
+ * @author Milton BO Date: 04/22/2020
+ */
+public class DummyEndUserNotificationType implements EndUserNotificationType {
+
+ @Override
+ public boolean init(Map configurationAttributes) {
+ return true;
+ }
+ @Override
+ public boolean init(CustomScript customScript, Map configurationAttributes) {
+ return true;
+ }
+ @Override
+ public boolean destroy(Map configurationAttributes) {
+ return true;
+ }
+
+ @Override
+ public int getApiVersion() {
+ return 1;
+ }
+
+ @Override
+ public boolean notifyEndUser(Object context) {
+ return false;
+ }
+
+}
diff --git a/core-script/src/main/java/org/gluu/model/custom/script/type/ciba/EndUserNotificationType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/ciba/EndUserNotificationType.java
new file mode 100644
index 000000000..dc86bfde7
--- /dev/null
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/ciba/EndUserNotificationType.java
@@ -0,0 +1,20 @@
+/*
+ * oxCore is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
+ *
+ * Copyright (c) 2014, Gluu
+ */
+
+package org.gluu.model.custom.script.type.ciba;
+
+import org.gluu.model.custom.script.type.BaseExternalType;
+
+/**
+ * Base interface for external authentication python script
+ *
+ * @author Milton BO Date: 04/22/2020
+ */
+public interface EndUserNotificationType extends BaseExternalType {
+
+ boolean notifyEndUser(Object context);
+
+}
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/client/ClientRegistrationType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/client/ClientRegistrationType.java
similarity index 87%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/client/ClientRegistrationType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/client/ClientRegistrationType.java
index ab9bd366f..06f802670 100644
--- a/oxService/src/main/java/org/gluu/model/custom/script/type/client/ClientRegistrationType.java
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/client/ClientRegistrationType.java
@@ -6,11 +6,11 @@
package org.gluu.model.custom.script.type.client;
-import java.util.Map;
-
import org.gluu.model.SimpleCustomProperty;
import org.gluu.model.custom.script.type.BaseExternalType;
+import java.util.Map;
+
/**
* Base interface for external custom client registration python script
*
@@ -22,4 +22,8 @@ public interface ClientRegistrationType extends BaseExternalType {
public boolean updateClient(Object registerRequest, Object client, Map configurationAttributes);
+ String getSoftwareStatementHmacSecret(Object context);
+
+ String getSoftwareStatementJwks(Object context);
+
}
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/client/DummyClientRegistrationType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/client/DummyClientRegistrationType.java
similarity index 71%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/client/DummyClientRegistrationType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/client/DummyClientRegistrationType.java
index eeb30cd69..cbf77668b 100644
--- a/oxService/src/main/java/org/gluu/model/custom/script/type/client/DummyClientRegistrationType.java
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/client/DummyClientRegistrationType.java
@@ -4,10 +4,10 @@
* Copyright (c) 2014, Gluu
*/package org.gluu.model.custom.script.type.client;
-import java.util.Map;
-
import org.gluu.model.SimpleCustomProperty;
+import org.gluu.model.custom.script.model.CustomScript;
+import java.util.Map;
/**
* Dummy implementation of interface ClientRegistrationType
*
@@ -19,7 +19,10 @@ public class DummyClientRegistrationType implements ClientRegistrationType {
public boolean init(Map configurationAttributes) {
return true;
}
-
+ @Override
+ public boolean init(CustomScript customScript, Map configurationAttributes) {
+ return true;
+ }
@Override
public boolean destroy(Map configurationAttributes) {
return true;
@@ -40,4 +43,13 @@ public boolean updateClient(Object registerRequest, Object client, Map configurationAttributes) {
+ return true;
+ }
+
+ @Override
+ public boolean init(CustomScript customScript, Map configurationAttributes) {
+ return true;
+ }
+
+ @Override
+ public boolean destroy(Map configurationAttributes) {
+ return true;
+ }
+
+ @Override
+ public int getApiVersion() {
+ return 1;
+ }
+
+ @Override
+ public boolean registerAttestationStart(Object paramAsJsonNode, Object context) {
+ return false;
+ }
+
+ @Override
+ public boolean registerAttestationFinish(Object paramAsJsonNode, Object context) {
+ return false;
+ }
+
+ @Override
+ public boolean verifyAttestationStart(Object paramAsJsonNode, Object context) {
+ return false;
+ }
+
+ @Override
+ public boolean verifyAttestationFinish(Object paramAsJsonNode, Object context) {
+ return false;
+ }
+
+ @Override
+ public boolean authenticateAssertionStart(Object paramAsJsonNode, Object context) {
+ return false;
+ }
+
+ @Override
+ public boolean authenticateAssertionFinish(Object paramAsJsonNode, Object context) {
+ return false;
+ }
+
+ @Override
+ public boolean verifyAssertionStart(Object paramAsJsonNode, Object context) {
+ return false;
+ }
+
+ @Override
+ public boolean verifyAssertionFinish(Object paramAsJsonNode, Object context) {
+ return false;
+ }
+
+}
diff --git a/core-script/src/main/java/org/gluu/model/custom/script/type/fido2/Fido2ExtensionType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/fido2/Fido2ExtensionType.java
new file mode 100644
index 000000000..d9c9eedd6
--- /dev/null
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/fido2/Fido2ExtensionType.java
@@ -0,0 +1,24 @@
+/*
+ * oxCore is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
+ *
+ * Copyright (c) 2020, Gluu
+ */
+
+package org.gluu.model.custom.script.type.fido2;
+
+import org.gluu.model.custom.script.type.BaseExternalType;
+
+public interface Fido2ExtensionType extends BaseExternalType {
+
+ boolean registerAttestationStart(Object paramAsJsonNode, Object context);
+ boolean registerAttestationFinish(Object paramAsJsonNode, Object context);
+
+ boolean verifyAttestationStart(Object paramAsJsonNode, Object context);
+ boolean verifyAttestationFinish(Object paramAsJsonNode, Object context);
+
+ boolean authenticateAssertionStart(Object paramAsJsonNode, Object context);
+ boolean authenticateAssertionFinish(Object paramAsJsonNode, Object context);
+
+ boolean verifyAssertionStart(Object paramAsJsonNode, Object context);
+ boolean verifyAssertionFinish(Object paramAsJsonNode, Object context);
+}
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/id/DummyIdGeneratorType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/id/DummyIdGeneratorType.java
similarity index 81%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/id/DummyIdGeneratorType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/id/DummyIdGeneratorType.java
index 9de8df3f5..8e39a5503 100644
--- a/oxService/src/main/java/org/gluu/model/custom/script/type/id/DummyIdGeneratorType.java
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/id/DummyIdGeneratorType.java
@@ -7,7 +7,7 @@
import java.util.Map;
import org.gluu.model.SimpleCustomProperty;
-
+import org.gluu.model.custom.script.model.CustomScript;
/**
* Dummy implementation of interface IdGeneratorType
*
@@ -19,7 +19,10 @@ public class DummyIdGeneratorType implements IdGeneratorType {
public boolean init(Map configurationAttributes) {
return true;
}
-
+ @Override
+ public boolean init(CustomScript customScript, Map configurationAttributes) {
+ return true;
+ }
@Override
public boolean destroy(Map configurationAttributes) {
return true;
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/id/IdGeneratorType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/id/IdGeneratorType.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/id/IdGeneratorType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/id/IdGeneratorType.java
diff --git a/core-script/src/main/java/org/gluu/model/custom/script/type/idp/DummyIdpType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/idp/DummyIdpType.java
new file mode 100644
index 000000000..c8d722d6b
--- /dev/null
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/idp/DummyIdpType.java
@@ -0,0 +1,53 @@
+/*
+ * oxCore is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
+ *
+ * Copyright (c) 2020, Gluu
+ */package org.gluu.model.custom.script.type.idp;
+
+import java.util.Map;
+
+import org.gluu.model.SimpleCustomProperty;
+import org.gluu.model.custom.script.model.CustomScript;
+/**
+ * Dummy implementation of interface IdpType
+ *
+ * @author Yuriy Movchan Date: 06/18/2020
+ */
+public class DummyIdpType implements IdpType {
+
+ @Override
+ public boolean init(Map configurationAttributes) {
+ return true;
+ }
+
+ @Override
+ public boolean init(CustomScript customScript, Map configurationAttributes) {
+ return true;
+ }
+
+ @Override
+ public boolean destroy(Map configurationAttributes) {
+ return true;
+ }
+
+ @Override
+ public int getApiVersion() {
+ return 1;
+ }
+
+ @Override
+ public boolean translateAttributes(Object context, Map configurationAttributes) {
+ return false;
+ }
+
+ @Override
+ public boolean updateAttributes(Object context, Map configurationAttributes) {
+ return false;
+ }
+
+ @Override
+ public boolean postAuthentication(Object context, Map configurationAttributes) {
+ return true;
+ }
+
+}
diff --git a/core-script/src/main/java/org/gluu/model/custom/script/type/idp/IdpType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/idp/IdpType.java
new file mode 100644
index 000000000..3a1869e0b
--- /dev/null
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/idp/IdpType.java
@@ -0,0 +1,27 @@
+/*
+ * oxCore is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
+ *
+ * Copyright (c) 2014, Gluu
+ */
+
+package org.gluu.model.custom.script.type.idp;
+
+import java.util.Map;
+
+import org.gluu.model.SimpleCustomProperty;
+import org.gluu.model.custom.script.type.BaseExternalType;
+
+/**
+ * Base interface for IDP script
+ *
+ * @author Yuriy Movchan Date: 06/18/2020
+ */
+public interface IdpType extends BaseExternalType {
+
+ boolean translateAttributes(Object context, Map configurationAttributes);
+
+ boolean updateAttributes(Object context, Map configurationAttributes);
+
+ boolean postAuthentication(Object context, Map configurationAttributes);
+
+}
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/introspection/DummyIntrospectionType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/introspection/DummyIntrospectionType.java
similarity index 76%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/introspection/DummyIntrospectionType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/introspection/DummyIntrospectionType.java
index 25419e1b9..a7dcb07d4 100644
--- a/oxService/src/main/java/org/gluu/model/custom/script/type/introspection/DummyIntrospectionType.java
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/introspection/DummyIntrospectionType.java
@@ -3,7 +3,7 @@
import java.util.Map;
import org.gluu.model.SimpleCustomProperty;
-
+import org.gluu.model.custom.script.model.CustomScript;
/**
* @author Yuriy Zabrovarnyy
*/
@@ -12,7 +12,10 @@ public class DummyIntrospectionType implements IntrospectionType {
public boolean init(Map configurationAttributes) {
return true;
}
-
+ @Override
+ public boolean init(CustomScript customScript, Map configurationAttributes) {
+ return true;
+ }
@Override
public boolean destroy(Map configurationAttributes) {
return true;
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/introspection/IntrospectionType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/introspection/IntrospectionType.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/introspection/IntrospectionType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/introspection/IntrospectionType.java
diff --git a/core-script/src/main/java/org/gluu/model/custom/script/type/logout/DummyEndSessionType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/logout/DummyEndSessionType.java
new file mode 100644
index 000000000..d8efad8c4
--- /dev/null
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/logout/DummyEndSessionType.java
@@ -0,0 +1,34 @@
+package org.gluu.model.custom.script.type.logout;
+
+import java.util.Map;
+
+import org.gluu.model.SimpleCustomProperty;
+import org.gluu.model.custom.script.model.CustomScript;
+
+/**
+ * @author Yuriy Zabrovarnyy
+ */
+public class DummyEndSessionType implements EndSessionType {
+ @Override
+ public boolean init(Map configurationAttributes) {
+ return true;
+ }
+ @Override
+ public boolean init(CustomScript customScript, Map configurationAttributes) {
+ return true;
+ }
+ @Override
+ public boolean destroy(Map configurationAttributes) {
+ return true;
+ }
+
+ @Override
+ public int getApiVersion() {
+ return 1;
+ }
+
+ @Override
+ public String getFrontchannelHtml(Object context) {
+ return null;
+ }
+}
diff --git a/core-script/src/main/java/org/gluu/model/custom/script/type/logout/EndSessionType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/logout/EndSessionType.java
new file mode 100644
index 000000000..d92a4c29f
--- /dev/null
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/logout/EndSessionType.java
@@ -0,0 +1,11 @@
+package org.gluu.model.custom.script.type.logout;
+
+import org.gluu.model.custom.script.type.BaseExternalType;
+
+/**
+ * @author Yuriy Zabrovarnyy
+ */
+public interface EndSessionType extends BaseExternalType {
+
+ String getFrontchannelHtml(Object context);
+}
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/owner/DummyResourceOwnerPasswordCredentialsType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/owner/DummyResourceOwnerPasswordCredentialsType.java
similarity index 76%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/owner/DummyResourceOwnerPasswordCredentialsType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/owner/DummyResourceOwnerPasswordCredentialsType.java
index 1a612988a..18fe2be02 100644
--- a/oxService/src/main/java/org/gluu/model/custom/script/type/owner/DummyResourceOwnerPasswordCredentialsType.java
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/owner/DummyResourceOwnerPasswordCredentialsType.java
@@ -3,6 +3,7 @@
import java.util.Map;
import org.gluu.model.SimpleCustomProperty;
+import org.gluu.model.custom.script.model.CustomScript;
/**
* @author Yuriy Zabrovarnyy
@@ -12,7 +13,10 @@ public class DummyResourceOwnerPasswordCredentialsType implements ResourceOwnerP
public boolean init(Map configurationAttributes) {
return true;
}
-
+ @Override
+ public boolean init(CustomScript customScript, Map configurationAttributes) {
+ return true;
+ }
@Override
public boolean destroy(Map configurationAttributes) {
return true;
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/owner/ResourceOwnerPasswordCredentialsType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/owner/ResourceOwnerPasswordCredentialsType.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/owner/ResourceOwnerPasswordCredentialsType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/owner/ResourceOwnerPasswordCredentialsType.java
diff --git a/core-script/src/main/java/org/gluu/model/custom/script/type/persistence/DummyPeristenceType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/persistence/DummyPeristenceType.java
new file mode 100644
index 000000000..ff18e9eca
--- /dev/null
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/persistence/DummyPeristenceType.java
@@ -0,0 +1,56 @@
+/*
+ * oxCore is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
+ *
+ * Copyright (c) 2020, Gluu
+ */package org.gluu.model.custom.script.type.persistence;
+
+import java.util.Map;
+
+import org.gluu.model.SimpleCustomProperty;
+import org.gluu.model.custom.script.model.CustomScript;
+/**
+ * Dummy implementation of interface DynamicPeristanceType
+ *
+ * @author Yuriy Movchan Date: 06/04/2020
+ */
+public class DummyPeristenceType implements PersistenceType {
+
+ @Override
+ public boolean init(Map configurationAttributes) {
+ return true;
+ }
+
+ @Override
+ public boolean init(CustomScript customScript, Map configurationAttributes) {
+ return true;
+ }
+
+ @Override
+ public boolean destroy(Map configurationAttributes) {
+ return true;
+ }
+
+ @Override
+ public int getApiVersion() {
+ return 1;
+ }
+
+ @Override
+ public void onAfterCreate(Object context, Map configurationAttributes) {
+ }
+
+ @Override
+ public void onAfterDestroy(Object context, Map configurationAttributes) {
+ }
+
+ @Override
+ public String createHashedPassword(String credential) {
+ return credential;
+ }
+
+ @Override
+ public boolean compareHashedPasswords(String credential, String storedCredential) {
+ return false;
+ }
+
+}
diff --git a/core-script/src/main/java/org/gluu/model/custom/script/type/persistence/PersistenceType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/persistence/PersistenceType.java
new file mode 100644
index 000000000..32cbbb58d
--- /dev/null
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/persistence/PersistenceType.java
@@ -0,0 +1,25 @@
+/*
+ * oxCore is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
+ *
+ * Copyright (c) 2014, Gluu
+ */
+
+package org.gluu.model.custom.script.type.persistence;
+
+import java.util.Map;
+
+import org.gluu.model.SimpleCustomProperty;
+import org.gluu.model.custom.script.type.BaseExternalType;
+import org.gluu.persist.extension.PersistenceExtension;
+
+/**
+ * Base interface for persistence script
+ *
+ * @author Yuriy Movchan Date: 06/04/2020
+ */
+public interface PersistenceType extends BaseExternalType, PersistenceExtension {
+
+ void onAfterCreate(Object context, Map configurationAttributes);
+ void onAfterDestroy(Object context, Map configurationAttributes);
+
+}
diff --git a/core-script/src/main/java/org/gluu/model/custom/script/type/postauthn/DummyPostAuthnType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/postauthn/DummyPostAuthnType.java
new file mode 100644
index 000000000..d94fcde65
--- /dev/null
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/postauthn/DummyPostAuthnType.java
@@ -0,0 +1,41 @@
+package org.gluu.model.custom.script.type.postauthn;
+
+import java.util.Map;
+
+import org.gluu.model.SimpleCustomProperty;
+import org.gluu.model.custom.script.model.CustomScript;
+
+/**
+ * @author Yuriy Zabrovarnyy
+ */
+public class DummyPostAuthnType implements PostAuthnType {
+ @Override
+ public boolean forceReAuthentication(Object context) {
+ return false;
+ }
+
+ @Override
+ public boolean forceAuthorization(Object context) {
+ return false;
+ }
+
+ @Override
+ public boolean init(Map configurationAttributes) {
+ return true;
+ }
+
+ @Override
+ public boolean init(CustomScript customScript, Map configurationAttributes) {
+ return true;
+ }
+
+ @Override
+ public boolean destroy(Map configurationAttributes) {
+ return true;
+ }
+
+ @Override
+ public int getApiVersion() {
+ return 0;
+ }
+}
diff --git a/core-script/src/main/java/org/gluu/model/custom/script/type/postauthn/PostAuthnType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/postauthn/PostAuthnType.java
new file mode 100644
index 000000000..63e6efea1
--- /dev/null
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/postauthn/PostAuthnType.java
@@ -0,0 +1,13 @@
+package org.gluu.model.custom.script.type.postauthn;
+
+import org.gluu.model.custom.script.type.BaseExternalType;
+
+/**
+ * @author Yuriy Zabrovarnyy
+ */
+public interface PostAuthnType extends BaseExternalType {
+
+ boolean forceReAuthentication(Object context);
+
+ boolean forceAuthorization(Object context);
+}
diff --git a/core-script/src/main/java/org/gluu/model/custom/script/type/revoke/DummyRevokeTokenType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/revoke/DummyRevokeTokenType.java
new file mode 100644
index 000000000..4aba8086b
--- /dev/null
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/revoke/DummyRevokeTokenType.java
@@ -0,0 +1,36 @@
+package org.gluu.model.custom.script.type.revoke;
+
+import org.gluu.model.SimpleCustomProperty;
+import org.gluu.model.custom.script.model.CustomScript;
+
+import java.util.Map;
+
+/**
+ * @author Yuriy Zabrovarnyy
+ */
+public class DummyRevokeTokenType implements RevokeTokenType {
+ @Override
+ public boolean init(Map configurationAttributes) {
+ return true;
+ }
+
+ @Override
+ public boolean init(CustomScript customScript, Map configurationAttributes) {
+ return true;
+ }
+
+ @Override
+ public boolean destroy(Map configurationAttributes) {
+ return true;
+ }
+
+ @Override
+ public int getApiVersion() {
+ return 1;
+ }
+
+ @Override
+ public boolean revoke(Object context) {
+ return true;
+ }
+}
diff --git a/core-script/src/main/java/org/gluu/model/custom/script/type/revoke/RevokeTokenType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/revoke/RevokeTokenType.java
new file mode 100644
index 000000000..7be84f194
--- /dev/null
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/revoke/RevokeTokenType.java
@@ -0,0 +1,11 @@
+package org.gluu.model.custom.script.type.revoke;
+
+import org.gluu.model.custom.script.type.BaseExternalType;
+
+/**
+ * @author Yuriy Zabrovarnyy
+ */
+public interface RevokeTokenType extends BaseExternalType {
+
+ boolean revoke(Object context);
+}
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/scim/DummyScimType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/scim/DummyScimType.java
similarity index 64%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/scim/DummyScimType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/scim/DummyScimType.java
index 396623201..60d157c1a 100644
--- a/oxService/src/main/java/org/gluu/model/custom/script/type/scim/DummyScimType.java
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/scim/DummyScimType.java
@@ -1,16 +1,14 @@
-/*
- * oxCore is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
- *
- * Copyright (c) 2014, Gluu
- */
package org.gluu.model.custom.script.type.scim;
import java.util.Map;
import org.gluu.model.SimpleCustomProperty;
+import org.gluu.model.custom.script.model.CustomScript;
+
+import javax.ws.rs.core.Response;
/**
- * @author Val Pecaoco
+ * @author jgomer2001
*/
public class DummyScimType implements ScimType {
@@ -19,6 +17,11 @@ public boolean init(Map configurationAttributes) {
return true;
}
+ @Override
+ public boolean init(CustomScript customScript, Map configurationAttributes) {
+ return true;
+ }
+
@Override
public boolean destroy(Map configurationAttributes) {
return true;
@@ -89,4 +92,34 @@ public boolean postDeleteGroup(Object user, Map co
return false;
}
+ @Override
+ public boolean getUser(Object user, Map configurationAttributes) {
+ return false;
+ }
+
+ @Override
+ public boolean getGroup(Object group, Map configurationAttributes) {
+ return false;
+ }
+
+ @Override
+ public boolean postSearchUsers(Object results, Map configurationAttributes) {
+ return false;
+ }
+
+ @Override
+ public boolean postSearchGroups(Object results, Map configurationAttributes) {
+ return false;
+ }
+
+ @Override
+ public Response manageResourceOperation(Object context, Object entity, Object payload, Map configurationAttributes) {
+ return null;
+ }
+
+ @Override
+ public Response manageSearchOperation(Object context, Object searchRequest, Map configurationAttributes) {
+ return null;
+ }
+
}
diff --git a/core-script/src/main/java/org/gluu/model/custom/script/type/scim/ScimType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/scim/ScimType.java
new file mode 100644
index 000000000..8d6f35c22
--- /dev/null
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/scim/ScimType.java
@@ -0,0 +1,51 @@
+package org.gluu.model.custom.script.type.scim;
+
+import java.util.Map;
+
+import org.gluu.model.SimpleCustomProperty;
+import org.gluu.model.custom.script.type.BaseExternalType;
+
+import javax.ws.rs.core.Response;
+
+/**
+ * @author jgomer2001
+ */
+public interface ScimType extends BaseExternalType {
+
+ boolean createUser(Object user, Map configurationAttributes);
+
+ boolean postCreateUser(Object user, Map configurationAttributes);
+
+ boolean updateUser(Object user, Map configurationAttributes);
+
+ boolean postUpdateUser(Object user, Map configurationAttributes);
+
+ boolean deleteUser(Object user, Map configurationAttributes);
+
+ boolean postDeleteUser(Object user, Map configurationAttributes);
+
+ boolean createGroup(Object group, Map configurationAttributes);
+
+ boolean postCreateGroup(Object group, Map configurationAttributes);
+
+ boolean updateGroup(Object group, Map configurationAttributes);
+
+ boolean postUpdateGroup(Object group, Map configurationAttributes);
+
+ boolean deleteGroup(Object group, Map configurationAttributes);
+
+ boolean postDeleteGroup(Object group, Map configurationAttributes);
+
+ boolean getUser(Object user, Map configurationAttributes);
+
+ boolean getGroup(Object group, Map configurationAttributes);
+
+ boolean postSearchUsers(Object results, Map configurationAttributes);
+
+ boolean postSearchGroups(Object results, Map configurationAttributes);
+
+ Response manageResourceOperation(Object context, Object entity, Object payload, Map configurationAttributes);
+
+ Response manageSearchOperation(Object context, Object searchRequest, Map configurationAttributes);
+
+}
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/scope/DummyDynamicScopeType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/scope/DummyDynamicScopeType.java
similarity index 83%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/scope/DummyDynamicScopeType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/scope/DummyDynamicScopeType.java
index 63b1fefd4..d5ee78288 100644
--- a/oxService/src/main/java/org/gluu/model/custom/script/type/scope/DummyDynamicScopeType.java
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/scope/DummyDynamicScopeType.java
@@ -8,7 +8,7 @@
import java.util.Map;
import org.gluu.model.SimpleCustomProperty;
-
+import org.gluu.model.custom.script.model.CustomScript;
/**
* Dummy implementation of interface DynamicScopeType
*
@@ -20,7 +20,10 @@ public class DummyDynamicScopeType implements DynamicScopeType {
public boolean init(Map configurationAttributes) {
return true;
}
-
+ @Override
+ public boolean init(CustomScript customScript, Map configurationAttributes) {
+ return true;
+ }
@Override
public boolean destroy(Map configurationAttributes) {
return true;
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/scope/DynamicScopeType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/scope/DynamicScopeType.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/scope/DynamicScopeType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/scope/DynamicScopeType.java
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/session/ApplicationSessionType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/session/ApplicationSessionType.java
similarity index 95%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/session/ApplicationSessionType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/session/ApplicationSessionType.java
index 796c71ce9..e5c303bfb 100644
--- a/oxService/src/main/java/org/gluu/model/custom/script/type/session/ApplicationSessionType.java
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/session/ApplicationSessionType.java
@@ -18,6 +18,8 @@
public interface ApplicationSessionType extends BaseExternalType {
boolean startSession(Object httpRequest, Object sessionState, Map configurationAttributes);
+
boolean endSession(Object httpRequest, Object sessionState, Map configurationAttributes);
+ void onEvent(Object event);
}
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/session/DummyApplicationSessionType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/session/DummyApplicationSessionType.java
similarity index 81%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/session/DummyApplicationSessionType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/session/DummyApplicationSessionType.java
index 261864dc0..b98493078 100644
--- a/oxService/src/main/java/org/gluu/model/custom/script/type/session/DummyApplicationSessionType.java
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/session/DummyApplicationSessionType.java
@@ -4,10 +4,10 @@
* Copyright (c) 2014, Gluu
*/
package org.gluu.model.custom.script.type.session;
-
import java.util.Map;
import org.gluu.model.SimpleCustomProperty;
+import org.gluu.model.custom.script.model.CustomScript;
/**
* Dummy implementation of interface ApplicationSessionType
@@ -20,7 +20,10 @@ public class DummyApplicationSessionType implements ApplicationSessionType {
public boolean init(Map configurationAttributes) {
return true;
}
-
+ @Override
+ public boolean init(CustomScript customScript, Map configurationAttributes) {
+ return true;
+ }
@Override
public boolean destroy(Map configurationAttributes) {
return true;
@@ -41,4 +44,7 @@ public boolean endSession(Object httpRequest, Object authorizationGrant, Map configurationAttributes) {
+ return true;
+ }
+
+ @Override
+ public boolean init(Map configurationAttributes) {
+ return true;
+ }
+
+ @Override
+ public boolean destroy(Map configurationAttributes) {
+ return true;
+ }
+
+ @Override
+ public int getApiVersion() {
+ return 0;
+ }
+}
diff --git a/core-script/src/main/java/org/gluu/model/custom/script/type/spontaneous/SpontaneousScopeType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/spontaneous/SpontaneousScopeType.java
new file mode 100644
index 000000000..89a703318
--- /dev/null
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/spontaneous/SpontaneousScopeType.java
@@ -0,0 +1,8 @@
+package org.gluu.model.custom.script.type.spontaneous;
+
+import org.gluu.model.custom.script.type.BaseExternalType;
+
+public interface SpontaneousScopeType extends BaseExternalType {
+
+ void manipulateScopes(Object context);
+}
diff --git a/core-script/src/main/java/org/gluu/model/custom/script/type/token/DummyUpdateTokenType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/token/DummyUpdateTokenType.java
new file mode 100644
index 000000000..a165317c0
--- /dev/null
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/token/DummyUpdateTokenType.java
@@ -0,0 +1,69 @@
+/*
+ * oxCore is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
+ *
+ * Copyright (c) 2020, Gluu
+ */
+
+package org.gluu.model.custom.script.type.token;
+
+import org.gluu.model.SimpleCustomProperty;
+import org.gluu.model.custom.script.model.CustomScript;
+
+import java.util.Map;
+
+/**
+ * @author Yuriy Movchan
+ */
+public class DummyUpdateTokenType implements UpdateTokenType {
+
+ @Override
+ public boolean init(Map configurationAttributes) {
+ return true;
+ }
+
+ @Override
+ public boolean init(CustomScript customScript, Map configurationAttributes) {
+ return true;
+ }
+
+ @Override
+ public boolean destroy(Map configurationAttributes) {
+ return true;
+ }
+
+ @Override
+ public int getApiVersion() {
+ return 1;
+ }
+
+ @Override
+ public boolean modifyIdToken(Object jwr, Object tokenContext) {
+ return false;
+ }
+
+ @Override
+ public boolean modifyRefreshToken(Object refreshToken, Object tokenContext) {
+ return false;
+ }
+
+ @Override
+ public boolean modifyAccessToken(Object accessToken, Object tokenContext) {
+ return false;
+ }
+
+ @Override
+ public int getRefreshTokenLifetimeInSeconds(Object tokenContext) {
+ return 0;
+ }
+
+ @Override
+ public int getIdTokenLifetimeInSeconds(Object context) {
+ return 0;
+ }
+
+ @Override
+ public int getAccessTokenLifetimeInSeconds(Object context) {
+ return 0;
+ }
+
+}
diff --git a/core-script/src/main/java/org/gluu/model/custom/script/type/token/UpdateTokenType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/token/UpdateTokenType.java
new file mode 100644
index 000000000..dafae0843
--- /dev/null
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/token/UpdateTokenType.java
@@ -0,0 +1,27 @@
+/*
+ * oxCore is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
+ *
+ * Copyright (c) 2020, Gluu
+ */
+
+package org.gluu.model.custom.script.type.token;
+
+import org.gluu.model.custom.script.type.BaseExternalType;
+
+/**
+ * @author Yuriy Movchan
+ */
+public interface UpdateTokenType extends BaseExternalType {
+
+ boolean modifyIdToken(Object jsonWebResponse, Object tokenContext);
+
+ boolean modifyRefreshToken(Object refreshToken, Object tokenContext);
+
+ boolean modifyAccessToken(Object accessToken, Object tokenContext);
+
+ int getRefreshTokenLifetimeInSeconds(Object tokenContext);
+
+ int getIdTokenLifetimeInSeconds(Object context);
+
+ int getAccessTokenLifetimeInSeconds(Object context);
+}
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/uma/UmaClaimsGatheringType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/uma/UmaClaimsGatheringType.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/uma/UmaClaimsGatheringType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/uma/UmaClaimsGatheringType.java
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/uma/UmaDummyClaimsGatheringType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/uma/UmaDummyClaimsGatheringType.java
similarity index 83%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/uma/UmaDummyClaimsGatheringType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/uma/UmaDummyClaimsGatheringType.java
index 1de8936ae..4fc9cb562 100644
--- a/oxService/src/main/java/org/gluu/model/custom/script/type/uma/UmaDummyClaimsGatheringType.java
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/uma/UmaDummyClaimsGatheringType.java
@@ -3,7 +3,7 @@
import java.util.Map;
import org.gluu.model.SimpleCustomProperty;
-
+import org.gluu.model.custom.script.model.CustomScript;
/**
* @author yuriyz on 06/16/2017.
*/
@@ -38,7 +38,10 @@ public String getPageForStep(int step, Object gatheringContext) {
public boolean init(Map configurationAttributes) {
return true;
}
-
+ @Override
+ public boolean init(CustomScript customScript, Map configurationAttributes) {
+ return true;
+ }
@Override
public boolean destroy(Map configurationAttributes) {
return true;
diff --git a/core-script/src/main/java/org/gluu/model/custom/script/type/uma/UmaDummyRptClaimsType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/uma/UmaDummyRptClaimsType.java
new file mode 100644
index 000000000..42ed90b3b
--- /dev/null
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/uma/UmaDummyRptClaimsType.java
@@ -0,0 +1,37 @@
+package org.gluu.model.custom.script.type.uma;
+
+import org.gluu.model.SimpleCustomProperty;
+import org.gluu.model.custom.script.model.CustomScript;
+
+import java.util.Map;
+
+/**
+ * @author Yuriy Zabrovarnyy
+ */
+public class UmaDummyRptClaimsType implements UmaRptClaimsType {
+
+ @Override
+ public boolean modify(Object rptAsJsonObject, Object context) {
+ return false;
+ }
+
+ @Override
+ public boolean init(Map configurationAttributes) {
+ return true;
+ }
+
+ @Override
+ public boolean init(CustomScript customScript, Map configurationAttributes) {
+ return true;
+ }
+
+ @Override
+ public boolean destroy(Map configurationAttributes) {
+ return true;
+ }
+
+ @Override
+ public int getApiVersion() {
+ return 1;
+ }
+}
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/uma/UmaDummyRptPolicyType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/uma/UmaDummyRptPolicyType.java
similarity index 82%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/uma/UmaDummyRptPolicyType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/uma/UmaDummyRptPolicyType.java
index 2c5c1f0cf..debabd0dd 100644
--- a/oxService/src/main/java/org/gluu/model/custom/script/type/uma/UmaDummyRptPolicyType.java
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/uma/UmaDummyRptPolicyType.java
@@ -5,8 +5,8 @@
import java.util.Map;
import org.gluu.model.SimpleCustomProperty;
+import org.gluu.model.custom.script.model.CustomScript;
import org.gluu.model.uma.ClaimDefinition;
-
/**
* @author yuriyz on 05/30/2017.
*/
@@ -16,7 +16,10 @@ public class UmaDummyRptPolicyType implements UmaRptPolicyType {
public boolean init(Map configurationAttributes) {
return true;
}
-
+ @Override
+ public boolean init(CustomScript customScript, Map configurationAttributes) {
+ return true;
+ }
@Override
public boolean destroy(Map configurationAttributes) {
return true;
diff --git a/core-script/src/main/java/org/gluu/model/custom/script/type/uma/UmaRptClaimsType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/uma/UmaRptClaimsType.java
new file mode 100644
index 000000000..0ff56ca73
--- /dev/null
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/uma/UmaRptClaimsType.java
@@ -0,0 +1,11 @@
+package org.gluu.model.custom.script.type.uma;
+
+import org.gluu.model.custom.script.type.BaseExternalType;
+
+/**
+ * @author Yuriy Zabrovarnyy
+ */
+public interface UmaRptClaimsType extends BaseExternalType {
+
+ boolean modify(Object rptAsJsonObject, Object context);
+}
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/uma/UmaRptPolicyType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/uma/UmaRptPolicyType.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/uma/UmaRptPolicyType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/uma/UmaRptPolicyType.java
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/user/CacheRefreshType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/user/CacheRefreshType.java
similarity index 88%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/user/CacheRefreshType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/user/CacheRefreshType.java
index 878ee8ccc..6ff5108f2 100644
--- a/oxService/src/main/java/org/gluu/model/custom/script/type/user/CacheRefreshType.java
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/user/CacheRefreshType.java
@@ -24,4 +24,6 @@ public interface CacheRefreshType extends BaseExternalType {
public boolean updateUser(Object person, Map configurationAttributes);
+ public boolean updateSourceUser(Object person, Map configurationAttributes);
+
}
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/user/DummyCacheRefreshType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/user/DummyCacheRefreshType.java
similarity index 76%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/user/DummyCacheRefreshType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/user/DummyCacheRefreshType.java
index a817b2511..a89966b21 100644
--- a/oxService/src/main/java/org/gluu/model/custom/script/type/user/DummyCacheRefreshType.java
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/user/DummyCacheRefreshType.java
@@ -8,8 +8,8 @@
import java.util.Map;
import org.gluu.model.SimpleCustomProperty;
+import org.gluu.model.custom.script.model.CustomScript;
import org.gluu.model.custom.script.model.bind.BindCredentials;
-
/**
* Dummy implementation of interface CacheRefreshType
*
@@ -21,7 +21,10 @@ public class DummyCacheRefreshType implements CacheRefreshType {
public boolean init(Map configurationAttributes) {
return true;
}
-
+ @Override
+ public boolean init(CustomScript customScript, Map configurationAttributes) {
+ return true;
+ }
@Override
public boolean destroy(Map configurationAttributes) {
return true;
@@ -29,7 +32,7 @@ public boolean destroy(Map configurationAttributes
@Override
public int getApiVersion() {
- return 2;
+ return 3;
}
@Override
@@ -37,6 +40,11 @@ public boolean updateUser(Object person, Map confi
return false;
}
+ @Override
+ public boolean updateSourceUser(Object person, Map configurationAttributes) {
+ return false;
+ }
+
@Override
public BindCredentials getBindCredentials(String configId, Map configurationAttributes) {
return null;
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/user/DummyUpdateUserType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/user/DummyUpdateUserType.java
similarity index 89%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/user/DummyUpdateUserType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/user/DummyUpdateUserType.java
index a73dde8a2..69a340d02 100644
--- a/oxService/src/main/java/org/gluu/model/custom/script/type/user/DummyUpdateUserType.java
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/user/DummyUpdateUserType.java
@@ -8,7 +8,7 @@
import java.util.Map;
import org.gluu.model.SimpleCustomProperty;
-
+import org.gluu.model.custom.script.model.CustomScript;
/**
* Dummy implementation of interface UpdateUserType
*
@@ -21,7 +21,10 @@ public class DummyUpdateUserType implements UpdateUserType {
public boolean init(Map configurationAttributes) {
return true;
}
-
+ @Override
+ public boolean init(CustomScript customScript, Map configurationAttributes) {
+ return true;
+ }
@Override
public boolean destroy(Map configurationAttributes) {
return true;
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/user/DummyUserRegistrationType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/user/DummyUserRegistrationType.java
similarity index 88%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/user/DummyUserRegistrationType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/user/DummyUserRegistrationType.java
index 8c903ec55..536f40d1c 100644
--- a/oxService/src/main/java/org/gluu/model/custom/script/type/user/DummyUserRegistrationType.java
+++ b/core-script/src/main/java/org/gluu/model/custom/script/type/user/DummyUserRegistrationType.java
@@ -8,7 +8,7 @@
import java.util.Map;
import org.gluu.model.SimpleCustomProperty;
-
+import org.gluu.model.custom.script.model.CustomScript;
/**
* Dummy implementation of interface UserRegistrationType
*
@@ -20,7 +20,10 @@ public class DummyUserRegistrationType implements UserRegistrationType {
public boolean init(Map configurationAttributes) {
return true;
}
-
+ @Override
+ public boolean init(CustomScript customScript, Map configurationAttributes) {
+ return true;
+ }
@Override
public boolean destroy(Map configurationAttributes) {
return true;
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/user/UpdateUserType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/user/UpdateUserType.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/user/UpdateUserType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/user/UpdateUserType.java
diff --git a/oxService/src/main/java/org/gluu/model/custom/script/type/user/UserRegistrationType.java b/core-script/src/main/java/org/gluu/model/custom/script/type/user/UserRegistrationType.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/model/custom/script/type/user/UserRegistrationType.java
rename to core-script/src/main/java/org/gluu/model/custom/script/type/user/UserRegistrationType.java
diff --git a/oxService/src/main/java/org/gluu/service/PythonService.java b/core-script/src/main/java/org/gluu/service/PythonService.java
similarity index 91%
rename from oxService/src/main/java/org/gluu/service/PythonService.java
rename to core-script/src/main/java/org/gluu/service/PythonService.java
index 908234707..ce13fd20b 100644
--- a/oxService/src/main/java/org/gluu/service/PythonService.java
+++ b/core-script/src/main/java/org/gluu/service/PythonService.java
@@ -19,7 +19,6 @@
import javax.annotation.PreDestroy;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
-import javax.inject.Named;
import org.gluu.exception.PythonException;
import org.gluu.persist.reflect.util.ReflectHelper;
@@ -28,6 +27,7 @@
import org.python.core.PyObject;
import org.python.util.PythonInterpreter;
import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Provides operations with python module
@@ -35,7 +35,6 @@
* @author Yuriy Movchan Date: 08.21.2012
*/
@ApplicationScoped
-@Named
public class PythonService implements Serializable {
private static final long serialVersionUID = 3398422090669045605L;
@@ -58,15 +57,21 @@ public void init() {
}
}
+ public void configure() {
+ this.log = LoggerFactory.getLogger(PythonService.class);
+ }
+
/*
* Initialize singleton instance during startup
*/
public boolean initPythonInterpreter(String pythonModulesDir) {
boolean result = false;
- if (isInitInterpreter()) {
+ String pythonHome = getPythonHome();
+ log.info("Initializing PythonService with Jython: '{}'", pythonHome);
+ if (StringHelper.isNotEmpty(pythonHome)) {
try {
- PythonInterpreter.initialize(getPreProperties(), getPostProperties(pythonModulesDir), null);
+ PythonInterpreter.initialize(getPreProperties(), getPostProperties(pythonModulesDir, pythonHome), null);
this.pythonInterpreter = new PythonInterpreter();
initPythonInterpreter(this.pythonInterpreter);
@@ -77,6 +82,8 @@ public boolean initPythonInterpreter(String pythonModulesDir) {
} catch (Exception ex) {
log.error("Failed to initialize PythonInterpreter correctly", ex);
}
+ } else {
+ log.error("Failed to initialize PythonService. Jython location is not defined!");
}
this.interpereterReady = result;
@@ -117,16 +124,13 @@ private Properties getPreProperties() {
return clonedProps;
}
- private Properties getPostProperties(String pythonModulesDir) {
+ private Properties getPostProperties(String pythonModulesDir, String pythonHome) {
Properties props = getPreProperties();
String catalinaTmpFolder = System.getProperty("java.io.tmpdir") + File.separator + "python" + File.separator + "cachedir";
props.setProperty("python.cachedir", catalinaTmpFolder);
- String pythonHome = System.getenv("PYTHON_HOME");
- if (StringHelper.isNotEmpty(pythonHome)) {
- props.setProperty("python.home", pythonHome);
- }
+ props.setProperty("python.home", pythonHome);
// Register custom python modules
if (StringHelper.isNotEmpty(pythonModulesDir)) {
@@ -139,15 +143,14 @@ private Properties getPostProperties(String pythonModulesDir) {
return props;
}
- private boolean isInitInterpreter() {
- String pythonHome = System.getenv("PYTHON_HOME");
+ private String getPythonHome() {
+ String pythonHome = System.getenv("PYTHON_HOME");
if (StringHelper.isNotEmpty(pythonHome)) {
- System.setProperty("python.home", pythonHome);
+ return pythonHome;
}
- String pythonHomeProperty = System.getProperty("python.home");
- return StringHelper.isNotEmpty(pythonHomeProperty);
- }
+ return System.getProperty("python.home");
+ }
public T loadPythonScript(String scriptName, String scriptPythonType, Class scriptJavaType, PyObject[] constructorArgs)
throws PythonException {
diff --git a/oxService/src/main/java/org/gluu/service/cdi/event/UpdateScriptEvent.java b/core-script/src/main/java/org/gluu/service/cdi/event/UpdateScriptEvent.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/service/cdi/event/UpdateScriptEvent.java
rename to core-script/src/main/java/org/gluu/service/cdi/event/UpdateScriptEvent.java
diff --git a/oxService/src/main/java/org/gluu/service/custom/inject/ReloadScript.java b/core-script/src/main/java/org/gluu/service/custom/inject/ReloadScript.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/service/custom/inject/ReloadScript.java
rename to core-script/src/main/java/org/gluu/service/custom/inject/ReloadScript.java
diff --git a/core-script/src/main/java/org/gluu/service/custom/script/AbstractCustomScriptService.java b/core-script/src/main/java/org/gluu/service/custom/script/AbstractCustomScriptService.java
new file mode 100644
index 000000000..47a8d7c52
--- /dev/null
+++ b/core-script/src/main/java/org/gluu/service/custom/script/AbstractCustomScriptService.java
@@ -0,0 +1,211 @@
+/*
+ * oxCore is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
+ *
+ * Copyright (c) 2014, Gluu
+ */
+package org.gluu.service.custom.script;
+
+import com.google.common.base.Optional;
+import org.gluu.model.custom.script.CustomScriptType;
+import org.gluu.model.custom.script.model.CustomScript;
+import org.gluu.persist.PersistenceEntryManager;
+import org.gluu.search.filter.Filter;
+import org.gluu.util.OxConstants;
+import org.slf4j.Logger;
+
+import javax.inject.Inject;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Operations with custom scripts
+ *
+ * @author Yuriy Movchan Date: 12/03/2014
+ * @author Mougang T.Gasmyr
+ */
+public abstract class AbstractCustomScriptService implements Serializable {
+
+ private static final long serialVersionUID = -6187179012715072064L;
+
+ @Inject
+ protected Logger log;
+
+ @Inject
+ protected PersistenceEntryManager persistenceEntryManager;
+
+ public void add(CustomScript customScript) {
+ persistenceEntryManager.persist(customScript);
+ }
+
+ public void update(CustomScript customScript) {
+ persistenceEntryManager.merge(customScript);
+ }
+
+ public void remove(CustomScript customScript) {
+ persistenceEntryManager.remove(customScript);
+ }
+
+ public CustomScript getCustomScriptByDn(String customScriptDn, String... returnAttributes) {
+ return persistenceEntryManager.find(customScriptDn, CustomScript.class, returnAttributes);
+ }
+
+ public CustomScript getCustomScriptByDn(Class> customScriptType, String customScriptDn) {
+ return (CustomScript) persistenceEntryManager.find(customScriptType, customScriptDn);
+ }
+
+ public Optional getCustomScriptByINum(String baseDn, String inum, String... returnAttributes) {
+
+ final List customScriptTypeFilters = new ArrayList();
+
+ final Filter customScriptTypeFilter = Filter.createEqualityFilter("inum", inum);
+ customScriptTypeFilters.add(customScriptTypeFilter);
+
+ final Filter filter = Filter.createORFilter(customScriptTypeFilters);
+
+ final List result = persistenceEntryManager.findEntries(baseDn, CustomScript.class, filter, returnAttributes);
+
+ if (result.isEmpty()) {
+
+ return Optional.absent();
+ }
+
+ return Optional.of(result.get(0));
+ }
+
+
+ public List findAllCustomScripts(String[] returnAttributes) {
+ String baseDn = baseDn();
+
+ List result = persistenceEntryManager.findEntries(baseDn, CustomScript.class, null, returnAttributes);
+
+ return result;
+ }
+
+ public List findCustomScripts(List customScriptTypes, String... returnAttributes) {
+ String baseDn = baseDn();
+
+ if ((customScriptTypes == null) || (customScriptTypes.size() == 0)) {
+ return findAllCustomScripts(returnAttributes);
+ }
+
+ List customScriptTypeFilters = new ArrayList();
+ for (CustomScriptType customScriptType : customScriptTypes) {
+ Filter customScriptTypeFilter = Filter.createEqualityFilter("oxScriptType", customScriptType.getValue());
+ customScriptTypeFilters.add(customScriptTypeFilter);
+ }
+
+ Filter filter = Filter.createORFilter(customScriptTypeFilters);
+
+ List result = persistenceEntryManager.findEntries(baseDn, CustomScript.class, filter, returnAttributes);
+
+ return result;
+ }
+
+ public CustomScript getScriptByInum(String inum) {
+ return persistenceEntryManager.find(CustomScript.class, buildDn(inum));
+ }
+
+ public List findCustomAuthScripts(String pattern, int sizeLimit) {
+ String[] targetArray = new String[]{pattern};
+ Filter descriptionFilter = Filter.createSubstringFilter(OxConstants.DESCRIPTION, null, targetArray, null);
+ Filter scriptTypeFilter = Filter.createEqualityFilter(OxConstants.SCRIPT_TYPE,
+ CustomScriptType.PERSON_AUTHENTICATION);
+ Filter displayNameFilter = Filter.createSubstringFilter(OxConstants.DISPLAY_NAME, null, targetArray, null);
+ Filter searchFilter = Filter.createORFilter(descriptionFilter, displayNameFilter);
+
+ return persistenceEntryManager.findEntries(baseDn(), CustomScript.class,
+ Filter.createANDFilter(searchFilter, scriptTypeFilter), sizeLimit);
+ }
+
+ public List findCustomAuthScripts(int sizeLimit) {
+ Filter searchFilter = Filter.createEqualityFilter(OxConstants.SCRIPT_TYPE,
+ CustomScriptType.PERSON_AUTHENTICATION.getValue());
+
+ return persistenceEntryManager.findEntries(baseDn(), CustomScript.class, searchFilter,
+ sizeLimit);
+ }
+
+
+ public CustomScript getScriptByDisplayName(String name) {
+ Filter searchFilter = Filter.createEqualityFilter("displayName",
+ name);
+ List result=persistenceEntryManager.findEntries(baseDn(), CustomScript.class, searchFilter,
+ 1);
+ if(result!=null && !result.isEmpty()){
+ return result.get(0);
+ }
+ return null;
+ }
+ public int getScriptLevel(CustomScript customScript) {
+ if(customScript!=null){
+ return customScript.getLevel();
+ }
+ return -2;
+ }
+
+ public List findOtherCustomScripts(String pattern, int sizeLimit) {
+ String[] targetArray = new String[]{pattern};
+ Filter descriptionFilter = Filter.createSubstringFilter(OxConstants.DESCRIPTION, null, targetArray, null);
+ Filter scriptTypeFilter = Filter.createNOTFilter(
+ Filter.createEqualityFilter(OxConstants.SCRIPT_TYPE, CustomScriptType.PERSON_AUTHENTICATION));
+ Filter displayNameFilter = Filter.createSubstringFilter(OxConstants.DISPLAY_NAME, null, targetArray, null);
+ Filter searchFilter = Filter.createORFilter(descriptionFilter, displayNameFilter);
+
+ return persistenceEntryManager.findEntries(baseDn(), CustomScript.class,
+ Filter.createANDFilter(searchFilter, scriptTypeFilter), sizeLimit);
+ }
+
+ public List findScriptByType(CustomScriptType type, int sizeLimit) {
+ Filter searchFilter = Filter.createEqualityFilter(OxConstants.SCRIPT_TYPE, type);
+
+ return persistenceEntryManager.findEntries(baseDn(), CustomScript.class, searchFilter,
+ sizeLimit);
+ }
+
+ public List findScriptByType(CustomScriptType type) {
+ Filter searchFilter = Filter.createEqualityFilter(OxConstants.SCRIPT_TYPE, type);
+
+ return persistenceEntryManager.findEntries(baseDn(), CustomScript.class, searchFilter, null);
+ }
+
+ public List findScriptByPatternAndType(String pattern, CustomScriptType type, int sizeLimit) {
+ String[] targetArray = new String[]{pattern};
+ Filter descriptionFilter = Filter.createSubstringFilter(OxConstants.DESCRIPTION, null, targetArray, null);
+ Filter displayNameFilter = Filter.createSubstringFilter(OxConstants.DISPLAY_NAME, null, targetArray, null);
+ Filter searchFilter = Filter.createORFilter(descriptionFilter, displayNameFilter);
+ Filter typeFilter = Filter.createEqualityFilter(OxConstants.SCRIPT_TYPE, type);
+
+ return persistenceEntryManager.findEntries(baseDn(), CustomScript.class,
+ Filter.createANDFilter(searchFilter, typeFilter), sizeLimit);
+ }
+
+ public List findScriptByPatternAndType(String pattern, CustomScriptType type) {
+ String[] targetArray = new String[]{pattern};
+ Filter descriptionFilter = Filter.createSubstringFilter(OxConstants.DESCRIPTION, null, targetArray, null);
+ Filter displayNameFilter = Filter.createSubstringFilter(OxConstants.DISPLAY_NAME, null, targetArray, null);
+ Filter searchFilter = Filter.createORFilter(descriptionFilter, displayNameFilter);
+ Filter typeFilter = Filter.createEqualityFilter(OxConstants.SCRIPT_TYPE, type);
+
+ return persistenceEntryManager.findEntries(baseDn(), CustomScript.class,
+ Filter.createANDFilter(searchFilter, typeFilter), null);
+ }
+
+ public List findOtherCustomScripts(int sizeLimit) {
+ Filter searchFilter = Filter.createNOTFilter(
+ Filter.createEqualityFilter(OxConstants.SCRIPT_TYPE, CustomScriptType.PERSON_AUTHENTICATION));
+
+ return persistenceEntryManager.findEntries(baseDn(), CustomScript.class, searchFilter,
+ sizeLimit);
+ }
+
+ public String buildDn(String customScriptId) {
+ final StringBuilder dn = new StringBuilder();
+ dn.append(String.format("inum=%s,", customScriptId));
+ dn.append(baseDn());
+ return dn.toString();
+ }
+
+ public abstract String baseDn();
+
+}
diff --git a/oxService/src/main/java/org/gluu/service/custom/script/CustomScriptManager.java b/core-script/src/main/java/org/gluu/service/custom/script/CustomScriptManager.java
similarity index 85%
rename from oxService/src/main/java/org/gluu/service/custom/script/CustomScriptManager.java
rename to core-script/src/main/java/org/gluu/service/custom/script/CustomScriptManager.java
index 3c93ee0ed..593d025f7 100644
--- a/oxService/src/main/java/org/gluu/service/custom/script/CustomScriptManager.java
+++ b/core-script/src/main/java/org/gluu/service/custom/script/CustomScriptManager.java
@@ -24,6 +24,7 @@
import javax.enterprise.context.BeforeDestroyed;
import javax.enterprise.event.Event;
import javax.enterprise.event.Observes;
+import javax.enterprise.inject.Instance;
import javax.inject.Inject;
import javax.servlet.ServletContext;
@@ -62,7 +63,7 @@ public class CustomScriptManager implements Serializable {
private static final long serialVersionUID = -4225890597520443390L;
public static final String CUSTOM_SCRIPT_MODIFIED_EVENT_TYPE = "customScriptModifiedEvent";
- private static final int DEFAULT_INTERVAL = 30; // 30 seconds
+ public static final int DEFAULT_INTERVAL = 30; // 30 seconds
public static final String[] CUSTOM_SCRIPT_CHECK_ATTRIBUTES = { "dn", "inum", "oxRevision", "oxScriptType",
"oxModuleProperty", "oxEnabled" };
@@ -74,7 +75,7 @@ public class CustomScriptManager implements Serializable {
private Event timerEvent;
@Inject
- private PythonService pythonService;
+ protected PythonService pythonService;
@Inject
protected AbstractCustomScriptService customScriptService;
@@ -83,6 +84,9 @@ public class CustomScriptManager implements Serializable {
@ReloadScript
private Event event;
+ @Inject
+ private Instance externalScriptServiceInstance;
+
protected List supportedCustomScriptTypes;
private Map customScriptConfigurations;
@@ -95,18 +99,22 @@ public class CustomScriptManager implements Serializable {
public void initTimer(List supportedCustomScriptTypes) {
this.supportedCustomScriptTypes = supportedCustomScriptTypes;
- this.isActive = new AtomicBoolean(false);
- this.lastFinishedTime = System.currentTimeMillis();
+ configure();
final int delay = 30;
final int interval = DEFAULT_INTERVAL;
- reload();
+ reload(true);
timerEvent.fire(new TimerEvent(new TimerSchedule(delay, interval), new UpdateScriptEvent(),
Scheduled.Literal.INSTANCE));
}
+ protected void configure() {
+ this.isActive = new AtomicBoolean(false);
+ this.lastFinishedTime = System.currentTimeMillis();
+ }
+
public void reloadTimerEvent(@Observes @Scheduled UpdateScriptEvent updateScriptEvent) {
if (this.isActive.get()) {
return;
@@ -117,7 +125,7 @@ public void reloadTimerEvent(@Observes @Scheduled UpdateScriptEvent updateScript
}
try {
- reload();
+ reload(false);
} catch (Throwable ex) {
log.error("Exception happened while reloading custom scripts configuration", ex);
} finally {
@@ -140,18 +148,35 @@ public void destroy(@BeforeDestroyed(ApplicationScoped.class) ServletContext ini
}
}
- private void reload() {
+ private void reload(boolean syncUpdate) {
boolean modified = reloadImpl();
if (modified) {
+ updateScriptServices(syncUpdate);
+ }
+ }
+
+ protected void updateScriptServices(boolean syncUpdate) {
+ if (syncUpdate) {
+ for (ExternalScriptService externalScriptService : externalScriptServiceInstance) {
+ if (supportedCustomScriptTypes.contains(externalScriptService.getCustomScriptType())) {
+ externalScriptService.reload(CUSTOM_SCRIPT_MODIFIED_EVENT_TYPE);
+ }
+ }
+ } else {
event.fire(CUSTOM_SCRIPT_MODIFIED_EVENT_TYPE);
}
}
private boolean reloadImpl() {
// Load current script revisions
- List customScripts = customScriptService.findCustomScripts(supportedCustomScriptTypes,
- CUSTOM_SCRIPT_CHECK_ATTRIBUTES);
+ List customScripts;
+ if (supportedCustomScriptTypes.isEmpty()) {
+ customScripts = new ArrayList();
+ } else {
+ customScripts = customScriptService.findCustomScripts(supportedCustomScriptTypes,
+ CUSTOM_SCRIPT_CHECK_ATTRIBUTES);
+ }
// Store updated external authenticator configurations
ReloadResult reloadResult = reloadCustomScriptConfigurations(this.customScriptConfigurations, customScripts);
@@ -208,7 +233,7 @@ private ReloadResult reloadCustomScriptConfigurations(
// reload script automatically after changing location_type
long fileModifiactionTime = getFileModificationTime(newCustomScript.getLocationPath());
- newCustomScript.setRevision(fileModifiactionTime);
+ newCustomScript.setRevision(newCustomScript.getRevision() + fileModifiactionTime);
}
String newSupportedCustomScriptInum = StringHelper.toLowerCase(newCustomScript.getInum());
@@ -216,8 +241,8 @@ private ReloadResult reloadCustomScriptConfigurations(
CustomScriptConfiguration prevCustomScriptConfiguration = newCustomScriptConfigurations
.get(newSupportedCustomScriptInum);
- if ((prevCustomScriptConfiguration == null) || (prevCustomScriptConfiguration.getCustomScript()
- .getRevision() != newCustomScript.getRevision())) {
+ if (prevCustomScriptConfiguration == null || prevCustomScriptConfiguration.getCustomScript()
+ .getRevision() != newCustomScript.getRevision()) {
// Destroy old version properly before creating new one
if (prevCustomScriptConfiguration != null) {
destroyCustomScript(prevCustomScriptConfiguration);
@@ -245,7 +270,7 @@ private ReloadResult reloadCustomScriptConfigurations(
// Replace script revision with file modification time. This should allow to
// reload script automatically after changing location_type
long fileModifiactionTime = getFileModificationTime(loadedCustomScript.getLocationPath());
- loadedCustomScript.setRevision(fileModifiactionTime);
+ loadedCustomScript.setRevision(loadedCustomScript.getRevision() + fileModifiactionTime);
if (fileModifiactionTime != 0) {
String scriptFromFile = loadFromFile(loadedCustomScript.getLocationPath());
@@ -343,7 +368,9 @@ private Map> groupCustomScript
CustomScriptType customScriptType = customScriptConfiguration.getCustomScript().getScriptType();
List customConfigurationsByScriptType = newCustomScriptConfigurationsByScriptType
.get(customScriptType);
- customConfigurationsByScriptType.add(customScriptConfiguration);
+ if (customConfigurationsByScriptType != null) {
+ customConfigurationsByScriptType.add(customScriptConfiguration);
+ }
}
return newCustomScriptConfigurationsByScriptType;
@@ -401,7 +428,21 @@ public BaseExternalType createExternalTypeFromStringWithPythonException(CustomSc
boolean initialized = false;
try {
- initialized = externalType.init(configurationAttributes);
+ // Workaround to allow load all required class in init method needed for proper script work
+ // At the end we restore ContextClassLoader
+ // More details: https://github.com/JanssenProject/jans/issues/5116
+ ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+ try {
+ if (externalType.getApiVersion() > 10) {
+ initialized = externalType.init(customScript, configurationAttributes);
+ } else {
+ initialized = externalType.init(configurationAttributes);
+ log.warn(" Update the script's init method to init(self, customScript, configurationAttributes)", customScript.getName());
+ }
+ } finally {
+ Thread.currentThread().setContextClassLoader(oldClassLoader);
+ }
} catch (Exception ex) {
log.error("Failed to initialize custom script: '{}'", ex, customScript.getName());
}
@@ -495,8 +536,12 @@ public CustomScriptConfiguration getCustomScriptConfigurationByInum(String inum)
public List getCustomScriptConfigurationsByScriptType(
CustomScriptType customScriptType) {
- return new ArrayList(
- this.customScriptConfigurationsByScriptType.get(customScriptType));
+ List tmpCustomScriptConfigurationsByScriptType = this.customScriptConfigurationsByScriptType
+ .get(customScriptType);
+ if (tmpCustomScriptConfigurationsByScriptType == null) {
+ tmpCustomScriptConfigurationsByScriptType = new ArrayList(0);
+ }
+ return new ArrayList(tmpCustomScriptConfigurationsByScriptType);
}
public List getCustomScriptConfigurations() {
@@ -507,4 +552,8 @@ public List getSupportedCustomScriptTypes() {
return supportedCustomScriptTypes;
}
+ public boolean isSupportedType(CustomScriptType customScriptType) {
+ return supportedCustomScriptTypes.contains(customScriptType);
+ }
+
}
diff --git a/oxService/src/main/java/org/gluu/service/custom/script/ExternalScriptService.java b/core-script/src/main/java/org/gluu/service/custom/script/ExternalScriptService.java
similarity index 77%
rename from oxService/src/main/java/org/gluu/service/custom/script/ExternalScriptService.java
rename to core-script/src/main/java/org/gluu/service/custom/script/ExternalScriptService.java
index 203ac05c3..7d7dd39d8 100644
--- a/oxService/src/main/java/org/gluu/service/custom/script/ExternalScriptService.java
+++ b/core-script/src/main/java/org/gluu/service/custom/script/ExternalScriptService.java
@@ -11,6 +11,7 @@
import java.util.List;
import java.util.Map;
+import javax.annotation.PostConstruct;
import javax.enterprise.event.Observes;
import javax.inject.Inject;
@@ -21,13 +22,16 @@
import org.gluu.service.custom.inject.ReloadScript;
import org.gluu.util.StringHelper;
import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
/**
* Provides factory methods needed to create external extension
*
* @author Yuriy Movchan Date: 01/08/2015
*/
-public class ExternalScriptService implements Serializable {
+public abstract class ExternalScriptService implements Serializable {
private static final long serialVersionUID = -1070021905117441202L;
@@ -38,16 +42,35 @@ public class ExternalScriptService implements Serializable {
protected CustomScriptManager customScriptManager;
protected CustomScriptType customScriptType;
+
+ protected boolean loaded;
protected Map customScriptConfigurationsNameMap;
protected List customScriptConfigurations;
protected CustomScriptConfiguration defaultExternalCustomScript;
+ @PostConstruct
+ public void init() {
+ this.loaded = false;
+ }
+
public ExternalScriptService(CustomScriptType customScriptType) {
this.customScriptType = customScriptType;
}
+ /**
+ * Method for standalone usage
+ */
+ public void configure(StandaloneCustomScriptManager customScriptManager) {
+ this.customScriptManager = customScriptManager;
+ this.log = LoggerFactory.getLogger(ExternalScriptService.class);
+ }
+
public void reload(@Observes @ReloadScript String event) {
+ // Skip reload if global script is not enabled for this application
+ if (!customScriptManager.isSupportedType(customScriptType)) {
+ return;
+ }
// Get actual list of external configurations
List newCustomScriptConfigurations = customScriptManager
.getCustomScriptConfigurationsByScriptType(customScriptType);
@@ -61,6 +84,8 @@ public void reload(@Observes @ReloadScript String event) {
// Allow to execute additional logic
reloadExternal();
+
+ loaded = true;
}
protected void addExternalConfigurations(List newCustomScriptConfigurations) {
@@ -94,7 +119,7 @@ public CustomScriptConfiguration determineDefaultCustomScriptConfiguration(List<
public int executeExternalGetApiVersion(CustomScriptConfiguration customScriptConfiguration) {
try {
- log.debug("Executing python 'getApiVersion' authenticator method");
+ log.trace("Executing python 'getApiVersion' authenticator method");
BaseExternalType externalAuthenticator = (BaseExternalType) customScriptConfiguration.getExternalType();
return externalAuthenticator.getApiVersion();
} catch (Exception ex) {
@@ -133,4 +158,25 @@ public List getCustomScriptConfigurations() {
return this.customScriptConfigurations;
}
+ public List getCustomScriptConfigurationsByDns(List dns) {
+ if (dns == null || dns.isEmpty() || customScriptConfigurations == null || customScriptConfigurations.isEmpty()) {
+ return Lists.newArrayList();
+ }
+ List scripts = Lists.newArrayList();
+ for (CustomScriptConfiguration script : customScriptConfigurations) {
+ if (dns.contains(script.getCustomScript().getDn())) {
+ scripts.add(script);
+ }
+ }
+ return scripts;
+ }
+
+ public CustomScriptType getCustomScriptType() {
+ return customScriptType;
+ }
+
+ public boolean isLoaded() {
+ return loaded;
+ }
+
}
diff --git a/core-script/src/main/java/org/gluu/service/custom/script/StandaloneCustomScriptManager.java b/core-script/src/main/java/org/gluu/service/custom/script/StandaloneCustomScriptManager.java
new file mode 100644
index 000000000..399accee6
--- /dev/null
+++ b/core-script/src/main/java/org/gluu/service/custom/script/StandaloneCustomScriptManager.java
@@ -0,0 +1,69 @@
+package org.gluu.service.custom.script;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.enterprise.inject.Vetoed;
+
+import org.gluu.model.custom.script.CustomScriptType;
+import org.gluu.persist.PersistenceEntryManager;
+import org.gluu.service.PythonService;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Standalone custom script manager
+ *
+ * @author Yuriy Movchan Date: 06/19/2020
+ */
+@Vetoed
+public class StandaloneCustomScriptManager extends CustomScriptManager {
+
+ private static final long serialVersionUID = -7212146007659551839L;
+
+ private List externalScriptServices = new ArrayList();
+
+ public StandaloneCustomScriptManager(PersistenceEntryManager entryManager, String scriptsBaseDn, String pythonModulesDir) {
+ // Configure python service
+ PythonService pythonService = new PythonService();
+ pythonService.configure();
+ pythonService.init();
+ // Initialize python interpreter
+ pythonService.initPythonInterpreter(pythonModulesDir);
+
+ // Configure custom script service
+ StandaloneCustomScriptService standaloneCustomScriptService = new StandaloneCustomScriptService();
+ standaloneCustomScriptService.configure(entryManager, scriptsBaseDn);
+
+ this.log = LoggerFactory.getLogger(StandaloneCustomScriptManager.class);
+ this.supportedCustomScriptTypes = new ArrayList();
+ this.pythonService = pythonService;
+ this.customScriptService = standaloneCustomScriptService;
+ }
+
+ public void init() {
+ configure();
+ reloadTimerEvent(null);
+ }
+
+ public void destory() {
+ super.destroy(null);
+ }
+
+ public void reload() {
+ reloadTimerEvent(null);
+ }
+
+ public void registerExternalScriptService(ExternalScriptService externalScriptService) {
+ externalScriptService.configure(this);
+ externalScriptServices.add(externalScriptService);
+ supportedCustomScriptTypes.add(externalScriptService.getCustomScriptType());
+ }
+
+ @Override
+ public void updateScriptServices(boolean syncUpdate) {
+ for (ExternalScriptService externalScriptService : externalScriptServices) {
+ externalScriptService.reload(null);
+ }
+ }
+
+}
diff --git a/core-script/src/main/java/org/gluu/service/custom/script/StandaloneCustomScriptService.java b/core-script/src/main/java/org/gluu/service/custom/script/StandaloneCustomScriptService.java
new file mode 100644
index 000000000..4b8c266fb
--- /dev/null
+++ b/core-script/src/main/java/org/gluu/service/custom/script/StandaloneCustomScriptService.java
@@ -0,0 +1,31 @@
+package org.gluu.service.custom.script;
+
+import javax.enterprise.inject.Vetoed;
+
+import org.gluu.persist.PersistenceEntryManager;
+import org.gluu.service.PythonService;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Operations with custom scripts
+ *
+ * @author Yuriy Movchan Date: 06/19/2020
+ */
+@Vetoed
+public class StandaloneCustomScriptService extends AbstractCustomScriptService {
+
+ private static final long serialVersionUID = -5283102477313448031L;
+
+ private String scriptsBaseDn;
+
+ public void configure(PersistenceEntryManager entryManager, String scriptsBaseDn) {
+ this.scriptsBaseDn = scriptsBaseDn;
+ this.log = LoggerFactory.getLogger(PythonService.class);
+ this.persistenceEntryManager = entryManager;
+ }
+
+ public String baseDn() {
+ return scriptsBaseDn;
+ }
+
+}
diff --git a/persistence-ldap/src/main/resources/META-INF/beans.xml b/core-script/src/main/resources/META-INF/beans.xml
similarity index 100%
rename from persistence-ldap/src/main/resources/META-INF/beans.xml
rename to core-script/src/main/resources/META-INF/beans.xml
diff --git a/core-script/src/test/java/org/gluu/service/custom/script/test/SampleIdpExternalScriptService.java b/core-script/src/test/java/org/gluu/service/custom/script/test/SampleIdpExternalScriptService.java
new file mode 100644
index 000000000..b206c21c6
--- /dev/null
+++ b/core-script/src/test/java/org/gluu/service/custom/script/test/SampleIdpExternalScriptService.java
@@ -0,0 +1,85 @@
+package org.gluu.service.custom.script.test;
+
+import java.util.Map;
+
+import org.gluu.model.SimpleCustomProperty;
+import org.gluu.model.custom.script.CustomScriptType;
+import org.gluu.model.custom.script.conf.CustomScriptConfiguration;
+import org.gluu.model.custom.script.type.idp.IdpType;
+import org.gluu.service.custom.script.ExternalScriptService;
+
+/**
+ * External IDP script service
+ *
+ * @author Yuriy Movchan
+ * @version 0.1, 06/18/2020
+ */
+public class SampleIdpExternalScriptService extends ExternalScriptService {
+
+ private static final long serialVersionUID = -1316361273036208685L;
+
+ public SampleIdpExternalScriptService() {
+ super(CustomScriptType.IDP);
+ }
+
+ // boolean translateAttributes(Object context, Map configurationAttributes);
+
+ public boolean executeExternalTranslateAttributesMethod(Object context, CustomScriptConfiguration customScriptConfiguration) {
+ try {
+ log.debug("Executing python 'translateAttributes' method");
+ IdpType idpType = (IdpType) customScriptConfiguration.getExternalType();
+ Map configurationAttributes = customScriptConfiguration.getConfigurationAttributes();
+ return idpType.translateAttributes(context, configurationAttributes);
+ } catch (Exception ex) {
+ log.error(ex.getMessage(), ex);
+ saveScriptError(customScriptConfiguration.getCustomScript(), ex);
+ }
+
+ return false;
+ }
+
+ public boolean executeExternalTranslateAttributesMethod(Object context) {
+ boolean result = true;
+ for (CustomScriptConfiguration customScriptConfiguration : this.customScriptConfigurations) {
+ if (customScriptConfiguration.getExternalType().getApiVersion() > 1) {
+ result &= executeExternalTranslateAttributesMethod(context, customScriptConfiguration);
+ if (!result) {
+ return result;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ // boolean updateAttributes(Object context, Map configurationAttributes);
+
+ public boolean executeExternalUpdateAttributesMethod(Object context, CustomScriptConfiguration customScriptConfiguration) {
+ try {
+ log.debug("Executing python 'updateAttributes' method");
+ IdpType idpType = (IdpType) customScriptConfiguration.getExternalType();
+ Map configurationAttributes = customScriptConfiguration.getConfigurationAttributes();
+ return idpType.updateAttributes(context, configurationAttributes);
+ } catch (Exception ex) {
+ log.error(ex.getMessage(), ex);
+ saveScriptError(customScriptConfiguration.getCustomScript(), ex);
+ }
+
+ return false;
+ }
+
+ public boolean executeExternalUpdateAttributesMethods(Object context) {
+ boolean result = true;
+ for (CustomScriptConfiguration customScriptConfiguration : this.customScriptConfigurations) {
+ if (customScriptConfiguration.getExternalType().getApiVersion() > 1) {
+ result &= executeExternalUpdateAttributesMethod(context, customScriptConfiguration);
+ if (!result) {
+ return result;
+ }
+ }
+ }
+
+ return result;
+ }
+
+}
diff --git a/core-script/src/test/java/org/gluu/service/custom/script/test/StandaloneCustomScriptManagerTest.java b/core-script/src/test/java/org/gluu/service/custom/script/test/StandaloneCustomScriptManagerTest.java
new file mode 100644
index 000000000..2a4b54a57
--- /dev/null
+++ b/core-script/src/test/java/org/gluu/service/custom/script/test/StandaloneCustomScriptManagerTest.java
@@ -0,0 +1,87 @@
+package org.gluu.service.custom.script.test;
+
+import java.util.Properties;
+
+import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.status.StatusLogger;
+import org.gluu.log.LoggingHelper;
+import org.gluu.persist.PersistenceEntryManager;
+import org.gluu.persist.ldap.impl.LdapEntryManager;
+import org.gluu.persist.ldap.impl.LdapEntryManagerFactory;
+import org.gluu.service.custom.script.StandaloneCustomScriptManager;
+
+public class StandaloneCustomScriptManagerTest {
+
+ private static final Logger LOG = Logger.getLogger(StandaloneCustomScriptManagerTest.class);
+
+ static {
+ StatusLogger.getLogger().setLevel(Level.OFF);
+ LoggingHelper.configureConsoleAppender();
+ }
+
+ private static Properties getSampleConnectionProperties() {
+ Properties connectionProperties = new Properties();
+
+ connectionProperties.put("ldap.bindDN", "cn=Directory Manager");
+ connectionProperties.put("ldap.bindPassword", "secret");
+// connectionProperties.put("ldap.bindPassword", "test");
+ connectionProperties.put("ldap.servers", "localhost:1636");
+ connectionProperties.put("ldap.useSSL", "true");
+ connectionProperties.put("ldap.maxconnections", "3");
+
+ return connectionProperties;
+ }
+
+ public static LdapEntryManager createLdapEntryManager() {
+ LdapEntryManagerFactory ldapEntryManagerFactory = new LdapEntryManagerFactory();
+ Properties connectionProperties = getSampleConnectionProperties();
+
+ LdapEntryManager ldapEntryManager = ldapEntryManagerFactory.createEntryManager(connectionProperties);
+ LOG.debug("Created LdapEntryManager: " + ldapEntryManager);
+
+ return ldapEntryManager;
+ }
+
+ public static void main(String[] args) {
+ if (System.getenv("PYTHON_HOME") == null) {
+ System.err.println("PYTHON_HOME environment variable is not defined");
+ System.exit(-1);
+ }
+
+ PersistenceEntryManager persistenceEntryManager = createLdapEntryManager();
+ StandaloneCustomScriptManager customScriptManager = new StandaloneCustomScriptManager(persistenceEntryManager, "ou=scripts,o=gluu", "/opt/gluu/python/libs");
+
+ // Register required external scripts
+ SampleIdpExternalScriptService sampleIdpExternalScriptService = new SampleIdpExternalScriptService();
+ customScriptManager.registerExternalScriptService(sampleIdpExternalScriptService);
+
+ // Init script manager and load scripts
+ customScriptManager.init();
+
+ // Call script
+ Object context = new SampleContext(System.currentTimeMillis());
+ sampleIdpExternalScriptService.executeExternalUpdateAttributesMethods(context);
+
+ // Reload script if needed
+ customScriptManager.reload();
+
+ // Call script
+ Object context2 = new SampleContext(System.currentTimeMillis());
+ sampleIdpExternalScriptService.executeExternalUpdateAttributesMethods(context2);
+
+ // Destroy custom script manager and scripts
+ customScriptManager.destory();
+ }
+
+ private static class SampleContext {
+
+ long time;
+
+ public SampleContext(long time) {
+ super();
+ this.time = time;
+ }
+ }
+
+}
diff --git a/core-standalone/pom.xml b/core-standalone/pom.xml
new file mode 100644
index 000000000..c9b0a9a15
--- /dev/null
+++ b/core-standalone/pom.xml
@@ -0,0 +1,65 @@
+
+
+ 4.0.0
+ org.gluu
+ oxcore-standalone
+ Configuration factories for standalone applications
+
+
+ org.gluu
+ oxcore
+ 4.5.6-SNAPSHOT
+
+
+
+ ${maven.min-version}
+
+
+
+
+
+ src/main/resources
+ true
+
+ **/*.xml
+ **/services/*
+ **/*.properties
+
+
+
+
+
+ src/test/resources
+ true
+
+ **/*.xml
+ **/services/*
+ **/*.properties
+
+
+
+
+
+
+
+ org.gluu
+ gluu-orm-cdi
+
+
+ org.gluu
+ oxcore-cache
+
+
+ org.gluu
+ gluu-orm-standalone
+
+
+
+
+ org.testng
+ testng
+
+
+
+
\ No newline at end of file
diff --git a/core-standalone/src/main/java/org/gluu/conf/model/AppConfiguration.java b/core-standalone/src/main/java/org/gluu/conf/model/AppConfiguration.java
new file mode 100644
index 000000000..c6f8cf764
--- /dev/null
+++ b/core-standalone/src/main/java/org/gluu/conf/model/AppConfiguration.java
@@ -0,0 +1,101 @@
+/*
+ * oxTrust is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
+ *
+ * Copyright (c) 2014, Gluu
+ */
+
+package org.gluu.conf.model;
+
+import java.io.Serializable;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+
+/**
+ * Base application configuration
+ *
+ * @author Yuriy Movchan
+ * @version 0.1, 11/02/2015
+ */
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class AppConfiguration implements Serializable {
+
+ private static final long serialVersionUID = -587414854758989561L;
+
+ private String applicationName;
+ private String openIdProviderUrl;
+ private String openIdClientId;
+ private String openIdClientPassword;
+ private List openIdScopes;
+ private String openIdRedirectUrl;
+
+ private String openIdPostLogoutRedirectUri;
+
+ private List openIdClaimMapping;
+
+ public String getApplicationName() {
+ return applicationName;
+ }
+
+ public void setApplicationName(String applicationName) {
+ this.applicationName = applicationName;
+ }
+
+ public String getOpenIdProviderUrl() {
+ return openIdProviderUrl;
+ }
+
+ public void setOpenIdProviderUrl(String openIdProviderUrl) {
+ this.openIdProviderUrl = openIdProviderUrl;
+ }
+
+ public String getOpenIdClientId() {
+ return openIdClientId;
+ }
+
+ public void setOpenIdClientId(String openIdClientId) {
+ this.openIdClientId = openIdClientId;
+ }
+
+ public String getOpenIdClientPassword() {
+ return openIdClientPassword;
+ }
+
+ public void setOpenIdClientPassword(String openIdClientPassword) {
+ this.openIdClientPassword = openIdClientPassword;
+ }
+
+ public List getOpenIdScopes() {
+ return openIdScopes;
+ }
+
+ public void setOpenIdScopes(List openIdScopes) {
+ this.openIdScopes = openIdScopes;
+ }
+
+ public String getOpenIdRedirectUrl() {
+ return openIdRedirectUrl;
+ }
+
+ public void setOpenIdRedirectUrl(String openIdRedirectUrl) {
+ this.openIdRedirectUrl = openIdRedirectUrl;
+ }
+
+ public List getOpenIdClaimMapping() {
+ return openIdClaimMapping;
+ }
+
+ public void setOpenIdClaimMapping(List openIdClaimMapping) {
+ this.openIdClaimMapping = openIdClaimMapping;
+ }
+
+ public String getOpenIdPostLogoutRedirectUri() {
+ return openIdPostLogoutRedirectUri;
+ }
+
+ public void setOpenIdPostLogoutRedirectUri(String openIdPostLogoutRedirectUri) {
+ this.openIdPostLogoutRedirectUri = openIdPostLogoutRedirectUri;
+ }
+
+}
diff --git a/core-standalone/src/main/java/org/gluu/conf/model/AppConfigurationEntry.java b/core-standalone/src/main/java/org/gluu/conf/model/AppConfigurationEntry.java
new file mode 100644
index 000000000..b183d3e1f
--- /dev/null
+++ b/core-standalone/src/main/java/org/gluu/conf/model/AppConfigurationEntry.java
@@ -0,0 +1,63 @@
+/*
+ * oxTrust is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
+ *
+ * Copyright (c) 2014, Gluu
+ */
+
+package org.gluu.conf.model;
+
+import java.io.Serializable;
+
+import org.gluu.persist.annotation.AttributeName;
+import org.gluu.persist.annotation.DN;
+import org.gluu.persist.annotation.DataEntry;
+import org.gluu.persist.annotation.JsonObject;
+import org.gluu.persist.annotation.ObjectClass;
+
+/**
+ * @author Yuriy Movchan
+ * @version 0.1, 03/25/2016
+ */
+@DataEntry
+@ObjectClass(value = "oxApplicationConfiguration")
+public class AppConfigurationEntry implements Serializable {
+
+ private static final long serialVersionUID = 1847361642302974184L;
+
+ @DN
+ private String dn;
+
+ @AttributeName(name = "oxRevision")
+ private long revision;
+
+ @JsonObject
+ @AttributeName(name = "oxConfApplication")
+ private AppConfiguration application;
+
+ public AppConfigurationEntry() {}
+
+ public String getDn() {
+ return dn;
+ }
+
+ public void setDn(String dn) {
+ this.dn = dn;
+ }
+
+ public long getRevision() {
+ return revision;
+ }
+
+ public void setRevision(long revision) {
+ this.revision = revision;
+ }
+
+ public AppConfiguration getApplication() {
+ return application;
+ }
+
+ public void setApplication(AppConfiguration application) {
+ this.application = application;
+ }
+
+}
diff --git a/core-standalone/src/main/java/org/gluu/conf/model/ClaimToAttributeMapping.java b/core-standalone/src/main/java/org/gluu/conf/model/ClaimToAttributeMapping.java
new file mode 100644
index 000000000..b9f0512d6
--- /dev/null
+++ b/core-standalone/src/main/java/org/gluu/conf/model/ClaimToAttributeMapping.java
@@ -0,0 +1,53 @@
+/*
+ * oxTrust is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
+ *
+ * Copyright (c) 2014, Gluu
+ */
+
+/**
+ * CAS oxAuth application configuration
+ *
+ * @author Yuriy Movchan
+ * @version 0.1, 03/25/2016
+ */
+package org.gluu.conf.model;
+
+import java.io.Serializable;
+
+/**
+ * Claim to attribute mapping
+ *
+ * @author Yuriy Movchan
+ * @version 0.1, 03/25/2016
+ */
+public class ClaimToAttributeMapping implements Serializable {
+
+ private static final long serialVersionUID = 3450326508968717097L;
+
+ private String claim;
+ private String attribute;
+
+ public String getClaim() {
+ return claim;
+ }
+
+ public void setClaim(String claim) {
+ this.claim = claim;
+ }
+
+ public String getAttribute() {
+ return attribute;
+ }
+
+ public void setAttribute(String attribute) {
+ this.attribute = attribute;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("ClaimToAttributeMapping [claim=").append(claim).append(", attribute=").append(attribute).append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/core-standalone/src/main/java/org/gluu/conf/model/SharedConfigurationEntry.java b/core-standalone/src/main/java/org/gluu/conf/model/SharedConfigurationEntry.java
new file mode 100644
index 000000000..77956a2b5
--- /dev/null
+++ b/core-standalone/src/main/java/org/gluu/conf/model/SharedConfigurationEntry.java
@@ -0,0 +1,125 @@
+/*
+ * oxTrust is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
+ *
+ * Copyright (c) 2014, Gluu
+ */
+
+package org.gluu.conf.model;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import org.gluu.model.SmtpConfiguration;
+import org.gluu.persist.annotation.AttributeName;
+import org.gluu.persist.annotation.CustomObjectClass;
+import org.gluu.persist.annotation.DataEntry;
+import org.gluu.persist.annotation.JsonObject;
+import org.gluu.persist.annotation.ObjectClass;
+import org.gluu.persist.model.base.InumEntry;
+import org.gluu.service.cache.CacheConfiguration;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+/**
+ * GluuConfiguration
+ *
+ * @author Yuriy Movchan Date: 01/21/2020
+ */
+@DataEntry
+@ObjectClass(value = "gluuConfiguration")
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class SharedConfigurationEntry extends InumEntry implements Serializable {
+
+ private static final long serialVersionUID = -1817003894646725601L;
+
+ @AttributeName
+ private String description;
+
+ @AttributeName
+ private String displayName;
+
+ @AttributeName(name = "gluuLastUpdate", updateOnly = true)
+ private Date lastUpdate;
+
+ @AttributeName(name = "gluuConfigurationPollingInterval")
+ private String pollingInterval;
+
+ @AttributeName(name = "oxTrustEmail")
+ private String contactEmail;
+
+ @AttributeName(name = "oxSmtpConfiguration")
+ @JsonObject
+ private SmtpConfiguration smtpConfiguration;
+
+ @AttributeName(name = "oxCacheConfiguration")
+ @JsonObject
+ private CacheConfiguration cacheConfiguration;
+
+ @CustomObjectClass
+ private String[] customObjectClasses;
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public void setDisplayName(String displayName) {
+ this.displayName = displayName;
+ }
+
+ public Date getLastUpdate() {
+ return lastUpdate;
+ }
+
+ public void setLastUpdate(Date lastUpdate) {
+ this.lastUpdate = lastUpdate;
+ }
+
+ public String getPollingInterval() {
+ return pollingInterval;
+ }
+
+ public void setPollingInterval(String pollingInterval) {
+ this.pollingInterval = pollingInterval;
+ }
+
+ public String getContactEmail() {
+ return contactEmail;
+ }
+
+ public void setContactEmail(String contactEmail) {
+ this.contactEmail = contactEmail;
+ }
+
+ public SmtpConfiguration getSmtpConfiguration() {
+ return smtpConfiguration;
+ }
+
+ public void setSmtpConfiguration(SmtpConfiguration smtpConfiguration) {
+ this.smtpConfiguration = smtpConfiguration;
+ }
+
+ public CacheConfiguration getCacheConfiguration() {
+ return cacheConfiguration;
+ }
+
+ public void setCacheConfiguration(CacheConfiguration cacheConfiguration) {
+ this.cacheConfiguration = cacheConfiguration;
+ }
+
+ public String[] getCustomObjectClasses() {
+ return customObjectClasses;
+ }
+
+ public void setCustomObjectClasses(String[] customObjectClasses) {
+ this.customObjectClasses = customObjectClasses;
+ }
+
+}
\ No newline at end of file
diff --git a/core-standalone/src/main/java/org/gluu/conf/service/ConfigurationFactory.java b/core-standalone/src/main/java/org/gluu/conf/service/ConfigurationFactory.java
new file mode 100644
index 000000000..f1e75507c
--- /dev/null
+++ b/core-standalone/src/main/java/org/gluu/conf/service/ConfigurationFactory.java
@@ -0,0 +1,322 @@
+/*
+ * oxTrust is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
+ *
+ * Copyright (c) 2014, Gluu
+ */
+
+package org.gluu.conf.service;
+
+import java.io.File;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.commons.lang.StringUtils;
+import org.gluu.conf.model.AppConfiguration;
+import org.gluu.conf.model.AppConfigurationEntry;
+import org.gluu.conf.model.SharedConfigurationEntry;
+import org.gluu.persist.PersistenceEntryManager;
+import org.gluu.persist.PersistenceEntryManagerFactory;
+import org.gluu.persist.exception.BasePersistenceException;
+import org.gluu.persist.model.PersistenceConfiguration;
+import org.gluu.persist.service.PersistanceFactoryService;
+import org.gluu.persist.service.StandalonePersistanceFactoryService;
+import org.gluu.service.cache.CacheConfiguration;
+import org.gluu.service.cache.InMemoryConfiguration;
+import org.gluu.util.StringHelper;
+import org.gluu.util.exception.ConfigurationException;
+import org.gluu.orm.util.properties.FileConfiguration;
+import org.gluu.util.security.PropertiesDecrypter;
+import org.gluu.util.security.StringEncrypter;
+import org.gluu.util.security.StringEncrypter.EncryptionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Base OpenId configuration
+ *
+ * @author Yuriy Movchan
+ * @version 0.1, 11/02/2015
+ */
+public abstract class ConfigurationFactory {
+
+ private final Logger LOG = LoggerFactory.getLogger(ConfigurationFactory.class);
+
+ static {
+ if (System.getProperty("gluu.base") != null) {
+ BASE_DIR = System.getProperty("gluu.base");
+ } else if ((System.getProperty("catalina.base") != null) && (System.getProperty("catalina.base.ignore") == null)) {
+ BASE_DIR = System.getProperty("catalina.base");
+ } else if (System.getProperty("catalina.home") != null) {
+ BASE_DIR = System.getProperty("catalina.home");
+ } else if (System.getProperty("jboss.home.dir") != null) {
+ BASE_DIR = System.getProperty("jboss.home.dir");
+ } else {
+ BASE_DIR = null;
+ }
+ }
+
+ public static final String BASE_DIR;
+ public static final String DIR = BASE_DIR + File.separator + "conf" + File.separator;
+
+ private static final String BASE_PROPERTIES_FILE = DIR + "gluu.properties";
+ public static final String DEFAULT_PROPERTIES_FILE = DIR + "openid.properties";
+
+ private static final String SALT_FILE_NAME = "salt";
+
+ private static final String SHARED_CONFIGURATION_DN = "ou=configuration,o=gluu";
+
+ private String confDir, saltFilePath;
+
+ private FileConfiguration baseConfiguration;
+
+ private C appConfiguration;
+
+ private PersistanceFactoryService persistanceFactoryService;
+ private PersistenceConfiguration persistenceConfiguration;
+
+ private String cryptoConfigurationSalt;
+ private StringEncrypter stringEncrypter;
+
+ private PersistenceEntryManager persistenceEntryManager;
+
+ private CacheConfiguration cacheConfiguration;
+
+ @SuppressWarnings("unused")
+ private long baseConfigurationFileLastModifiedTime;
+
+ private boolean loaded = false;
+ private long loadedRevision = -1;
+
+ private AtomicBoolean isActive;
+
+ protected ConfigurationFactory() {
+ this.isActive = new AtomicBoolean(true);
+ try {
+ create();
+ } finally {
+ this.isActive.set(false);
+ }
+ }
+
+ private void create() {
+ this.persistanceFactoryService = new StandalonePersistanceFactoryService();
+
+ this.persistenceConfiguration = persistanceFactoryService.loadPersistenceConfiguration(getDefaultConfigurationFileName());
+ this.baseConfiguration = loadBaseConfiguration();
+
+ this.confDir = confDir();
+ this.saltFilePath = confDir + SALT_FILE_NAME;
+
+ this.cryptoConfigurationSalt = loadCryptoConfigurationSalt();
+ this.stringEncrypter = createStringEncrypter();
+
+ this.persistenceEntryManager = createPersistenceEntryManager();
+
+ if (!createFromDb()) {
+ LOG.error("Failed to load configuration from DB. Please fix it!!!.");
+ throw new ConfigurationException("Failed to load configuration from DB.");
+ } else {
+ this.loaded = true;
+ LOG.info("Configuration loaded successfully.");
+ }
+
+ this.cacheConfiguration = loadCacheConfiguration();
+ }
+
+ public void destroy() {
+ if (this.persistenceEntryManager != null) {
+ destroyPersistenceEntryManager(this.persistenceEntryManager);
+ }
+ }
+
+ private FileConfiguration createFileConfiguration(String fileName, boolean isMandatory) {
+ try {
+ FileConfiguration fileConfiguration = new FileConfiguration(fileName);
+
+ return fileConfiguration;
+ } catch (Exception ex) {
+ if (isMandatory) {
+ LOG.error("Failed to load configuration from {}", fileName, ex);
+ throw new ConfigurationException("Failed to load configuration from " + fileName, ex);
+ }
+ }
+
+ return null;
+ }
+
+ private FileConfiguration loadBaseConfiguration() {
+ FileConfiguration fileConfiguration = createFileConfiguration(BASE_PROPERTIES_FILE, true);
+
+ return fileConfiguration;
+ }
+
+ private String loadCryptoConfigurationSalt() {
+ try {
+ FileConfiguration cryptoConfiguration = new FileConfiguration(this.saltFilePath);
+
+ return cryptoConfiguration.getString("encodeSalt");
+ } catch (Exception ex) {
+ LOG.error("Failed to load configuration from {}", saltFilePath, ex);
+ throw new ConfigurationException("Failed to load configuration from " + saltFilePath, ex);
+ }
+ }
+
+ private CacheConfiguration loadCacheConfiguration() {
+ SharedConfigurationEntry sharedConfigurationEntry = persistenceEntryManager.find(SharedConfigurationEntry.class, SHARED_CONFIGURATION_DN);
+ if (sharedConfigurationEntry == null) {
+ LOG.error("Failed to load share configuration from DB. Please fix it!!!.");
+ throw new ConfigurationException("Failed to load shared configuration from DB.");
+ }
+
+ CacheConfiguration cacheConfiguration = sharedConfigurationEntry.getCacheConfiguration();
+ if (cacheConfiguration == null || cacheConfiguration.getCacheProviderType() == null) {
+ LOG.error("Failed to read cache configuration from DB. Please check configuration oxCacheConfiguration attribute " +
+ "that must contain cache configuration JSON represented by CacheConfiguration.class. Shared configuration DN: " + SHARED_CONFIGURATION_DN);
+ LOG.info("Creating fallback IN-MEMORY cache configuration ... ");
+
+ cacheConfiguration = new CacheConfiguration();
+ cacheConfiguration.setInMemoryConfiguration(new InMemoryConfiguration());
+
+ LOG.info("IN-MEMORY cache configuration is created.");
+ }
+ LOG.info("Cache configuration: " + cacheConfiguration);
+
+ return cacheConfiguration;
+ }
+
+ private String confDir() {
+ final String confDir = getPersistenceConfiguration().getString("confDir");
+ if (StringUtils.isNotBlank(confDir)) {
+ return confDir;
+ }
+
+ return DIR;
+ }
+
+ private boolean createFromDb() {
+ LOG.info("Loading configuration from '{}' DB...", baseConfiguration.getString("persistence.type"));
+ try {
+ final L persistenceConf = loadConfigurationFromDb();
+ this.loadedRevision = persistenceConf.getRevision();
+ if (persistenceConf != null) {
+ this.appConfiguration = (C) persistenceConf.getApplication();
+ return true;
+ }
+ } catch (Exception ex) {
+ LOG.error(ex.getMessage(), ex);
+ }
+
+ return false;
+ }
+
+ private L loadConfigurationFromDb(String... returnAttributes) {
+ try {
+ final String dn = baseConfiguration.getString(getApplicationConfigurationPropertyName());
+
+ final L persistanceConf = this.persistenceEntryManager.find(dn, getAppConfigurationType(), returnAttributes);
+ return persistanceConf;
+ } catch (BasePersistenceException ex) {
+ LOG.error(ex.getMessage());
+ }
+
+ return null;
+ }
+
+ protected Properties preparePersistanceProperties() {
+ FileConfiguration persistenceConfig = persistenceConfiguration.getConfiguration();
+ Properties connectionProperties = (Properties) persistenceConfig.getProperties();
+
+ Properties decryptedConnectionProperties;
+ try {
+ decryptedConnectionProperties = PropertiesDecrypter.decryptAllProperties(StringEncrypter.defaultInstance(), connectionProperties, this.cryptoConfigurationSalt);
+ } catch (EncryptionException ex) {
+ throw new ConfigurationException("Failed to decript configuration properties", ex);
+ }
+
+ return decryptedConnectionProperties;
+ }
+
+ private PersistenceEntryManager createPersistenceEntryManager() {
+ Properties connectionProperties = preparePersistanceProperties();
+
+ PersistenceEntryManagerFactory persistenceEntryManagerFactory = persistanceFactoryService.getPersistenceEntryManagerFactory(persistenceConfiguration);
+ PersistenceEntryManager persistenceEntryManager = persistenceEntryManagerFactory.createEntryManager(connectionProperties);
+ LOG.info("Created PersistenceEntryManager: {} with operation service: {}",
+ new Object[] {persistenceEntryManager,
+ persistenceEntryManager.getOperationService() });
+
+ return persistenceEntryManager;
+ }
+
+ private void destroyPersistenceEntryManager(final PersistenceEntryManager persistenceEntryManager) {
+ boolean result = persistenceEntryManager.destroy();
+ if (result) {
+ LOG.debug("Destoyed PersistenceEntryManager: {}", persistenceEntryManager);
+ } else {
+ LOG.error("Failed to destoy PersistenceEntryManager: {}", persistenceEntryManager);
+ }
+ }
+
+ private StringEncrypter createStringEncrypter() {
+ String encodeSalt = this.cryptoConfigurationSalt;
+
+ if (StringHelper.isEmpty(encodeSalt)) {
+ throw new ConfigurationException("Encode salt isn't defined");
+ }
+
+ try {
+ StringEncrypter stringEncrypter = StringEncrypter.instance(encodeSalt);
+
+ return stringEncrypter;
+ } catch (EncryptionException ex) {
+ throw new ConfigurationException("Failed to create StringEncrypter instance");
+ }
+ }
+
+ public StringEncrypter getStringEncrypter() {
+ return stringEncrypter;
+ }
+
+ public FileConfiguration getPersistenceConfiguration() {
+ return this.persistenceConfiguration.getConfiguration();
+ }
+
+ public FileConfiguration getBaseConfiguration() {
+ return baseConfiguration;
+ }
+
+ public String getCryptoConfigurationSalt() {
+ return cryptoConfigurationSalt;
+ }
+
+ public PersistenceEntryManager getPersistenceEntryManager() {
+ return persistenceEntryManager;
+ }
+
+ protected String getDefaultPersistanceConfigurationFileName() {
+ return "gluu-ldap.properties";
+ }
+
+ public C getAppConfiguration() {
+ return appConfiguration;
+ }
+
+ public CacheConfiguration getCacheConfiguration() {
+ return cacheConfiguration;
+ }
+
+ public boolean isLoaded() {
+ return loaded;
+ }
+
+ public long getLoadedRevision() {
+ return loadedRevision;
+ }
+
+ protected abstract String getDefaultConfigurationFileName();
+
+ protected abstract Class getAppConfigurationType();
+
+ protected abstract String getApplicationConfigurationPropertyName();
+
+}
diff --git a/core-standalone/src/test/java/org/gluu/conf/service/DummyConfigurationFactory.java b/core-standalone/src/test/java/org/gluu/conf/service/DummyConfigurationFactory.java
new file mode 100644
index 000000000..2c981e073
--- /dev/null
+++ b/core-standalone/src/test/java/org/gluu/conf/service/DummyConfigurationFactory.java
@@ -0,0 +1,27 @@
+package org.gluu.conf.service;
+
+import org.gluu.conf.model.AppConfiguration;
+import org.gluu.conf.model.AppConfigurationEntry;
+
+/**
+ * @author Yuriy Movchan
+ * @version 0.1, 01/02/2020
+ */
+public class DummyConfigurationFactory extends ConfigurationFactory {
+
+ @Override
+ protected String getDefaultConfigurationFileName() {
+ return "gluu-dummy.properties";
+ }
+
+ @Override
+ protected Class getAppConfigurationType() {
+ return AppConfigurationEntry.class;
+ }
+
+ @Override
+ protected String getApplicationConfigurationPropertyName() {
+ return "oxdummyConfigurationEntryDN";
+ }
+
+}
diff --git a/core-standalone/src/test/java/org/gluu/conf/service/DummyConfigurationFactoryTest.java b/core-standalone/src/test/java/org/gluu/conf/service/DummyConfigurationFactoryTest.java
new file mode 100644
index 000000000..7e0cbc363
--- /dev/null
+++ b/core-standalone/src/test/java/org/gluu/conf/service/DummyConfigurationFactoryTest.java
@@ -0,0 +1,34 @@
+package org.gluu.conf.service;
+
+import static org.testng.Assert.assertNotNull;
+
+import org.gluu.service.cache.CacheConfiguration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/**
+ * @author Yuriy Movchan
+ * @version 0.1, 01/02/2020
+ */
+public class DummyConfigurationFactoryTest {
+
+ private DummyConfigurationFactory dummyConfigurationFactory;
+
+ @BeforeClass
+ public void beforeClass() {
+ this.dummyConfigurationFactory = new DummyConfigurationFactory();
+ }
+
+ @Test(enabled = false)
+ public void checkAppConfigurationLoad() {
+ assertNotNull(dummyConfigurationFactory.getAppConfiguration());
+ }
+
+ @Test(enabled = false)
+ public void checkCacheConfiguration() {
+ CacheConfiguration cacheConfiguration = dummyConfigurationFactory.getCacheConfiguration();
+ assertNotNull(cacheConfiguration);
+ assertNotNull(cacheConfiguration.getCacheProviderType());
+ }
+
+}
diff --git a/core-timer-weld/pom.xml b/core-timer-weld/pom.xml
new file mode 100644
index 000000000..e5ab68787
--- /dev/null
+++ b/core-timer-weld/pom.xml
@@ -0,0 +1,76 @@
+
+
+ 4.0.0
+ oxcore-timer-weld
+ Weld CDI timer implementation
+
+
+ org.gluu
+ oxcore
+ 4.5.6-SNAPSHOT
+
+
+
+ ${maven.min-version}
+
+
+
+
+
+ src/main/resources
+ true
+
+ **/*.xml
+ **/services/*
+ **/*.properties
+
+
+
+
+
+
+
+
+ ${project.groupId}
+ oxcore-cdi
+
+
+ ${project.groupId}
+ oxcore-util
+
+
+
+
+ org.slf4j
+ slf4j-api
+ provided
+
+
+
+
+ javax.enterprise
+ cdi-api
+ provided
+
+
+ org.jboss.spec.javax.annotation
+ jboss-annotations-api_1.2_spec
+ provided
+
+
+
+
+ org.jboss.weld
+ weld-core-impl
+ provided
+
+
+
+
+ org.quartz-scheduler
+ quartz
+
+
+
+
\ No newline at end of file
diff --git a/oxService/src/main/java/org/gluu/service/timer/JobExecutionDelegate.java b/core-timer-weld/src/main/java/org/gluu/service/timer/JobExecutionDelegate.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/service/timer/JobExecutionDelegate.java
rename to core-timer-weld/src/main/java/org/gluu/service/timer/JobExecutionDelegate.java
diff --git a/oxService/src/main/java/org/gluu/service/timer/JobExecutionFactory.java b/core-timer-weld/src/main/java/org/gluu/service/timer/JobExecutionFactory.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/service/timer/JobExecutionFactory.java
rename to core-timer-weld/src/main/java/org/gluu/service/timer/JobExecutionFactory.java
diff --git a/oxService/src/main/java/org/gluu/service/timer/QuartzSchedulerManager.java b/core-timer-weld/src/main/java/org/gluu/service/timer/QuartzSchedulerManager.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/service/timer/QuartzSchedulerManager.java
rename to core-timer-weld/src/main/java/org/gluu/service/timer/QuartzSchedulerManager.java
diff --git a/oxService/src/main/java/org/gluu/service/timer/RequestJobListener.java b/core-timer-weld/src/main/java/org/gluu/service/timer/RequestJobListener.java
similarity index 100%
rename from oxService/src/main/java/org/gluu/service/timer/RequestJobListener.java
rename to core-timer-weld/src/main/java/org/gluu/service/timer/RequestJobListener.java
diff --git a/oxService/src/main/java/org/gluu/service/timer/TimerJob.java b/core-timer-weld/src/main/java/org/gluu/service/timer/TimerJob.java
similarity index 95%
rename from oxService/src/main/java/org/gluu/service/timer/TimerJob.java
rename to core-timer-weld/src/main/java/org/gluu/service/timer/TimerJob.java
index db7ba9ee2..2f6b84642 100644
--- a/oxService/src/main/java/org/gluu/service/timer/TimerJob.java
+++ b/core-timer-weld/src/main/java/org/gluu/service/timer/TimerJob.java
@@ -32,10 +32,8 @@ public void execute(JobExecutionContext context) throws JobExecutionException {
if (timerEvent == null) {
return;
}
-
- log.debug("Fire timer event [{}] with qualifiers {} from instance {}", timerEvent.getTargetEvent().getClass().getName(),
+ log.trace("Fire timer event [{}] with qualifiers {} from instance {}", timerEvent.getTargetEvent().getClass().getName(),
timerEvent.getQualifiers(), System.identityHashCode(this));
-
beanManager.fireEvent(timerEvent.getTargetEvent(), timerEvent.getQualifiers());
} catch (Exception ex) {
throw new JobExecutionException(ex);
diff --git a/core-timer-weld/src/main/resources/META-INF/beans.xml b/core-timer-weld/src/main/resources/META-INF/beans.xml
new file mode 100644
index 000000000..2f4f7e279
--- /dev/null
+++ b/core-timer-weld/src/main/resources/META-INF/beans.xml
@@ -0,0 +1,7 @@
+
+
+
diff --git a/demo-cdi/pom.xml b/demo-cdi/pom.xml
index fcd65af09..d868e7667 100644
--- a/demo-cdi/pom.xml
+++ b/demo-cdi/pom.xml
@@ -2,14 +2,13 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
- org.gluu
oxcore-demo-cdi
Demo CDI services
org.gluu
oxcore
- 4.0.0-SNAPSHOT
+ 4.5.6-SNAPSHOT
@@ -45,11 +44,10 @@
provided
-
+
org.jboss.resteasy
- resteasy-jaxrs
- provided
+ resteasy-cdi
diff --git a/doc/pom.xml b/doc/pom.xml
new file mode 100644
index 000000000..c88fa3e99
--- /dev/null
+++ b/doc/pom.xml
@@ -0,0 +1,15 @@
+
+
+ org.gluu
+ oxcore
+ 4.5.6-SNAPSHOT
+
+
+ 4.0.0
+ gluu-doc
+ jar
+ gluu-doc
+
+
+
diff --git a/doc/src/main/java/org/gluu/doc/annotation/DocFeatureFlag.java b/doc/src/main/java/org/gluu/doc/annotation/DocFeatureFlag.java
new file mode 100644
index 000000000..613fde79f
--- /dev/null
+++ b/doc/src/main/java/org/gluu/doc/annotation/DocFeatureFlag.java
@@ -0,0 +1,16 @@
+package org.gluu.doc.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.SOURCE)
+public @interface DocFeatureFlag {
+ String description();
+
+ boolean isRequired() default false;
+
+ String defaultValue();
+}
diff --git a/doc/src/main/java/org/gluu/doc/annotation/DocFeatureFlagProcessor.java b/doc/src/main/java/org/gluu/doc/annotation/DocFeatureFlagProcessor.java
new file mode 100644
index 000000000..f9c401965
--- /dev/null
+++ b/doc/src/main/java/org/gluu/doc/annotation/DocFeatureFlagProcessor.java
@@ -0,0 +1,112 @@
+package org.gluu.doc.annotation;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedOptions;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+@SupportedAnnotationTypes("org.gluu.doc.annotation.DocFeatureFlag")
+@SupportedOptions({"module"})
+public class DocFeatureFlagProcessor extends AbstractProcessor {
+
+ String moduleName;
+ @Override
+ public boolean process(Set extends TypeElement> annotations, RoundEnvironment env) {
+
+ moduleName = processingEnv.getOptions().get("module");
+
+ for (TypeElement annotation : annotations) {
+ Set extends Element> annotatedElements = env.getElementsAnnotatedWith(annotation);
+
+ // sort alphabetically
+ List extends Element> sortedElements = annotatedElements.stream()
+ .sorted((prop1, prop2)->prop1.getSimpleName().toString().toLowerCase().compareTo(prop2.getSimpleName().toString().toLowerCase()))
+ .collect(Collectors.toList());
+
+ StringBuilder docContents = new StringBuilder();
+ StringBuilder tableContents = new StringBuilder();
+ StringBuilder detailsContent = new StringBuilder();
+
+ // prepare document header
+ prepareDocTagsAndTableHeader(docContents, tableContents);
+
+ // for each feature flag add a row in table and add content for the details section
+ for (Element element : sortedElements)
+ {
+ DocFeatureFlag elementAnnotation = element.getAnnotation(DocFeatureFlag.class);
+ addToTable(tableContents, element, elementAnnotation);
+ addToDetails(detailsContent, element, elementAnnotation);
+ }
+ tableContents.append("\n\n");
+ createAndWriteDoc(docContents.append((tableContents.append(detailsContent.toString()))));
+
+ }
+ return false;
+ }
+
+ private void prepareDocTagsAndTableHeader(StringBuilder docContents, StringBuilder tableContents) {
+ // add tags
+ docContents.append("---\n")
+ .append("tags:\n")
+ .append("- administration\n")
+ .append("- reference\n")
+ .append("- json\n")
+ .append("- feature-flags\n")
+ .append("---\n")
+ .append("\n")
+ .append("# "+moduleName+" Feature Flags") // add doc header
+ .append("\n")
+ .append("\n");
+
+ tableContents.append("| Feature Flag Name ") // prepare table header
+ .append("| Description ")
+ .append("| | ")
+ .append("\n")
+ .append("|-----|-----|-----|")
+ .append("\n");
+ }
+
+ private void createAndWriteDoc(StringBuilder docContent) {
+
+ FileObject docFile = null;
+ try{
+ docFile = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", moduleName.toLowerCase().replaceAll("\\s", "")+"-feature-flags.md");
+ }
+ catch (IOException ioe){
+ processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, this.getClass().getName()+": Error occurred while creating annotation documentation file");
+ }
+ if(docFile!=null){
+ try(PrintWriter docWriter = new PrintWriter(docFile.openWriter());) {
+ docWriter.write(docContent.toString());
+ docWriter.flush();
+ } catch (IOException e) {
+ processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, this.getClass().getName()+": Error occurred while writing annotation documentation file");
+ }
+ }
+ }
+
+ private static void addToDetails(StringBuilder propDetails, Element jansElement, DocFeatureFlag featureFlagAnnotation) {
+ propDetails.append("### "+ jansElement.getSimpleName()+"\n\n");
+ propDetails.append("- Description: "+ featureFlagAnnotation.description()+"\n\n");
+ propDetails.append("- Required: "+ (featureFlagAnnotation.isRequired()?"Yes":"No")+"\n\n");
+ propDetails.append("- Default value: "+ featureFlagAnnotation.defaultValue()+"\n\n");
+ propDetails.append("\n");
+ }
+
+ private static void addToTable(StringBuilder propTable, Element jansElement, DocFeatureFlag featureFlagAnnotation) {
+ propTable.append("| "+ jansElement.getSimpleName()+" ");
+ propTable.append("| "+ featureFlagAnnotation.description()+" ");
+ propTable.append("| [Details](#"+jansElement.getSimpleName().toString().toLowerCase()+") |");
+ propTable.append("\n");
+ }
+}
diff --git a/doc/src/main/java/org/gluu/doc/annotation/DocProperty.java b/doc/src/main/java/org/gluu/doc/annotation/DocProperty.java
new file mode 100644
index 000000000..e2126c860
--- /dev/null
+++ b/doc/src/main/java/org/gluu/doc/annotation/DocProperty.java
@@ -0,0 +1,16 @@
+package org.gluu.doc.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.SOURCE)
+public @interface DocProperty {
+ String description() default "None";
+
+ boolean isRequired() default false;
+
+ String defaultValue() default "None";
+}
diff --git a/doc/src/main/java/org/gluu/doc/annotation/DocPropertyProcessor.java b/doc/src/main/java/org/gluu/doc/annotation/DocPropertyProcessor.java
new file mode 100644
index 000000000..614703b22
--- /dev/null
+++ b/doc/src/main/java/org/gluu/doc/annotation/DocPropertyProcessor.java
@@ -0,0 +1,120 @@
+package org.gluu.doc.annotation;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedOptions;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+@SupportedAnnotationTypes("org.gluu.doc.annotation.DocProperty")
+@SupportedOptions({"module"})
+public class DocPropertyProcessor extends AbstractProcessor {
+
+ String moduleName;
+
+ // This method would be called once per class containing annotated elements
+ @Override
+ public boolean process(Set extends TypeElement> annotations, RoundEnvironment env) {
+
+ moduleName = processingEnv.getOptions().get("module");
+
+ // Loop iterates once per supported annotation type by this processor
+ for (TypeElement annotation : annotations) {
+
+ // Get all the elements that are annotated by a particular annotation located across classes in this module
+ Set extends Element> annotatedProperties = env.getElementsAnnotatedWith(annotation);
+
+ // sort alphabetically
+ List extends Element> sortedProperties = annotatedProperties.stream()
+ .sorted((prop1, prop2)->prop1.getSimpleName().toString().toLowerCase().compareTo(prop2.getSimpleName().toString().toLowerCase()))
+ .collect(Collectors.toList());
+
+ StringBuilder docContents = new StringBuilder();
+ StringBuilder tableContents = new StringBuilder();
+ StringBuilder detailsContent = new StringBuilder();
+
+ // prepare document header
+ prepareDocTagsAndTableHeader(docContents, tableContents);
+
+ // for each property add a row in table and add content for the details section
+ for (Element jansProperty : sortedProperties)
+ {
+ DocProperty propertyAnnotation = jansProperty.getAnnotation(DocProperty.class);
+ addToTable(tableContents, jansProperty, propertyAnnotation);
+ addToDetails(detailsContent, jansProperty, propertyAnnotation);
+ }
+ tableContents.append("\n\n");
+ docContents.append((tableContents.append(detailsContent.toString())));
+ createAndWriteDoc(docContents);
+
+ }
+ return false;
+ }
+
+ private void prepareDocTagsAndTableHeader(StringBuilder docContents, StringBuilder tableContents) {
+
+ // add tags
+ docContents.append("---\n")
+ .append("tags:\n")
+ .append("- administration\n")
+ .append("- reference\n")
+ .append("- json\n")
+ .append("- properties\n")
+ .append("---\n")
+ .append("\n")
+ .append("# "+moduleName+" Configuration Properties") // add doc headers
+ .append("\n")
+ .append("\n");
+
+ tableContents.append("| Property Name ") // prepare table header
+ .append("| Description ")
+ .append("| | ")
+ .append("\n")
+ .append("|-----|-----|-----|")
+ .append("\n");
+ }
+
+ private void createAndWriteDoc(StringBuilder docContent) {
+
+ FileObject docFile = null;
+ try{
+ docFile = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", moduleName.toLowerCase().replaceAll("\\s", "")+"-properties.md");
+ }
+ catch (IOException ioe){
+ processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, this.getClass().getName()+": Error occurred while creating annotation documentation file");
+ }
+ if(docFile!=null){
+ try(PrintWriter docWriter = new PrintWriter(docFile.openWriter());) {
+ docWriter.write(docContent.toString());
+ docWriter.flush();
+ } catch (IOException e) {
+ processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, this.getClass().getName()+": Error occurred while writing annotation documentation file");
+ }
+ }
+
+ }
+
+ private static void addToDetails(StringBuilder propDetails, Element jansProperty, DocProperty propertyAnnotation) {
+ propDetails.append("### "+ jansProperty.getSimpleName()+"\n\n");
+ propDetails.append("- Description: "+ propertyAnnotation.description()+"\n\n");
+ propDetails.append("- Required: "+ (propertyAnnotation.isRequired()?"Yes":"No")+"\n\n");
+ propDetails.append("- Default value: "+ propertyAnnotation.defaultValue()+"\n\n");
+ propDetails.append("\n");
+ }
+
+ private static void addToTable(StringBuilder propTable, Element jansProperty, DocProperty propertyAnnotation) {
+ propTable.append("| "+ jansProperty.getSimpleName()+" ");
+ propTable.append("| "+ propertyAnnotation.description()+" ");
+ propTable.append("| [Details](#"+jansProperty.getSimpleName().toString().toLowerCase()+") |");
+ propTable.append("\n");
+ }
+}
diff --git a/exception-extension-cdi/pom.xml b/exception-extension-cdi/pom.xml
new file mode 100644
index 000000000..f0168b1c3
--- /dev/null
+++ b/exception-extension-cdi/pom.xml
@@ -0,0 +1,53 @@
+
+
+ 4.0.0
+ exception-extension-cdi
+ Reusable CDI exception handler extension
+
+
+ org.gluu
+ oxcore
+ 4.5.6-SNAPSHOT
+
+
+
+ ${maven.min-version}
+
+
+
+
+
+ src/main/resources
+ true
+
+