keycloak-aplcache
Changes
audit/jboss-logging/src/main/java/org/keycloak/audit/log/JBossLoggingAuditListenerFactory.java 9(+2 -7)
authentication/authentication-api/src/main/java/org/keycloak/authentication/AuthenticationSpi.java 27(+27 -0)
authentication/authentication-api/src/main/resources/META-INF/services/org.keycloak.provider.Spi 1(+1 -0)
authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ExternalModelAuthenticationProviderFactory.java 8(+2 -6)
authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ModelAuthenticationProviderFactory.java 7(+2 -5)
authentication/authentication-picketlink/src/main/java/org/keycloak/authentication/picketlink/PicketlinkAuthenticationProvider.java 15(+6 -9)
authentication/authentication-picketlink/src/main/java/org/keycloak/authentication/picketlink/PicketlinkAuthenticationProviderFactory.java 7(+2 -5)
core/src/main/java/org/keycloak/Config.java 129(+129 -0)
export-import/export-import-api/src/main/java/org/keycloak/exportimport/ExportImportProvider.java 5(+3 -2)
export-import/export-import-impl/pom.xml 31(+15 -16)
export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ExportImportConfig.java 54(+54 -0)
export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ExportImportProviderImpl.java 15(+8 -7)
export-import/export-import-impl/src/main/java/org/keycloak/exportimport/io/directory/TmpDirExportImportIOProvider.java 10(+5 -5)
export-import/export-import-impl/src/main/java/org/keycloak/exportimport/io/zip/EncryptedZIPIOProvider.java 10(+5 -5)
export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelImporter.java 2(+1 -1)
export-import/export-import-impl/src/test/java/org/keycloak/exportimport/ExportImportTestBase.java 34(+21 -13)
export-import/export-import-impl/src/test/java/org/keycloak/exportimport/JPAToMongoExportImportTest.java 15(+7 -8)
export-import/export-import-impl/src/test/java/org/keycloak/exportimport/MongoToJPAExportImportTest.java 29(+14 -15)
model/jpa/pom.xml 18(+0 -18)
model/mongo/pom.xml 30(+9 -21)
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoKeycloakSessionFactory.java 55(+46 -9)
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/config/MongoClientProvider.java 21(+0 -21)
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/config/MongoClientProviderHolder.java 20(+0 -20)
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/config/SystemPropertiesMongoClientProvider.java 104(+0 -104)
model/mongo/src/main/resources/META-INF/services/org.keycloak.models.KeycloakSessionFactory 1(+1 -0)
picketlink/keycloak-picketlink-api/src/main/java/org/keycloak/picketlink/IdentityManagerSpi.java 25(+25 -0)
picketlink/keycloak-picketlink-api/src/main/resources/META-INF/services/org.keycloak.provider.Spi 1(+1 -0)
picketlink/keycloak-picketlink-realm/src/main/java/org/keycloak/picketlink/realm/RealmIdentityManagerProviderFactory.java 7(+2 -5)
project-integrations/aerogear-ups/auth-server/src/main/java/org/aerogear/ups/security/UpsSecurityApplication.java 6(+4 -2)
server/pom.xml 33(+33 -0)
services/pom.xml 1(+1 -0)
testsuite/integration/pom.xml 27(+14 -13)
testsuite/integration/README.md 6(+3 -3)
testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java 31(+17 -14)
Details
diff --git a/audit/api/src/main/java/org/keycloak/audit/Audit.java b/audit/api/src/main/java/org/keycloak/audit/Audit.java
index 1ccdca8..625074f 100644
--- a/audit/api/src/main/java/org/keycloak/audit/Audit.java
+++ b/audit/api/src/main/java/org/keycloak/audit/Audit.java
@@ -5,10 +5,8 @@ import org.keycloak.models.ClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
-import org.keycloak.provider.ProviderFactoryLoader;
import java.util.HashMap;
-import java.util.LinkedList;
import java.util.List;
/**
diff --git a/audit/api/src/main/java/org/keycloak/audit/AuditListenerSpi.java b/audit/api/src/main/java/org/keycloak/audit/AuditListenerSpi.java
new file mode 100644
index 0000000..e2f0b9c
--- /dev/null
+++ b/audit/api/src/main/java/org/keycloak/audit/AuditListenerSpi.java
@@ -0,0 +1,27 @@
+package org.keycloak.audit;
+
+import org.keycloak.provider.Provider;
+import org.keycloak.provider.ProviderFactory;
+import org.keycloak.provider.Spi;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class AuditListenerSpi implements Spi {
+
+ @Override
+ public String getName() {
+ return "audit-listener";
+ }
+
+ @Override
+ public Class<? extends Provider> getProviderClass() {
+ return AuditListener.class;
+ }
+
+ @Override
+ public Class<? extends ProviderFactory> getProviderFactoryClass() {
+ return AuditListenerFactory.class;
+ }
+
+}
diff --git a/audit/api/src/main/java/org/keycloak/audit/AuditProviderSpi.java b/audit/api/src/main/java/org/keycloak/audit/AuditProviderSpi.java
new file mode 100644
index 0000000..249f7ea
--- /dev/null
+++ b/audit/api/src/main/java/org/keycloak/audit/AuditProviderSpi.java
@@ -0,0 +1,27 @@
+package org.keycloak.audit;
+
+import org.keycloak.provider.Provider;
+import org.keycloak.provider.ProviderFactory;
+import org.keycloak.provider.Spi;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class AuditProviderSpi implements Spi {
+
+ @Override
+ public String getName() {
+ return "audit";
+ }
+
+ @Override
+ public Class<? extends Provider> getProviderClass() {
+ return AuditProvider.class;
+ }
+
+ @Override
+ public Class<? extends ProviderFactory> getProviderFactoryClass() {
+ return AuditProviderFactory.class;
+ }
+
+}
diff --git a/audit/api/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/audit/api/src/main/resources/META-INF/services/org.keycloak.provider.Spi
new file mode 100644
index 0000000..2a1aeb8
--- /dev/null
+++ b/audit/api/src/main/resources/META-INF/services/org.keycloak.provider.Spi
@@ -0,0 +1,2 @@
+org.keycloak.audit.AuditProviderSpi
+org.keycloak.audit.AuditListenerSpi
\ No newline at end of file
diff --git a/audit/jboss-logging/src/main/java/org/keycloak/audit/log/JBossLoggingAuditListenerFactory.java b/audit/jboss-logging/src/main/java/org/keycloak/audit/log/JBossLoggingAuditListenerFactory.java
index 1f936af..1bafa9f 100644
--- a/audit/jboss-logging/src/main/java/org/keycloak/audit/log/JBossLoggingAuditListenerFactory.java
+++ b/audit/jboss-logging/src/main/java/org/keycloak/audit/log/JBossLoggingAuditListenerFactory.java
@@ -1,10 +1,10 @@
package org.keycloak.audit.log;
import org.jboss.logging.Logger;
+import org.keycloak.Config;
import org.keycloak.audit.AuditListener;
import org.keycloak.audit.AuditListenerFactory;
import org.keycloak.provider.ProviderSession;
-import org.keycloak.provider.ProviderSessionFactory;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -21,7 +21,7 @@ public class JBossLoggingAuditListenerFactory implements AuditListenerFactory {
}
@Override
- public void init() {
+ public void init(Config.Scope config) {
}
@Override
@@ -33,9 +33,4 @@ public class JBossLoggingAuditListenerFactory implements AuditListenerFactory {
return ID;
}
- @Override
- public boolean lazyLoad() {
- return false;
- }
-
}
diff --git a/audit/jpa/src/main/java/org/keycloak/audit/jpa/JpaAuditProviderFactory.java b/audit/jpa/src/main/java/org/keycloak/audit/jpa/JpaAuditProviderFactory.java
index c7d7a1a..01f72e2 100644
--- a/audit/jpa/src/main/java/org/keycloak/audit/jpa/JpaAuditProviderFactory.java
+++ b/audit/jpa/src/main/java/org/keycloak/audit/jpa/JpaAuditProviderFactory.java
@@ -1,9 +1,9 @@
package org.keycloak.audit.jpa;
+import org.keycloak.Config;
import org.keycloak.audit.AuditProvider;
import org.keycloak.audit.AuditProviderFactory;
import org.keycloak.provider.ProviderSession;
-import org.keycloak.provider.ProviderSessionFactory;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
@@ -22,7 +22,7 @@ public class JpaAuditProviderFactory implements AuditProviderFactory {
}
@Override
- public void init() {
+ public void init(Config.Scope config) {
emf = Persistence.createEntityManagerFactory("jpa-keycloak-audit-store");
}
@@ -36,9 +36,4 @@ public class JpaAuditProviderFactory implements AuditProviderFactory {
return ID;
}
- @Override
- public boolean lazyLoad() {
- return true;
- }
-
}
diff --git a/audit/mongo/src/main/java/org/keycloak/audit/mongo/MongoAuditProviderFactory.java b/audit/mongo/src/main/java/org/keycloak/audit/mongo/MongoAuditProviderFactory.java
index 8f78fb4..4ffcda1 100644
--- a/audit/mongo/src/main/java/org/keycloak/audit/mongo/MongoAuditProviderFactory.java
+++ b/audit/mongo/src/main/java/org/keycloak/audit/mongo/MongoAuditProviderFactory.java
@@ -2,13 +2,16 @@ package org.keycloak.audit.mongo;
import com.mongodb.DB;
import com.mongodb.MongoClient;
+import com.mongodb.MongoCredential;
+import com.mongodb.ServerAddress;
import com.mongodb.WriteConcern;
+import org.keycloak.Config;
import org.keycloak.audit.AuditProvider;
import org.keycloak.audit.AuditProviderFactory;
import org.keycloak.provider.ProviderSession;
-import org.keycloak.provider.ProviderSessionFactory;
import java.net.UnknownHostException;
+import java.util.Collections;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -29,11 +32,28 @@ public class MongoAuditProviderFactory implements AuditProviderFactory {
}
@Override
- public void init() {
+ public void init(Config.Scope config) {
try {
- client = new MongoClient(System.getProperty(MONGO_HOST, "localhost"), Integer.parseInt(System.getProperty(MONGO_PORT, "27017")));
+ String host = config.get("host", ServerAddress.defaultHost());
+ int port = config.getInt("port", ServerAddress.defaultPort());
+ String dbName = config.get("db", "keycloak-audit");
+ boolean clearOnStartup = config.getBoolean("clearOnStartup", false);
+
+ String user = config.get("user");
+ String password = config.get("password");
+ if (user != null && password != null) {
+ MongoCredential credential = MongoCredential.createMongoCRCredential(user, dbName, password.toCharArray());
+ client = new MongoClient(new ServerAddress(host, port), Collections.singletonList(credential));
+ } else {
+ client = new MongoClient(host, port);
+ }
+
client.setWriteConcern(WriteConcern.UNACKNOWLEDGED);
- db = client.getDB(System.getProperty(MONGO_DB_NAME, "keycloak-audit"));
+ db = client.getDB(dbName);
+
+ if (clearOnStartup) {
+ db.getCollection("audit").drop();
+ }
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
@@ -49,9 +69,4 @@ public class MongoAuditProviderFactory implements AuditProviderFactory {
return ID;
}
- @Override
- public boolean lazyLoad() {
- return true;
- }
-
}
diff --git a/audit/tests/src/main/java/org/keycloak/audit/tests/AbstractAuditProviderTest.java b/audit/tests/src/main/java/org/keycloak/audit/tests/AbstractAuditProviderTest.java
index 3de7473..b24ee37 100644
--- a/audit/tests/src/main/java/org/keycloak/audit/tests/AbstractAuditProviderTest.java
+++ b/audit/tests/src/main/java/org/keycloak/audit/tests/AbstractAuditProviderTest.java
@@ -4,14 +4,15 @@ import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
+import org.keycloak.Config;
import org.keycloak.audit.AuditProvider;
import org.keycloak.audit.AuditProviderFactory;
import org.keycloak.audit.Event;
import org.keycloak.provider.ProviderFactory;
-import org.keycloak.provider.ProviderFactoryLoader;
import java.util.HashMap;
import java.util.Map;
+import java.util.ServiceLoader;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -23,9 +24,14 @@ public abstract class AbstractAuditProviderTest {
@Before
public void before() {
- ProviderFactoryLoader<AuditProvider> loader = ProviderFactoryLoader.create(AuditProviderFactory.class);
- factory = loader.find(getProviderId());
- factory.init();
+ String providerId = getProviderId();
+ ServiceLoader<AuditProviderFactory> factories = ServiceLoader.load(AuditProviderFactory.class);
+ for (AuditProviderFactory f : factories) {
+ if (f.getId().equals(providerId)) {
+ factory = f;
+ factory.init(Config.scope("audit", providerId));
+ }
+ }
provider = factory.create(null);
}
diff --git a/authentication/authentication-api/src/main/java/org/keycloak/authentication/AuthenticationSpi.java b/authentication/authentication-api/src/main/java/org/keycloak/authentication/AuthenticationSpi.java
new file mode 100644
index 0000000..875b150
--- /dev/null
+++ b/authentication/authentication-api/src/main/java/org/keycloak/authentication/AuthenticationSpi.java
@@ -0,0 +1,27 @@
+package org.keycloak.authentication;
+
+import org.keycloak.provider.Provider;
+import org.keycloak.provider.ProviderFactory;
+import org.keycloak.provider.Spi;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class AuthenticationSpi implements Spi {
+
+ @Override
+ public String getName() {
+ return "authentication";
+ }
+
+ @Override
+ public Class<? extends Provider> getProviderClass() {
+ return AuthenticationProvider.class;
+ }
+
+ @Override
+ public Class<? extends ProviderFactory> getProviderFactoryClass() {
+ return AuthenticationProviderFactory.class;
+ }
+
+}
diff --git a/authentication/authentication-api/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/authentication/authentication-api/src/main/resources/META-INF/services/org.keycloak.provider.Spi
new file mode 100644
index 0000000..9305401
--- /dev/null
+++ b/authentication/authentication-api/src/main/resources/META-INF/services/org.keycloak.provider.Spi
@@ -0,0 +1 @@
+org.keycloak.authentication.AuthenticationSpi
\ No newline at end of file
diff --git a/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ExternalModelAuthenticationProviderFactory.java b/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ExternalModelAuthenticationProviderFactory.java
index 3f58d4e..4a208c0 100644
--- a/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ExternalModelAuthenticationProviderFactory.java
+++ b/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ExternalModelAuthenticationProviderFactory.java
@@ -1,10 +1,10 @@
package org.keycloak.authentication.model;
+import org.keycloak.Config;
import org.keycloak.authentication.AuthProviderConstants;
import org.keycloak.authentication.AuthenticationProvider;
import org.keycloak.authentication.AuthenticationProviderFactory;
import org.keycloak.provider.ProviderSession;
-import org.keycloak.provider.ProviderSessionFactory;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -17,7 +17,7 @@ public class ExternalModelAuthenticationProviderFactory implements Authenticatio
}
@Override
- public void init() {
+ public void init(Config.Scope config) {
}
@Override
@@ -29,8 +29,4 @@ public class ExternalModelAuthenticationProviderFactory implements Authenticatio
return AuthProviderConstants.PROVIDER_NAME_EXTERNAL_MODEL;
}
- @Override
- public boolean lazyLoad() {
- return false;
- }
}
diff --git a/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ModelAuthenticationProviderFactory.java b/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ModelAuthenticationProviderFactory.java
index 8b9e6c1..47ef637 100644
--- a/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ModelAuthenticationProviderFactory.java
+++ b/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ModelAuthenticationProviderFactory.java
@@ -1,5 +1,6 @@
package org.keycloak.authentication.model;
+import org.keycloak.Config;
import org.keycloak.authentication.AuthProviderConstants;
import org.keycloak.authentication.AuthenticationProvider;
import org.keycloak.authentication.AuthenticationProviderFactory;
@@ -16,7 +17,7 @@ public class ModelAuthenticationProviderFactory implements AuthenticationProvide
}
@Override
- public void init() {
+ public void init(Config.Scope config) {
}
@Override
@@ -28,8 +29,4 @@ public class ModelAuthenticationProviderFactory implements AuthenticationProvide
return AuthProviderConstants.PROVIDER_NAME_MODEL;
}
- @Override
- public boolean lazyLoad() {
- return false;
- }
}
diff --git a/authentication/authentication-picketlink/src/main/java/org/keycloak/authentication/picketlink/PicketlinkAuthenticationProvider.java b/authentication/authentication-picketlink/src/main/java/org/keycloak/authentication/picketlink/PicketlinkAuthenticationProvider.java
index 0027be6..ce69bd3 100755
--- a/authentication/authentication-picketlink/src/main/java/org/keycloak/authentication/picketlink/PicketlinkAuthenticationProvider.java
+++ b/authentication/authentication-picketlink/src/main/java/org/keycloak/authentication/picketlink/PicketlinkAuthenticationProvider.java
@@ -1,28 +1,25 @@
package org.keycloak.authentication.picketlink;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
import org.jboss.logging.Logger;
-import org.jboss.resteasy.spi.ResteasyProviderFactory;
-import org.keycloak.models.RealmModel;
-import org.keycloak.authentication.AuthProviderStatus;
import org.keycloak.authentication.AuthProviderConstants;
+import org.keycloak.authentication.AuthProviderStatus;
import org.keycloak.authentication.AuthUser;
import org.keycloak.authentication.AuthenticationProvider;
import org.keycloak.authentication.AuthenticationProviderException;
+import org.keycloak.models.RealmModel;
import org.keycloak.picketlink.IdentityManagerProvider;
-import org.keycloak.util.ProviderLoader;
import org.picketlink.idm.IdentityManagementException;
import org.picketlink.idm.IdentityManager;
-import org.picketlink.idm.PartitionManager;
import org.picketlink.idm.credential.Credentials;
import org.picketlink.idm.credential.Password;
import org.picketlink.idm.credential.UsernamePasswordCredentials;
import org.picketlink.idm.model.basic.BasicModel;
import org.picketlink.idm.model.basic.User;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
/**
* AuthenticationProvider, which delegates authentication to picketlink
*
diff --git a/authentication/authentication-picketlink/src/main/java/org/keycloak/authentication/picketlink/PicketlinkAuthenticationProviderFactory.java b/authentication/authentication-picketlink/src/main/java/org/keycloak/authentication/picketlink/PicketlinkAuthenticationProviderFactory.java
index db1ece3..29cdb6f 100644
--- a/authentication/authentication-picketlink/src/main/java/org/keycloak/authentication/picketlink/PicketlinkAuthenticationProviderFactory.java
+++ b/authentication/authentication-picketlink/src/main/java/org/keycloak/authentication/picketlink/PicketlinkAuthenticationProviderFactory.java
@@ -1,5 +1,6 @@
package org.keycloak.authentication.picketlink;
+import org.keycloak.Config;
import org.keycloak.authentication.AuthProviderConstants;
import org.keycloak.authentication.AuthenticationProvider;
import org.keycloak.authentication.AuthenticationProviderFactory;
@@ -17,7 +18,7 @@ public class PicketlinkAuthenticationProviderFactory implements AuthenticationPr
}
@Override
- public void init() {
+ public void init(Config.Scope config) {
}
@Override
@@ -29,8 +30,4 @@ public class PicketlinkAuthenticationProviderFactory implements AuthenticationPr
return AuthProviderConstants.PROVIDER_NAME_PICKETLINK;
}
- @Override
- public boolean lazyLoad() {
- return false;
- }
}
core/src/main/java/org/keycloak/Config.java 129(+129 -0)
diff --git a/core/src/main/java/org/keycloak/Config.java b/core/src/main/java/org/keycloak/Config.java
new file mode 100644
index 0000000..34d0fa4
--- /dev/null
+++ b/core/src/main/java/org/keycloak/Config.java
@@ -0,0 +1,129 @@
+package org.keycloak;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class Config {
+
+ private static ConfigProvider configProvider = new SystemPropertiesConfigProvider();
+
+ public static void init(ConfigProvider configProvider) {
+ Config.configProvider = configProvider;
+ }
+
+ public static String getAdminRealm() {
+ return configProvider.scope("admin").get("realm", "keycloak-admin");
+ }
+
+ public static String getProvider(String spi) {
+ return configProvider.getProvider(spi);
+ }
+
+ public static Scope scope(String... scope) {
+ return configProvider.scope(scope);
+ }
+
+ public static interface ConfigProvider {
+
+ String getProvider(String spi);
+
+ Scope scope(String... scope);
+
+ }
+
+ public static class SystemPropertiesConfigProvider implements ConfigProvider {
+
+ @Override
+ public String getProvider(String spi) {
+ return System.getProperties().getProperty("keycloak." + spi + ".provider");
+ }
+
+ @Override
+ public Scope scope(String... scope) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("keycloak.");
+ for (String s : scope) {
+ sb.append(s);
+ sb.append(".");
+ }
+ return new SystemPropertiesScope(sb.toString());
+ }
+
+ }
+
+ public static class SystemPropertiesScope implements Scope {
+
+ private String prefix;
+
+ public SystemPropertiesScope(String prefix) {
+ this.prefix = prefix;
+ }
+
+ @Override
+ public String get(String key) {
+ return get(key, null);
+ }
+
+ @Override
+ public String get(String key, String defaultValue) {
+ return System.getProperty(prefix + key, defaultValue);
+ }
+
+ @Override
+ public Integer getInt(String key) {
+ return getInt(key, null);
+ }
+
+ @Override
+ public Integer getInt(String key, Integer defaultValue) {
+ String v = get(key, null);
+ return v != null ? Integer.parseInt(v) : defaultValue;
+ }
+
+ @Override
+ public Long getLong(String key) {
+ return getLong(key, null);
+ }
+
+ @Override
+ public Long getLong(String key, Long defaultValue) {
+ String v = get(key, null);
+ return v != null ? Long.parseLong(v) : defaultValue;
+ }
+
+ @Override
+ public Boolean getBoolean(String key) {
+ return getBoolean(key, null);
+ }
+
+ @Override
+ public Boolean getBoolean(String key, Boolean defaultValue) {
+ String v = get(key, null);
+ return v != null ? Boolean.parseBoolean(v) : defaultValue;
+ }
+
+ }
+
+ /**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+ public static interface Scope {
+
+ String get(String key);
+
+ String get(String key, String defaultValue);
+
+ Integer getInt(String key);
+
+ Integer getInt(String key, Integer defaultValue);
+
+ Long getLong(String key);
+
+ Long getLong(String key, Long defaultValue);
+
+ Boolean getBoolean(String key);
+
+ Boolean getBoolean(String key, Boolean defaultValue);
+
+ }
+}
diff --git a/core/src/main/java/org/keycloak/provider/ProviderFactory.java b/core/src/main/java/org/keycloak/provider/ProviderFactory.java
index 996d2c5..0e49732 100644
--- a/core/src/main/java/org/keycloak/provider/ProviderFactory.java
+++ b/core/src/main/java/org/keycloak/provider/ProviderFactory.java
@@ -1,5 +1,7 @@
package org.keycloak.provider;
+import org.keycloak.Config;
+
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
@@ -7,12 +9,10 @@ public interface ProviderFactory<T extends Provider> {
public T create(ProviderSession providerSession);
- public void init();
+ public void init(Config.Scope config);
public void close();
public String getId();
- public boolean lazyLoad();
-
}
diff --git a/core/src/main/java/org/keycloak/provider/ProviderSessionFactory.java b/core/src/main/java/org/keycloak/provider/ProviderSessionFactory.java
index 2e347df..93536d0 100755
--- a/core/src/main/java/org/keycloak/provider/ProviderSessionFactory.java
+++ b/core/src/main/java/org/keycloak/provider/ProviderSessionFactory.java
@@ -1,7 +1,5 @@
package org.keycloak.provider;
-import java.util.Set;
-
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
@@ -11,12 +9,6 @@ public interface ProviderSessionFactory {
void close();
- <T extends Provider> ProviderFactory<T> getProviderFactory(Class<T> clazz);
-
- <T extends Provider> ProviderFactory<T> getProviderFactory(Class<T> clazz, String id);
-
- Set<String> providerIds(Class<? extends Provider> clazz);
-
void init();
}
diff --git a/core/src/main/java/org/keycloak/provider/Spi.java b/core/src/main/java/org/keycloak/provider/Spi.java
new file mode 100644
index 0000000..03b9afc
--- /dev/null
+++ b/core/src/main/java/org/keycloak/provider/Spi.java
@@ -0,0 +1,12 @@
+package org.keycloak.provider;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public interface Spi {
+
+ public String getName();
+ public Class<? extends Provider> getProviderClass();
+ public Class<? extends ProviderFactory> getProviderFactoryClass();
+
+}
diff --git a/core/src/main/java/org/keycloak/util/CollectionUtil.java b/core/src/main/java/org/keycloak/util/CollectionUtil.java
new file mode 100644
index 0000000..41df40e
--- /dev/null
+++ b/core/src/main/java/org/keycloak/util/CollectionUtil.java
@@ -0,0 +1,26 @@
+package org.keycloak.util;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * @author <a href="mailto:jeroen.rosenberg@gmail.com">Jeroen Rosenberg</a>
+ */
+public class CollectionUtil {
+
+ public static String join(Collection<String> strings) {
+ return join(strings, ", ");
+ }
+
+ public static String join(Collection<String> strings, String separator) {
+ Iterator<String> iter = strings.iterator();
+ StringBuilder sb = new StringBuilder();
+ if(iter.hasNext()){
+ sb.append(iter.next());
+ while(iter.hasNext()){
+ sb.append(separator).append(iter.next());
+ }
+ }
+ return sb.toString();
+ }
+}
diff --git a/core/src/main/java/org/keycloak/util/StringPropertyReplacer.java b/core/src/main/java/org/keycloak/util/StringPropertyReplacer.java
new file mode 100644
index 0000000..d46f699
--- /dev/null
+++ b/core/src/main/java/org/keycloak/util/StringPropertyReplacer.java
@@ -0,0 +1,263 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.util;
+
+import java.util.Properties;
+import java.io.File;
+
+/**
+ * A utility class for replacing properties in strings.
+ *
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @author <a href="Scott.Stark@jboss.org">Scott Stark</a>
+ * @author <a href="claudio.vesco@previnet.it">Claudio Vesco</a>
+ * @author <a href="mailto:adrian@jboss.com">Adrian Brock</a>
+ * @author <a href="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
+ * @version <tt>$Revision: 2898 $</tt>
+ */
+public final class StringPropertyReplacer
+{
+ /** New line string constant */
+ public static final String NEWLINE = System.getProperty("line.separator", "\n");
+
+ /** File separator value */
+ private static final String FILE_SEPARATOR = File.separator;
+
+ /** Path separator value */
+ private static final String PATH_SEPARATOR = File.pathSeparator;
+
+ /** File separator alias */
+ private static final String FILE_SEPARATOR_ALIAS = "/";
+
+ /** Path separator alias */
+ private static final String PATH_SEPARATOR_ALIAS = ":";
+
+ // States used in property parsing
+ private static final int NORMAL = 0;
+ private static final int SEEN_DOLLAR = 1;
+ private static final int IN_BRACKET = 2;
+
+ /**
+ * Go through the input string and replace any occurance of ${p} with
+ * the System.getProperty(p) value. If there is no such property p defined,
+ * then the ${p} reference will remain unchanged.
+ *
+ * If the property reference is of the form ${p:v} and there is no such property p,
+ * then the default value v will be returned.
+ *
+ * If the property reference is of the form ${p1,p2} or ${p1,p2:v} then
+ * the primary and the secondary properties will be tried in turn, before
+ * returning either the unchanged input, or the default value.
+ *
+ * The property ${/} is replaced with System.getProperty("file.separator")
+ * value and the property ${:} is replaced with System.getProperty("path.separator").
+ *
+ * @param string - the string with possible ${} references
+ * @return the input string with all property references replaced if any.
+ * If there are no valid references the input string will be returned.
+ */
+ public static String replaceProperties(final String string)
+ {
+ return replaceProperties(string, null);
+ }
+
+ /**
+ * Go through the input string and replace any occurance of ${p} with
+ * the props.getProperty(p) value. If there is no such property p defined,
+ * then the ${p} reference will remain unchanged.
+ *
+ * If the property reference is of the form ${p:v} and there is no such property p,
+ * then the default value v will be returned.
+ *
+ * If the property reference is of the form ${p1,p2} or ${p1,p2:v} then
+ * the primary and the secondary properties will be tried in turn, before
+ * returning either the unchanged input, or the default value.
+ *
+ * The property ${/} is replaced with System.getProperty("file.separator")
+ * value and the property ${:} is replaced with System.getProperty("path.separator").
+ *
+ * @param string - the string with possible ${} references
+ * @param props - the source for ${x} property ref values, null means use System.getProperty()
+ * @return the input string with all property references replaced if any.
+ * If there are no valid references the input string will be returned.
+ */
+ public static String replaceProperties(final String string, final Properties props)
+ {
+ final char[] chars = string.toCharArray();
+ StringBuffer buffer = new StringBuffer();
+ boolean properties = false;
+ int state = NORMAL;
+ int start = 0;
+ for (int i = 0; i < chars.length; ++i)
+ {
+ char c = chars[i];
+
+ // Dollar sign outside brackets
+ if (c == '$' && state != IN_BRACKET)
+ state = SEEN_DOLLAR;
+
+ // Open bracket immediatley after dollar
+ else if (c == '{' && state == SEEN_DOLLAR)
+ {
+ buffer.append(string.substring(start, i - 1));
+ state = IN_BRACKET;
+ start = i - 1;
+ }
+
+ // No open bracket after dollar
+ else if (state == SEEN_DOLLAR)
+ state = NORMAL;
+
+ // Closed bracket after open bracket
+ else if (c == '}' && state == IN_BRACKET)
+ {
+ // No content
+ if (start + 2 == i)
+ {
+ buffer.append("${}"); // REVIEW: Correct?
+ }
+ else // Collect the system property
+ {
+ String value = null;
+
+ String key = string.substring(start + 2, i);
+
+ // check for alias
+ if (FILE_SEPARATOR_ALIAS.equals(key))
+ {
+ value = FILE_SEPARATOR;
+ }
+ else if (PATH_SEPARATOR_ALIAS.equals(key))
+ {
+ value = PATH_SEPARATOR;
+ }
+ else
+ {
+ // check from the properties
+ if (props != null)
+ value = props.getProperty(key);
+ else
+ value = System.getProperty(key);
+
+ if (value == null)
+ {
+ // Check for a default value ${key:default}
+ int colon = key.indexOf(':');
+ if (colon > 0)
+ {
+ String realKey = key.substring(0, colon);
+ if (props != null)
+ value = props.getProperty(realKey);
+ else
+ value = System.getProperty(realKey);
+
+ if (value == null)
+ {
+ // Check for a composite key, "key1,key2"
+ value = resolveCompositeKey(realKey, props);
+
+ // Not a composite key either, use the specified default
+ if (value == null)
+ value = key.substring(colon+1);
+ }
+ }
+ else
+ {
+ // No default, check for a composite key, "key1,key2"
+ value = resolveCompositeKey(key, props);
+ }
+ }
+ }
+
+ if (value != null)
+ {
+ properties = true;
+ buffer.append(value);
+ }
+ else
+ {
+ buffer.append("${");
+ buffer.append(key);
+ buffer.append('}');
+ }
+
+ }
+ start = i + 1;
+ state = NORMAL;
+ }
+ }
+
+ // No properties
+ if (properties == false)
+ return string;
+
+ // Collect the trailing characters
+ if (start != chars.length)
+ buffer.append(string.substring(start, chars.length));
+
+ // Done
+ return buffer.toString();
+ }
+
+ /**
+ * Try to resolve a "key" from the provided properties by
+ * checking if it is actually a "key1,key2", in which case
+ * try first "key1", then "key2". If all fails, return null.
+ *
+ * It also accepts "key1," and ",key2".
+ *
+ * @param key the key to resolve
+ * @param props the properties to use
+ * @return the resolved key or null
+ */
+ private static String resolveCompositeKey(String key, Properties props)
+ {
+ String value = null;
+
+ // Look for the comma
+ int comma = key.indexOf(',');
+ if (comma > -1)
+ {
+ // If we have a first part, try resolve it
+ if (comma > 0)
+ {
+ // Check the first part
+ String key1 = key.substring(0, comma);
+ if (props != null)
+ value = props.getProperty(key1);
+ else
+ value = System.getProperty(key1);
+ }
+ // Check the second part, if there is one and first lookup failed
+ if (value == null && comma < key.length() - 1)
+ {
+ String key2 = key.substring(comma + 1);
+ if (props != null)
+ value = props.getProperty(key2);
+ else
+ value = System.getProperty(key2);
+ }
+ }
+ // Return whatever we've found or null
+ return value;
+ }
+}
\ No newline at end of file
diff --git a/docbook/reference/en/en-US/modules/server-installation.xml b/docbook/reference/en/en-US/modules/server-installation.xml
index 873fd6e..70f14f4 100755
--- a/docbook/reference/en/en-US/modules/server-installation.xml
+++ b/docbook/reference/en/en-US/modules/server-installation.xml
@@ -252,12 +252,12 @@ keycloak-war-dist-all-1.0-beta-1-SNAPSHOT/
First you need to specify that you want to use <literal>mongo</literal> instead of default <literal>jpa</literal> model, and you may also specify
host, port and name of mongo database. So you can start keycloak with the command like this:
<programlisting><![CDATA[
-./standalone.sh -Dkeycloak.model=mongo -Dkeycloak.mongo.host=localhost
--Dkeycloak.mongo.port=27017 -Dkeycloak.mongo.db=keycloak
+./standalone.sh -Dkeycloak.model=mongo -Dkeycloak.model.mongo.host=localhost
+-Dkeycloak.model.mongoport=27017 -Dkeycloak.model.mongo.db=keycloak
]]></programlisting>
Note that when you install MongoDB on your laptop, it's usually on localhost/270717 by default. That's why properties
- <literal>keycloak.mongo.host</literal> and <literal>keycloak.mongo.port</literal> are not mandatory, but they already have
- default values <literal>localhost</literal> and <literal>27017</literal> . Similarly property <literal>keycloak.mongo.db</literal>
+ <literal>keycloak.model.mongo.host</literal> and <literal>keycloak.model.mongo.port</literal> are not mandatory, but they already have
+ default values <literal>localhost</literal> and <literal>27017</literal> . Similarly property <literal>keycloak.model.mongo.db</literal>
has default value <literal>keycloak</literal> for name of underlying database. So the example above could be simplified like:
<programlisting><![CDATA[
./standalone.sh -Dkeycloak.model=mongo
diff --git a/export-import/export-import-api/pom.xml b/export-import/export-import-api/pom.xml
index 7f94100..e4ed0ad 100644
--- a/export-import/export-import-api/pom.xml
+++ b/export-import/export-import-api/pom.xml
@@ -16,6 +16,12 @@
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
+ <artifactId>keycloak-core</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.keycloak</groupId>
<artifactId>keycloak-model-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
diff --git a/export-import/export-import-api/src/main/java/org/keycloak/exportimport/ExportImportProvider.java b/export-import/export-import-api/src/main/java/org/keycloak/exportimport/ExportImportProvider.java
index 9ada46b..9798370 100644
--- a/export-import/export-import-api/src/main/java/org/keycloak/exportimport/ExportImportProvider.java
+++ b/export-import/export-import-api/src/main/java/org/keycloak/exportimport/ExportImportProvider.java
@@ -1,11 +1,12 @@
package org.keycloak.exportimport;
-import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.provider.ProviderSessionFactory;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface ExportImportProvider {
- void checkExportImport(KeycloakSessionFactory identitySessionFactory);
+ void checkExportImport(ProviderSessionFactory identitySessionFactory);
+
}
export-import/export-import-impl/pom.xml 31(+15 -16)
diff --git a/export-import/export-import-impl/pom.xml b/export-import/export-import-impl/pom.xml
index a4898e5..17a566e 100644
--- a/export-import/export-import-impl/pom.xml
+++ b/export-import/export-import-impl/pom.xml
@@ -33,13 +33,6 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>org.keycloak</groupId>
- <artifactId>keycloak-audit-api</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
- </dependency>
-
- <dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>jaxrs-api</artifactId>
<scope>provided</scope>
@@ -122,6 +115,12 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-model-tests</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<scope>test</scope>
@@ -149,10 +148,10 @@
</dependencies>
<properties>
- <keycloak.mongo.host>localhost</keycloak.mongo.host>
- <keycloak.mongo.port>27018</keycloak.mongo.port>
- <keycloak.mongo.db>keycloak</keycloak.mongo.db>
- <keycloak.mongo.clearOnStartup>true</keycloak.mongo.clearOnStartup>
+ <keycloak.model.mongo.host>localhost</keycloak.model.mongo.host>
+ <keycloak.model.mongo.port>27018</keycloak.model.mongo.port>
+ <keycloak.model.mongo.db>keycloak</keycloak.model.mongo.db>
+ <keycloak.model.mongo.clearOnStartup>true</keycloak.model.mongo.clearOnStartup>
</properties>
<build>
@@ -179,10 +178,10 @@
</goals>
<configuration>
<systemPropertyVariables>
- <keycloak.mongo.host>${keycloak.mongo.host}</keycloak.mongo.host>
- <keycloak.mongo.port>${keycloak.mongo.port}</keycloak.mongo.port>
- <keycloak.mongo.db>${keycloak.mongo.db}</keycloak.mongo.db>
- <keycloak.mongo.clearOnStartup>${keycloak.mongo.clearOnStartup}</keycloak.mongo.clearOnStartup>
+ <keycloak.model.mongo.host>${keycloak.model.mongo.host}</keycloak.model.mongo.host>
+ <keycloak.model.mongo.port>${keycloak.model.mongo.port}</keycloak.model.mongo.port>
+ <keycloak.model.mongo.db>${keycloak.model.mongo.db}</keycloak.model.mongo.db>
+ <keycloak.model.mongo.clearOnStartup>${keycloak.model.mongo.clearOnStartup}</keycloak.model.mongo.clearOnStartup>
</systemPropertyVariables>
</configuration>
</execution>
@@ -207,7 +206,7 @@
<goal>start</goal>
</goals>
<configuration>
- <port>${keycloak.mongo.port}</port>
+ <port>${keycloak.model.mongo.port}</port>
<logging>file</logging>
<logFile>${project.build.directory}/mongodb.log</logFile>
</configuration>
diff --git a/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ExportImportConfig.java b/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ExportImportConfig.java
new file mode 100644
index 0000000..d87b55c
--- /dev/null
+++ b/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ExportImportConfig.java
@@ -0,0 +1,54 @@
+package org.keycloak.exportimport;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class ExportImportConfig {
+
+ public static final String ACTION = "keycloak.migration.action";
+ public static final String PROVIDER = "keycloak.migration.provider";
+ public static final String PROVIDER_DEFAULT = "zip";
+
+ // used for "directory" provider
+ public static final String DIR = "keycloak.migration.dir";
+ // used for "zip" provider
+ public static final String FILE = "keycloak.migration.zipFile";
+ public static final String PASSWORD = "keycloak.migration.zipPassword";
+
+ public static String getAction() {
+ return System.getProperty(ACTION);
+ }
+
+ public static void setAction(String exportImportAction) {
+ System.setProperty(ACTION, exportImportAction);
+ }
+
+ public static String getProvider() {
+ return System.getProperty(PROVIDER, PROVIDER_DEFAULT);
+ }
+
+ public static void setProvider(String exportImportProvider) {
+ System.setProperty(PROVIDER, exportImportProvider);
+ }
+
+ public static String getDir() {
+ return System.getProperty(DIR);
+ }
+
+ public static String getZipFile() {
+ return System.getProperty(FILE);
+ }
+
+ public static void setZipFile(String exportImportZipFile) {
+ System.setProperty(FILE, exportImportZipFile);
+ }
+
+ public static String getZipPassword() {
+ return System.getProperty(PASSWORD);
+ }
+
+ public static void setZipPassword(String exportImportZipPassword) {
+ System.setProperty(PASSWORD, exportImportZipPassword);
+ }
+
+}
diff --git a/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ExportImportProviderImpl.java b/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ExportImportProviderImpl.java
index 32e0b84..de84633 100644
--- a/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ExportImportProviderImpl.java
+++ b/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ExportImportProviderImpl.java
@@ -4,10 +4,10 @@ import org.jboss.logging.Logger;
import org.keycloak.exportimport.io.ExportImportIOProvider;
import org.keycloak.exportimport.io.ExportWriter;
import org.keycloak.exportimport.io.ImportReader;
-import org.keycloak.models.Config;
import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.KeycloakTransaction;
+import org.keycloak.provider.ProviderSession;
+import org.keycloak.provider.ProviderSessionFactory;
import org.keycloak.util.ProviderLoader;
/**
@@ -21,8 +21,8 @@ public class ExportImportProviderImpl implements ExportImportProvider {
public static final String ACTION_IMPORT = "import";
@Override
- public void checkExportImport(KeycloakSessionFactory identitySessionFactory) {
- String exportImportAction = Config.getExportImportAction();
+ public void checkExportImport(ProviderSessionFactory providerSessionFactory) {
+ String exportImportAction = ExportImportConfig.getAction();
boolean export = false;
boolean importt = false;
@@ -35,7 +35,8 @@ public class ExportImportProviderImpl implements ExportImportProvider {
}
if (export || importt) {
- KeycloakSession session = identitySessionFactory.createSession();
+ ProviderSession providerSession = providerSessionFactory.createSession();
+ KeycloakSession session = providerSession.getProvider(KeycloakSession.class);
KeycloakTransaction transaction = session.getTransaction();
try {
transaction.begin();
@@ -63,13 +64,13 @@ public class ExportImportProviderImpl implements ExportImportProvider {
}
throw new RuntimeException(e);
} finally {
- session.close();
+ providerSession.close();
}
}
}
private ExportImportIOProvider getProvider() {
- String providerId = Config.getExportImportProvider();
+ String providerId = ExportImportConfig.getProvider();
logger.infof("Requested migration provider: " + providerId);
Iterable<ExportImportIOProvider> providers = ProviderLoader.load(ExportImportIOProvider.class);
diff --git a/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/io/directory/TmpDirExportImportIOProvider.java b/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/io/directory/TmpDirExportImportIOProvider.java
index 962c3ac..b785c41 100644
--- a/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/io/directory/TmpDirExportImportIOProvider.java
+++ b/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/io/directory/TmpDirExportImportIOProvider.java
@@ -1,11 +1,11 @@
package org.keycloak.exportimport.io.directory;
-import java.io.File;
-
+import org.keycloak.exportimport.ExportImportConfig;
import org.keycloak.exportimport.io.ExportImportIOProvider;
import org.keycloak.exportimport.io.ExportWriter;
import org.keycloak.exportimport.io.ImportReader;
-import org.keycloak.models.Config;
+
+import java.io.File;
/**
* Export/import into JSON files inside "tmp" directory. This implementation is used mainly for testing
@@ -19,13 +19,13 @@ public class TmpDirExportImportIOProvider implements ExportImportIOProvider {
@Override
public ExportWriter getExportWriter() {
- String dir = Config.getExportImportDir();
+ String dir = ExportImportConfig.getDir();
return dir!=null ? new TmpDirExportWriter(new File(dir)) : new TmpDirExportWriter();
}
@Override
public ImportReader getImportReader() {
- String dir = Config.getExportImportDir();
+ String dir = ExportImportConfig.getDir();
return dir!=null ? new TmpDirImportReader(new File(dir)) : new TmpDirImportReader();
}
diff --git a/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/io/zip/EncryptedZIPIOProvider.java b/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/io/zip/EncryptedZIPIOProvider.java
index 837157e..31883ac 100644
--- a/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/io/zip/EncryptedZIPIOProvider.java
+++ b/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/io/zip/EncryptedZIPIOProvider.java
@@ -1,10 +1,10 @@
package org.keycloak.exportimport.io.zip;
import org.jboss.logging.Logger;
+import org.keycloak.exportimport.ExportImportConfig;
import org.keycloak.exportimport.io.ExportImportIOProvider;
import org.keycloak.exportimport.io.ExportWriter;
import org.keycloak.exportimport.io.ImportReader;
-import org.keycloak.models.Config;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -22,8 +22,8 @@ public class EncryptedZIPIOProvider implements ExportImportIOProvider {
@Override
public ExportWriter getExportWriter() {
- String zipFile = Config.getExportImportZipFile();
- String zipPassword = Config.getExportImportZipPassword();
+ String zipFile = ExportImportConfig.getZipFile();
+ String zipPassword = ExportImportConfig.getZipPassword();
logger.infof("Using zip for export: " + zipFile);
if (zipFile==null || zipPassword==null) {
@@ -35,8 +35,8 @@ public class EncryptedZIPIOProvider implements ExportImportIOProvider {
@Override
public ImportReader getImportReader() {
- String zipFile = Config.getExportImportZipFile();
- String zipPassword = Config.getExportImportZipPassword();
+ String zipFile = ExportImportConfig.getZipFile();
+ String zipPassword = ExportImportConfig.getZipPassword();
logger.infof("Using zip for import: " + zipFile);
if (zipFile==null || zipPassword==null) {
diff --git a/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelImporter.java b/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelImporter.java
index 3bfc9aa..15f9fae 100755
--- a/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelImporter.java
+++ b/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelImporter.java
@@ -13,7 +13,7 @@ import org.keycloak.models.ApplicationModel;
import org.keycloak.models.AuthenticationLinkModel;
import org.keycloak.models.AuthenticationProviderModel;
import org.keycloak.models.ClientModel;
-import org.keycloak.models.Config;
+import org.keycloak.Config;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.OAuthClientModel;
import org.keycloak.models.PasswordPolicy;
diff --git a/export-import/export-import-impl/src/test/java/org/keycloak/exportimport/ExportImportTestBase.java b/export-import/export-import-impl/src/test/java/org/keycloak/exportimport/ExportImportTestBase.java
index 1e39f24..49817c7 100644
--- a/export-import/export-import-impl/src/test/java/org/keycloak/exportimport/ExportImportTestBase.java
+++ b/export-import/export-import-impl/src/test/java/org/keycloak/exportimport/ExportImportTestBase.java
@@ -1,36 +1,43 @@
package org.keycloak.exportimport;
-import java.util.Iterator;
-
+import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
import org.keycloak.model.test.AbstractModelTest;
import org.keycloak.model.test.ImportTest;
-import org.keycloak.models.Config;
import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
+import org.keycloak.provider.ProviderSession;
+import org.keycloak.provider.ProviderSessionFactory;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.managers.ApplianceBootstrap;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.resources.KeycloakApplication;
import org.keycloak.util.ProviderLoader;
+import java.util.Iterator;
+
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public abstract class ExportImportTestBase {
- protected KeycloakSessionFactory factory;
+ protected ProviderSessionFactory factory;
+ protected ProviderSession providerSession;
protected KeycloakSession identitySession;
protected RealmManager realmManager;
+ @After
+ public void after() {
+ System.getProperties().remove("keycloak.model.provider");
+ }
+
@Test
public void testExportImport() throws Exception {
// Init JPA model
- Config.setModelProvider(getExportModelProvider());
- factory = KeycloakApplication.createSessionFactory();
+ System.setProperty("keycloak.model.provider", getExportModelProvider());
+ factory = KeycloakApplication.createProviderSessionFactory();
// Bootstrap admin realm
beginTransaction();
@@ -59,8 +66,8 @@ public abstract class ExportImportTestBase {
factory.close();
// Bootstrap mongo session and factory
- Config.setModelProvider(getImportModelProvider());
- factory = KeycloakApplication.createSessionFactory();
+ System.setProperty("keycloak.model.provider", getImportModelProvider());
+ factory = KeycloakApplication.createProviderSessionFactory();
// Full import of previous export into mongo
importModel(factory);
@@ -83,19 +90,20 @@ public abstract class ExportImportTestBase {
protected abstract String getImportModelProvider();
- protected abstract void exportModel(KeycloakSessionFactory factory);
+ protected abstract void exportModel(ProviderSessionFactory factory);
- protected abstract void importModel(KeycloakSessionFactory factory);
+ protected abstract void importModel(ProviderSessionFactory factory);
protected void beginTransaction() {
- identitySession = factory.createSession();
+ providerSession = factory.createSession();
+ identitySession = providerSession.getProvider(KeycloakSession.class);
identitySession.getTransaction().begin();
realmManager = new RealmManager(identitySession);
}
protected void commitTransaction() {
identitySession.getTransaction().commit();
- identitySession.close();
+ providerSession.close();
}
protected ExportImportProvider getExportImportProvider() {
diff --git a/export-import/export-import-impl/src/test/java/org/keycloak/exportimport/JPAToMongoExportImportTest.java b/export-import/export-import-impl/src/test/java/org/keycloak/exportimport/JPAToMongoExportImportTest.java
index 8175bdb..52ee054 100644
--- a/export-import/export-import-impl/src/test/java/org/keycloak/exportimport/JPAToMongoExportImportTest.java
+++ b/export-import/export-import-impl/src/test/java/org/keycloak/exportimport/JPAToMongoExportImportTest.java
@@ -1,8 +1,7 @@
package org.keycloak.exportimport;
import org.keycloak.exportimport.io.directory.TmpDirExportImportIOProvider;
-import org.keycloak.models.Config;
-import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.provider.ProviderSessionFactory;
/**
* Test for full export of data from JPA and import them to Mongo. Using "directory" provider
@@ -22,16 +21,16 @@ public class JPAToMongoExportImportTest extends ExportImportTestBase {
}
@Override
- protected void exportModel(KeycloakSessionFactory factory) {
- Config.setExportImportAction(ExportImportProviderImpl.ACTION_EXPORT);
- Config.setExportImportProvider(TmpDirExportImportIOProvider.PROVIDER_ID);
+ protected void exportModel(ProviderSessionFactory factory) {
+ ExportImportConfig.setAction(ExportImportProviderImpl.ACTION_EXPORT);
+ ExportImportConfig.setProvider(TmpDirExportImportIOProvider.PROVIDER_ID);
getExportImportProvider().checkExportImport(factory);
}
@Override
- protected void importModel(KeycloakSessionFactory factory) {
- Config.setExportImportAction(ExportImportProviderImpl.ACTION_IMPORT);
- Config.setExportImportProvider(TmpDirExportImportIOProvider.PROVIDER_ID);
+ protected void importModel(ProviderSessionFactory factory) {
+ ExportImportConfig.setAction(ExportImportProviderImpl.ACTION_IMPORT);
+ ExportImportConfig.setProvider(TmpDirExportImportIOProvider.PROVIDER_ID);
getExportImportProvider().checkExportImport(factory);
}
}
diff --git a/export-import/export-import-impl/src/test/java/org/keycloak/exportimport/MongoToJPAExportImportTest.java b/export-import/export-import-impl/src/test/java/org/keycloak/exportimport/MongoToJPAExportImportTest.java
index e715c9c..849c388 100644
--- a/export-import/export-import-impl/src/test/java/org/keycloak/exportimport/MongoToJPAExportImportTest.java
+++ b/export-import/export-import-impl/src/test/java/org/keycloak/exportimport/MongoToJPAExportImportTest.java
@@ -1,11 +1,10 @@
package org.keycloak.exportimport;
-import java.io.File;
-
import org.junit.Assert;
import org.keycloak.exportimport.io.zip.EncryptedZIPIOProvider;
-import org.keycloak.models.Config;
-import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.provider.ProviderSessionFactory;
+
+import java.io.File;
/**
* Test for full export of data from Mongo and import them to JPA. Using export into encrypted ZIP and import from it
@@ -27,12 +26,12 @@ public class MongoToJPAExportImportTest extends ExportImportTestBase {
}
@Override
- protected void exportModel(KeycloakSessionFactory factory) {
- Config.setExportImportAction(ExportImportProviderImpl.ACTION_EXPORT);
- Config.setExportImportProvider(EncryptedZIPIOProvider.PROVIDER_ID);
+ protected void exportModel(ProviderSessionFactory factory) {
+ ExportImportConfig.setAction(ExportImportProviderImpl.ACTION_EXPORT);
+ ExportImportConfig.setProvider(EncryptedZIPIOProvider.PROVIDER_ID);
File zipFile = getZipFile();
- Config.setExportImportZipFile(zipFile.getAbsolutePath());
- Config.setExportImportZipPassword("password123");
+ ExportImportConfig.setZipFile(zipFile.getAbsolutePath());
+ ExportImportConfig.setZipPassword("password123");
if (zipFile.exists()) {
zipFile.delete();
@@ -42,12 +41,12 @@ public class MongoToJPAExportImportTest extends ExportImportTestBase {
}
@Override
- protected void importModel(KeycloakSessionFactory factory) {
- Config.setExportImportAction(ExportImportProviderImpl.ACTION_IMPORT);
- Config.setExportImportProvider(EncryptedZIPIOProvider.PROVIDER_ID);
+ protected void importModel(ProviderSessionFactory factory) {
+ ExportImportConfig.setAction(ExportImportProviderImpl.ACTION_IMPORT);
+ ExportImportConfig.setProvider(EncryptedZIPIOProvider.PROVIDER_ID);
File zipFile = getZipFile();
- Config.setExportImportZipFile(zipFile.getAbsolutePath());
- Config.setExportImportZipPassword("password-invalid");
+ ExportImportConfig.setZipFile(zipFile.getAbsolutePath());
+ ExportImportConfig.setZipPassword("password-invalid");
// Try invalid password
try {
@@ -55,7 +54,7 @@ public class MongoToJPAExportImportTest extends ExportImportTestBase {
Assert.fail("Not expected to be here. Exception should be thrown");
} catch (Exception e) {};
- Config.setExportImportZipPassword("password123");
+ ExportImportConfig.setZipPassword("password123");
new ExportImportProviderImpl().checkExportImport(factory);
if (zipFile.exists()) {
diff --git a/forms/common-freemarker/src/main/java/org/keycloak/freemarker/ThemeLoader.java b/forms/common-freemarker/src/main/java/org/keycloak/freemarker/ThemeLoader.java
index c64bff6..23f99e3 100755
--- a/forms/common-freemarker/src/main/java/org/keycloak/freemarker/ThemeLoader.java
+++ b/forms/common-freemarker/src/main/java/org/keycloak/freemarker/ThemeLoader.java
@@ -1,6 +1,6 @@
package org.keycloak.freemarker;
-import org.keycloak.models.Config;
+import org.keycloak.Config;
import org.keycloak.util.ProviderLoader;
import java.io.IOException;
@@ -20,7 +20,7 @@ public class ThemeLoader {
public static Theme createTheme(String name, Theme.Type type) throws FreeMarkerException {
if (name == null) {
- name = Config.getThemeDefault();
+ name = Config.scope("theme").get("default");
}
List<ThemeProvider> providers = new LinkedList();
diff --git a/forms/common-themes/src/main/java/org/keycloak/theme/DefaultKeycloakThemeProvider.java b/forms/common-themes/src/main/java/org/keycloak/theme/DefaultKeycloakThemeProvider.java
index a323945..8a8659c 100644
--- a/forms/common-themes/src/main/java/org/keycloak/theme/DefaultKeycloakThemeProvider.java
+++ b/forms/common-themes/src/main/java/org/keycloak/theme/DefaultKeycloakThemeProvider.java
@@ -1,15 +1,11 @@
package org.keycloak.theme;
import org.keycloak.freemarker.Theme;
-import org.keycloak.freemarker.ThemeLoader;
import org.keycloak.freemarker.ThemeProvider;
-import org.keycloak.models.Config;
import java.io.IOException;
import java.util.Collections;
-import java.util.HashMap;
import java.util.HashSet;
-import java.util.Map;
import java.util.Set;
/**
diff --git a/forms/common-themes/src/main/java/org/keycloak/theme/FolderThemeProvider.java b/forms/common-themes/src/main/java/org/keycloak/theme/FolderThemeProvider.java
index a76b328..101851c 100644
--- a/forms/common-themes/src/main/java/org/keycloak/theme/FolderThemeProvider.java
+++ b/forms/common-themes/src/main/java/org/keycloak/theme/FolderThemeProvider.java
@@ -2,7 +2,7 @@ package org.keycloak.theme;
import org.keycloak.freemarker.Theme;
import org.keycloak.freemarker.ThemeProvider;
-import org.keycloak.models.Config;
+import org.keycloak.Config;
import java.io.File;
import java.io.FileFilter;
@@ -19,7 +19,7 @@ public class FolderThemeProvider implements ThemeProvider {
private File rootDir;
public FolderThemeProvider() {
- String d = Config.getThemeDir();
+ String d = Config.scope("theme").get("dir");
if (d != null) {
rootDir = new File(d);
}
diff --git a/model/api/src/main/java/org/keycloak/models/KeycloakSession.java b/model/api/src/main/java/org/keycloak/models/KeycloakSession.java
index 9aa55ee..aa61bec 100755
--- a/model/api/src/main/java/org/keycloak/models/KeycloakSession.java
+++ b/model/api/src/main/java/org/keycloak/models/KeycloakSession.java
@@ -1,12 +1,14 @@
package org.keycloak.models;
+import org.keycloak.provider.Provider;
+
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
-public interface KeycloakSession {
+public interface KeycloakSession extends Provider {
KeycloakTransaction getTransaction();
RealmModel createRealm(String name);
diff --git a/model/api/src/main/java/org/keycloak/models/KeycloakSessionFactory.java b/model/api/src/main/java/org/keycloak/models/KeycloakSessionFactory.java
index 3149f9b..dba6d84 100755
--- a/model/api/src/main/java/org/keycloak/models/KeycloakSessionFactory.java
+++ b/model/api/src/main/java/org/keycloak/models/KeycloakSessionFactory.java
@@ -1,10 +1,13 @@
package org.keycloak.models;
+import org.keycloak.provider.ProviderFactory;
+import org.keycloak.provider.ProviderSession;
+
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
-public interface KeycloakSessionFactory {
- KeycloakSession createSession();
+public interface KeycloakSessionFactory extends ProviderFactory<KeycloakSession> {
+ KeycloakSession create(ProviderSession providerSession);
void close();
}
diff --git a/model/api/src/main/java/org/keycloak/models/ModelSpi.java b/model/api/src/main/java/org/keycloak/models/ModelSpi.java
new file mode 100644
index 0000000..42586e9
--- /dev/null
+++ b/model/api/src/main/java/org/keycloak/models/ModelSpi.java
@@ -0,0 +1,27 @@
+package org.keycloak.models;
+
+import org.keycloak.provider.Provider;
+import org.keycloak.provider.ProviderFactory;
+import org.keycloak.provider.Spi;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class ModelSpi implements Spi {
+
+ @Override
+ public String getName() {
+ return "model";
+ }
+
+ @Override
+ public Class<? extends Provider> getProviderClass() {
+ return KeycloakSession.class;
+ }
+
+ @Override
+ public Class<? extends ProviderFactory> getProviderFactoryClass() {
+ return KeycloakSessionFactory.class;
+ }
+
+}
diff --git a/model/api/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/model/api/src/main/resources/META-INF/services/org.keycloak.provider.Spi
new file mode 100644
index 0000000..48ff59e
--- /dev/null
+++ b/model/api/src/main/resources/META-INF/services/org.keycloak.provider.Spi
@@ -0,0 +1 @@
+org.keycloak.models.ModelSpi
\ No newline at end of file
model/jpa/pom.xml 18(+0 -18)
diff --git a/model/jpa/pom.xml b/model/jpa/pom.xml
index 15ac823..c12e9cd 100755
--- a/model/jpa/pom.xml
+++ b/model/jpa/pom.xml
@@ -32,24 +32,6 @@
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
- <artifactId>keycloak-audit-api</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.keycloak</groupId>
- <artifactId>keycloak-audit-jpa</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.keycloak</groupId>
- <artifactId>keycloak-audit-jboss-logging</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.keycloak</groupId>
<artifactId>keycloak-model-api</artifactId>
<version>${project.version}</version>
</dependency>
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakSessionFactory.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakSessionFactory.java
index 67ba543..6efe710 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakSessionFactory.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakSessionFactory.java
@@ -1,28 +1,53 @@
package org.keycloak.models.jpa;
+import org.keycloak.Config;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.provider.ProviderSession;
import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import java.util.Properties;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class JpaKeycloakSessionFactory implements KeycloakSessionFactory {
- protected EntityManagerFactory factory;
- public JpaKeycloakSessionFactory(EntityManagerFactory factory) {
- this.factory = factory;
+ protected EntityManagerFactory emf;
+
+ @Override
+ public void init(Config.Scope config) {
+ emf = Persistence.createEntityManagerFactory("jpa-keycloak-identity-store", getHibernateProperties());
+ }
+
+ @Override
+ public String getId() {
+ return "jpa";
}
@Override
- public KeycloakSession createSession() {
- return new JpaKeycloakSession(factory.createEntityManager());
+ public KeycloakSession create(ProviderSession providerSession) {
+ return new JpaKeycloakSession(emf.createEntityManager());
}
@Override
public void close() {
- factory.close();
+ emf.close();
}
+
+ // Allows to override some properties in persistence.xml by system properties
+ protected Properties getHibernateProperties() {
+ Properties result = new Properties();
+
+ for (Object property : System.getProperties().keySet()) {
+ if (property.toString().startsWith("hibernate.")) {
+ String propValue = System.getProperty(property.toString());
+ result.put(property, propValue);
+ }
+ }
+ return result;
+ }
+
}
diff --git a/model/jpa/src/main/resources/META-INF/services/org.keycloak.models.KeycloakSessionFactory b/model/jpa/src/main/resources/META-INF/services/org.keycloak.models.KeycloakSessionFactory
new file mode 100644
index 0000000..d77ce1b
--- /dev/null
+++ b/model/jpa/src/main/resources/META-INF/services/org.keycloak.models.KeycloakSessionFactory
@@ -0,0 +1 @@
+org.keycloak.models.jpa.JpaKeycloakSessionFactory
\ No newline at end of file
model/mongo/pom.xml 30(+9 -21)
diff --git a/model/mongo/pom.xml b/model/mongo/pom.xml
index 01bce2f..cab3668 100755
--- a/model/mongo/pom.xml
+++ b/model/mongo/pom.xml
@@ -45,18 +45,6 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>org.keycloak</groupId>
- <artifactId>keycloak-audit-api</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.keycloak</groupId>
- <artifactId>keycloak-audit-jboss-logging</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
@@ -103,10 +91,10 @@
</dependencies>
<properties>
- <keycloak.mongo.host>localhost</keycloak.mongo.host>
- <keycloak.mongo.port>27018</keycloak.mongo.port>
- <keycloak.mongo.db>keycloak</keycloak.mongo.db>
- <keycloak.mongo.clearOnStartup>true</keycloak.mongo.clearOnStartup>
+ <keycloak.model.mongo.host>localhost</keycloak.model.mongo.host>
+ <keycloak.model.mongo.port>27018</keycloak.model.mongo.port>
+ <keycloak.model.mongo.db>keycloak</keycloak.model.mongo.db>
+ <keycloak.model.mongo.clearOnStartup>true</keycloak.model.mongo.clearOnStartup>
</properties>
<build>
@@ -133,10 +121,10 @@
</goals>
<configuration>
<systemPropertyVariables>
- <keycloak.mongo.host>${keycloak.mongo.host}</keycloak.mongo.host>
- <keycloak.mongo.port>${keycloak.mongo.port}</keycloak.mongo.port>
- <keycloak.mongo.db>${keycloak.mongo.db}</keycloak.mongo.db>
- <keycloak.mongo.clearOnStartup>${keycloak.mongo.clearOnStartup}</keycloak.mongo.clearOnStartup>
+ <keycloak.model.mongo.host>${keycloak.model.mongo.host}</keycloak.model.mongo.host>
+ <keycloak.model.mongo.port>${keycloak.model.mongo.port}</keycloak.model.mongo.port>
+ <keycloak.model.mongo.db>${keycloak.model.mongo.db}</keycloak.model.mongo.db>
+ <keycloak.model.mongo.clearOnStartup>${keycloak.model.mongo.clearOnStartup}</keycloak.model.mongo.clearOnStartup>
</systemPropertyVariables>
<dependenciesToScan>
<dependency>org.keycloak:keycloak-model-tests</dependency>
@@ -164,7 +152,7 @@
<goal>start</goal>
</goals>
<configuration>
- <port>${keycloak.mongo.port}</port>
+ <port>${keycloak.model.mongo.port}</port>
<logging>file</logging>
<logFile>${project.build.directory}/mongodb.log</logFile>
</configuration>
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoKeycloakSessionFactory.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoKeycloakSessionFactory.java
index 6feb373..142cdbe 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoKeycloakSessionFactory.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoKeycloakSessionFactory.java
@@ -1,6 +1,11 @@
package org.keycloak.models.mongo.keycloak.adapters;
+import com.mongodb.DB;
+import com.mongodb.MongoClient;
+import com.mongodb.MongoCredential;
+import com.mongodb.ServerAddress;
import org.jboss.logging.Logger;
+import org.keycloak.Config;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.entities.AuthenticationLinkEntity;
@@ -10,7 +15,6 @@ import org.keycloak.models.entities.RequiredCredentialEntity;
import org.keycloak.models.entities.SocialLinkEntity;
import org.keycloak.models.mongo.api.MongoStore;
import org.keycloak.models.mongo.impl.MongoStoreImpl;
-import org.keycloak.models.mongo.keycloak.config.MongoClientProvider;
import org.keycloak.models.mongo.keycloak.entities.MongoApplicationEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoOAuthClientEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity;
@@ -18,6 +22,10 @@ import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoUserEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoUserSessionEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoUsernameLoginFailureEntity;
+import org.keycloak.provider.ProviderSession;
+
+import java.net.UnknownHostException;
+import java.util.Collections;
/**
* KeycloakSessionFactory implementation based on MongoDB
@@ -27,7 +35,7 @@ import org.keycloak.models.mongo.keycloak.entities.MongoUsernameLoginFailureEnti
public class MongoKeycloakSessionFactory implements KeycloakSessionFactory {
protected static final Logger logger = Logger.getLogger(MongoKeycloakSessionFactory.class);
- private static final Class<?>[] MANAGED_ENTITY_TYPES = (Class<?>[])new Class<?>[] {
+ private static final Class<?>[] MANAGED_ENTITY_TYPES = (Class<?>[]) new Class<?>[]{
MongoRealmEntity.class,
MongoUserEntity.class,
MongoRoleEntity.class,
@@ -42,21 +50,50 @@ public class MongoKeycloakSessionFactory implements KeycloakSessionFactory {
MongoUserSessionEntity.class
};
- private final MongoClientProvider mongoClientProvider;
- private final MongoStore mongoStore;
+ private MongoClient client;
+
+ private MongoStore mongoStore;
+
+ @Override
+ public String getId() {
+ return "mongo";
+ }
+
+ @Override
+ public void init(Config.Scope config) {
+ try {
+ String host = config.get("host", ServerAddress.defaultHost());
+ int port = config.getInt("port", ServerAddress.defaultPort());
+ String dbName = config.get("db", "keycloak-audit");
+ boolean clearOnStartup = config.getBoolean("clearOnStartup", false);
+
+ String user = config.get("user");
+ String password = config.get("password");
+ if (user != null && password != null) {
+ MongoCredential credential = MongoCredential.createMongoCRCredential(user, dbName, password.toCharArray());
+ client = new MongoClient(new ServerAddress(host, port), Collections.singletonList(credential));
+ } else {
+ client = new MongoClient(host, port);
+ }
+
+ DB db = client.getDB(dbName);
+
+ this.mongoStore = new MongoStoreImpl(db, clearOnStartup, MANAGED_ENTITY_TYPES);
+ } catch (UnknownHostException e) {
+ throw new RuntimeException(e);
+ }
- public MongoKeycloakSessionFactory(MongoClientProvider provider) {
- this.mongoClientProvider = provider;
- this.mongoStore = new MongoStoreImpl(provider.getDB(), provider.clearCollectionsOnStartup(), MANAGED_ENTITY_TYPES);
}
@Override
- public KeycloakSession createSession() {
+ public KeycloakSession create(ProviderSession providerSession) {
return new MongoKeycloakSession(mongoStore);
}
@Override
public void close() {
- this.mongoClientProvider.close();
+ this.client.close();
}
+
}
+
diff --git a/model/mongo/src/main/resources/META-INF/services/org.keycloak.models.KeycloakSessionFactory b/model/mongo/src/main/resources/META-INF/services/org.keycloak.models.KeycloakSessionFactory
new file mode 100644
index 0000000..47363dc
--- /dev/null
+++ b/model/mongo/src/main/resources/META-INF/services/org.keycloak.models.KeycloakSessionFactory
@@ -0,0 +1 @@
+org.keycloak.models.mongo.keycloak.adapters.MongoKeycloakSessionFactory
\ No newline at end of file
diff --git a/model/tests/src/test/java/org/keycloak/model/test/AbstractModelTest.java b/model/tests/src/test/java/org/keycloak/model/test/AbstractModelTest.java
index 2f7177b..428d4c8 100755
--- a/model/tests/src/test/java/org/keycloak/model/test/AbstractModelTest.java
+++ b/model/tests/src/test/java/org/keycloak/model/test/AbstractModelTest.java
@@ -11,10 +11,9 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
-import org.keycloak.models.Config;
+import org.keycloak.Config;
import org.keycloak.provider.ProviderSession;
import org.keycloak.provider.ProviderSessionFactory;
import org.keycloak.representations.idm.RealmRepresentation;
@@ -28,7 +27,6 @@ import org.keycloak.util.JsonSerialization;
*/
public class AbstractModelTest {
- protected static KeycloakSessionFactory factory;
protected static ProviderSessionFactory providerSessionFactory;
protected KeycloakSession identitySession;
@@ -37,41 +35,40 @@ public class AbstractModelTest {
@BeforeClass
public static void beforeClass() {
- factory = KeycloakApplication.createSessionFactory();
providerSessionFactory = KeycloakApplication.createProviderSessionFactory();
- KeycloakSession identitySession = factory.createSession();
+ ProviderSession providerSession = providerSessionFactory.createSession();
+ KeycloakSession identitySession = providerSession.getProvider(KeycloakSession.class);
try {
identitySession.getTransaction().begin();
new ApplianceBootstrap().bootstrap(identitySession, "/auth");
identitySession.getTransaction().commit();
} finally {
- identitySession.close();
+ providerSession.close();
}
}
@AfterClass
public static void afterClass() {
providerSessionFactory.close();
- factory.close();
}
@Before
public void before() throws Exception {
- identitySession = factory.createSession();
+ providerSession = providerSessionFactory.createSession();
+
+ identitySession = providerSession.getProvider(KeycloakSession.class);
identitySession.getTransaction().begin();
realmManager = new RealmManager(identitySession);
-
- providerSession = providerSessionFactory.createSession();
}
@After
public void after() throws Exception {
identitySession.getTransaction().commit();
providerSession.close();
- identitySession.close();
- identitySession = factory.createSession();
+ providerSession = providerSessionFactory.createSession();
+ identitySession = providerSession.getProvider(KeycloakSession.class);
try {
identitySession.getTransaction().begin();
@@ -84,7 +81,7 @@ public class AbstractModelTest {
identitySession.getTransaction().commit();
} finally {
- identitySession.close();
+ providerSession.close();
}
}
@@ -103,8 +100,10 @@ public class AbstractModelTest {
}
protected void resetSession() {
- identitySession.close();
- identitySession = factory.createSession();
+ providerSession.close();
+
+ providerSession = providerSessionFactory.createSession();
+ identitySession = providerSession.getProvider(KeycloakSession.class);
identitySession.getTransaction().begin();
realmManager = new RealmManager(identitySession);
}
diff --git a/model/tests/src/test/java/org/keycloak/model/test/AuthenticationManagerTest.java b/model/tests/src/test/java/org/keycloak/model/test/AuthenticationManagerTest.java
index 880ce14..a603226 100755
--- a/model/tests/src/test/java/org/keycloak/model/test/AuthenticationManagerTest.java
+++ b/model/tests/src/test/java/org/keycloak/model/test/AuthenticationManagerTest.java
@@ -164,7 +164,7 @@ public class AuthenticationManagerTest extends AbstractModelTest {
realm.setAccessTokenLifespan(1000);
realm.addRequiredCredential(CredentialRepresentation.PASSWORD);
realm.setAuthenticationProviders(Arrays.asList(AuthenticationProviderModel.DEFAULT_PROVIDER));
- protector = new BruteForceProtector(factory);
+ protector = new BruteForceProtector(providerSessionFactory);
protector.start();
am = new AuthenticationManager(providerSession, protector);
diff --git a/picketlink/keycloak-picketlink-api/src/main/java/org/keycloak/picketlink/IdentityManagerSpi.java b/picketlink/keycloak-picketlink-api/src/main/java/org/keycloak/picketlink/IdentityManagerSpi.java
new file mode 100644
index 0000000..42111da
--- /dev/null
+++ b/picketlink/keycloak-picketlink-api/src/main/java/org/keycloak/picketlink/IdentityManagerSpi.java
@@ -0,0 +1,25 @@
+package org.keycloak.picketlink;
+
+import org.keycloak.provider.Provider;
+import org.keycloak.provider.ProviderFactory;
+import org.keycloak.provider.Spi;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class IdentityManagerSpi implements Spi {
+ @Override
+ public String getName() {
+ return "picketlink-identity-manager";
+ }
+
+ @Override
+ public Class<? extends Provider> getProviderClass() {
+ return IdentityManagerProvider.class;
+ }
+
+ @Override
+ public Class<? extends ProviderFactory> getProviderFactoryClass() {
+ return IdentityManagerProviderFactory.class;
+ }
+}
diff --git a/picketlink/keycloak-picketlink-api/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/picketlink/keycloak-picketlink-api/src/main/resources/META-INF/services/org.keycloak.provider.Spi
new file mode 100644
index 0000000..ffcb6e5
--- /dev/null
+++ b/picketlink/keycloak-picketlink-api/src/main/resources/META-INF/services/org.keycloak.provider.Spi
@@ -0,0 +1 @@
+org.keycloak.picketlink.IdentityManagerSpi
\ No newline at end of file
diff --git a/picketlink/keycloak-picketlink-realm/src/main/java/org/keycloak/picketlink/realm/RealmIdentityManagerProviderFactory.java b/picketlink/keycloak-picketlink-realm/src/main/java/org/keycloak/picketlink/realm/RealmIdentityManagerProviderFactory.java
index 83b5970..236cff6 100644
--- a/picketlink/keycloak-picketlink-realm/src/main/java/org/keycloak/picketlink/realm/RealmIdentityManagerProviderFactory.java
+++ b/picketlink/keycloak-picketlink-realm/src/main/java/org/keycloak/picketlink/realm/RealmIdentityManagerProviderFactory.java
@@ -1,5 +1,6 @@
package org.keycloak.picketlink.realm;
+import org.keycloak.Config;
import org.keycloak.picketlink.IdentityManagerProvider;
import org.keycloak.picketlink.IdentityManagerProviderFactory;
import org.keycloak.provider.ProviderSession;
@@ -20,7 +21,7 @@ public class RealmIdentityManagerProviderFactory implements IdentityManagerProvi
}
@Override
- public void init() {
+ public void init(Config.Scope config) {
partitionManagerRegistry = new PartitionManagerRegistry();
}
@@ -33,8 +34,4 @@ public class RealmIdentityManagerProviderFactory implements IdentityManagerProvi
return "realm";
}
- @Override
- public boolean lazyLoad() {
- return false;
- }
}
diff --git a/project-integrations/aerogear-ups/auth-server/src/main/java/org/aerogear/ups/security/UpsSecurityApplication.java b/project-integrations/aerogear-ups/auth-server/src/main/java/org/aerogear/ups/security/UpsSecurityApplication.java
index eddeace..b7b0d56 100755
--- a/project-integrations/aerogear-ups/auth-server/src/main/java/org/aerogear/ups/security/UpsSecurityApplication.java
+++ b/project-integrations/aerogear-ups/auth-server/src/main/java/org/aerogear/ups/security/UpsSecurityApplication.java
@@ -4,6 +4,7 @@ import org.jboss.resteasy.core.Dispatcher;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
+import org.keycloak.provider.ProviderSession;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.resources.KeycloakApplication;
@@ -22,7 +23,8 @@ public class UpsSecurityApplication extends KeycloakApplication {
@Override
protected void setupDefaultRealm(String contextPath) {
super.setupDefaultRealm(contextPath);
- KeycloakSession session = factory.createSession();
+ ProviderSession providerSession = providerSessionFactory.createSession();
+ KeycloakSession session = providerSession.getProvider(KeycloakSession.class);
session.getTransaction().begin();
// disable master realm by deleting the admin user.
@@ -33,7 +35,7 @@ public class UpsSecurityApplication extends KeycloakApplication {
if (admin != null) master.removeUser(admin.getLoginName());
session.getTransaction().commit();
} finally {
- session.close();
+ providerSession.close();
}
}
server/pom.xml 33(+33 -0)
diff --git a/server/pom.xml b/server/pom.xml
index 3e29a02..1276b48 100755
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -225,6 +225,39 @@
<scope>provided</scope>
</dependency>
+ <!-- Mongo dependencies -->
+ <dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-model-mongo</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-audit-mongo</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.mongodb</groupId>
+ <artifactId>mongo-java-driver</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.picketlink</groupId>
+ <artifactId>picketlink-common</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.picketlink</groupId>
+ <artifactId>picketlink-idm-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.picketlink</groupId>
+ <artifactId>picketlink-idm-impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.picketlink</groupId>
+ <artifactId>picketlink-idm-simple-schema</artifactId>
+ </dependency>
+
<!-- export/import -->
<dependency>
<groupId>org.keycloak</groupId>
diff --git a/server/src/main/resources/META-INF/keycloak-server.json b/server/src/main/resources/META-INF/keycloak-server.json
new file mode 100644
index 0000000..62405d9
--- /dev/null
+++ b/server/src/main/resources/META-INF/keycloak-server.json
@@ -0,0 +1,26 @@
+{
+ "admin": {
+ "realm": "keycloak-admin"
+ },
+
+ "audit": {
+ "provider": "jpa"
+ },
+
+ "model": {
+ "provider": "jpa"
+ },
+
+ "timer": {
+ "provider": "basic"
+ },
+
+ "theme": {
+ "default": "keycloak",
+ "dir": "${jboss.server.config.dir}/themes"
+ },
+
+ "scheduled": {
+ "interval": 900
+ }
+}
\ No newline at end of file
diff --git a/server/src/main/resources/META-INF/persistence.xml b/server/src/main/resources/META-INF/persistence.xml
index a75390a..90b1742 100755
--- a/server/src/main/resources/META-INF/persistence.xml
+++ b/server/src/main/resources/META-INF/persistence.xml
@@ -25,6 +25,7 @@
<properties>
<property name="hibernate.hbm2ddl.auto" value="update" />
+ <property name="jboss.as.jpa.managed" value="false" />
</properties>
</persistence-unit>
@@ -36,6 +37,7 @@
<properties>
<property name="hibernate.hbm2ddl.auto" value="update" />
+ <property name="jboss.as.jpa.managed" value="false" />
</properties>
</persistence-unit>
services/pom.xml 1(+1 -0)
diff --git a/services/pom.xml b/services/pom.xml
index af526e7..6b8ceef 100755
--- a/services/pom.xml
+++ b/services/pom.xml
@@ -102,6 +102,7 @@
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
<scope>provided</scope>
</dependency>
+
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
diff --git a/services/src/main/java/org/keycloak/services/DefaultProviderSession.java b/services/src/main/java/org/keycloak/services/DefaultProviderSession.java
index cd6a9c9..aee7a41 100755
--- a/services/src/main/java/org/keycloak/services/DefaultProviderSession.java
+++ b/services/src/main/java/org/keycloak/services/DefaultProviderSession.java
@@ -6,6 +6,8 @@ import org.keycloak.provider.ProviderSession;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -13,6 +15,7 @@ import java.util.Set;
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class DefaultProviderSession implements ProviderSession {
+
private DefaultProviderSessionFactory factory;
private Map<Integer, Provider> providers = new HashMap<Integer, Provider>();
@@ -21,8 +24,16 @@ public class DefaultProviderSession implements ProviderSession {
}
public <T extends Provider> T getProvider(Class<T> clazz) {
- String id = factory.getDefaultProvider(clazz);
- return id != null ? getProvider(clazz, id) : null;
+ Integer hash = clazz.hashCode();
+ T provider = (T) providers.get(hash);
+ if (provider == null) {
+ ProviderFactory<T> providerFactory = factory.getProviderFactory(clazz);
+ if (providerFactory != null) {
+ provider = providerFactory.create(this);
+ providers.put(hash, provider);
+ }
+ }
+ return provider;
}
public <T extends Provider> T getProvider(Class<T> clazz, String id) {
@@ -39,15 +50,14 @@ public class DefaultProviderSession implements ProviderSession {
}
public <T extends Provider> Set<String> listProviderIds(Class<T> clazz) {
- return factory.providerIds(clazz);
+ return factory.getAllProviderIds(clazz);
}
@Override
public <T extends Provider> Set<T> getAllProviders(Class<T> clazz) {
- Set<String> providerIds = listProviderIds(clazz);
Set<T> providers = new HashSet<T>();
- for (String providerId : providerIds) {
- providers.add(getProvider(clazz, providerId));
+ for (String id : listProviderIds(clazz)) {
+ providers.add(getProvider(clazz, id));
}
return providers;
}
diff --git a/services/src/main/java/org/keycloak/services/DefaultProviderSessionFactory.java b/services/src/main/java/org/keycloak/services/DefaultProviderSessionFactory.java
index fbc0993..128c272 100755
--- a/services/src/main/java/org/keycloak/services/DefaultProviderSessionFactory.java
+++ b/services/src/main/java/org/keycloak/services/DefaultProviderSessionFactory.java
@@ -1,71 +1,99 @@
package org.keycloak.services;
+import org.jboss.logging.Logger;
+import org.keycloak.Config;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
-import org.keycloak.provider.ProviderFactoryLoader;
import org.keycloak.provider.ProviderSession;
import org.keycloak.provider.ProviderSessionFactory;
+import org.keycloak.provider.Spi;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
+import java.util.ServiceLoader;
import java.util.Set;
public class DefaultProviderSessionFactory implements ProviderSessionFactory {
- private Map<Class<? extends Provider>, ProviderFactoryLoader> loaders = new HashMap<Class<? extends Provider>, ProviderFactoryLoader>();
- private Map<Class<? extends Provider>, String> defaultFactories = new HashMap<Class<? extends Provider>, String>();
+ private static final Logger log = Logger.getLogger(DefaultProviderSessionFactory.class);
- public ProviderSession createSession() {
- return new DefaultProviderSession(this);
- }
+ private Map<Class<? extends Provider>, String> provider = new HashMap<Class<? extends Provider>, String>();
+ private Map<Class<? extends Provider>, Map<String, ProviderFactory>> factoriesMap = new HashMap<Class<? extends Provider>, Map<String, ProviderFactory>>();
- public void close() {
- for (ProviderFactoryLoader loader : loaders.values()) {
- loader.close();
+ public void init() {
+ for (Spi spi : ServiceLoader.load(Spi.class)) {
+ Map<String, ProviderFactory> factories = new HashMap<String, ProviderFactory>();
+ factoriesMap.put(spi.getProviderClass(), factories);
+
+ String provider = Config.getProvider(spi.getName());
+ if (provider != null) {
+ this.provider.put(spi.getProviderClass(), provider);
+
+ ProviderFactory factory = loadProviderFactory(spi, provider);
+ Config.Scope scope = Config.scope(spi.getName(), provider);
+ factory.init(scope);
+ log.debug("Initialized " + factory.getClass().getName() + " (config = " + scope + ")");
+
+ factories.put(factory.getId(), factory);
+
+ log.info("Loaded SPI " + spi.getName() + " (provider = " + provider + ")");
+ } else {
+ for (ProviderFactory factory : ServiceLoader.load(spi.getProviderFactoryClass())) {
+ Config.Scope scope = Config.scope(spi.getName(), factory.getId());
+ factory.init(scope);
+ log.debug("Initialized " + factory.getClass().getName() + " (config = " + scope + ")");
+
+ factories.put(factory.getId(), factory);
+ }
+
+ if (factories.size() == 1) {
+ provider = factories.values().iterator().next().getId();
+ this.provider.put(spi.getProviderClass(), provider);
+
+ log.info("Loaded SPI " + spi.getName() + " (provider = " + provider + ")");
+ } else {
+ log.info("Loaded SPI " + spi.getName() + " (providers = " + factories.keySet() + ")");
+ }
+ }
}
}
- public <T extends Provider> ProviderFactory<T> getProviderFactory(Class<T> clazz) {
- String id = defaultFactories.get(clazz);
- if (id == null) {
- return null;
+ private ProviderFactory loadProviderFactory(Spi spi, String id) {
+ for (ProviderFactory factory : ServiceLoader.load(spi.getProviderFactoryClass())) {
+ if (factory.getId().equals(id)){
+ return factory;
+ }
}
- return getProviderFactory(clazz, id);
- }
-
- public <T extends Provider> ProviderFactory<T> getProviderFactory(Class<T> clazz, String id) {
- ProviderFactoryLoader loader = getLoader(clazz);
- return loader != null ? loader.find(id) : null;
- }
-
- public Set<String> providerIds(Class<? extends Provider> clazz) {
- ProviderFactoryLoader loader = getLoader(clazz);
- return loader != null ? loader.providerIds() : null;
+ throw new RuntimeException("Failed to find provider " + id + " for " + spi.getName());
}
- public String getDefaultProvider(Class<? extends Provider> clazz) {
- return defaultFactories.get(clazz);
+ public ProviderSession createSession() {
+ return new DefaultProviderSession(this);
}
- public void registerLoader(Class<? extends Provider> clazz, ProviderFactoryLoader loader) {
- loaders.put(clazz, loader);
-
+ <T extends Provider> ProviderFactory<T> getProviderFactory(Class<T> clazz) {
+ return getProviderFactory(clazz, provider.get(clazz));
}
- public void registerLoader(Class<? extends Provider> clazz, ProviderFactoryLoader loader, String defaultProvider) {
- loaders.put(clazz, loader);
- defaultFactories.put(clazz, defaultProvider);
-
+ <T extends Provider> ProviderFactory<T> getProviderFactory(Class<T> clazz, String id) {
+ return factoriesMap.get(clazz).get(id);
}
- public void init() {
- for (ProviderFactoryLoader l : loaders.values()) {
- l.init();
+ <T extends Provider> Set<String> getAllProviderIds(Class<T> clazz) {
+ Set<String> ids = new HashSet<String>();
+ for (ProviderFactory f : factoriesMap.get(clazz).values()) {
+ ids.add(f.getId());
}
+ return ids;
}
- private <T extends Provider> ProviderFactoryLoader getLoader(Class<T> clazz) {
- return loaders.get(clazz);
+ public void close() {
+ for (Map<String, ProviderFactory> factories : factoriesMap.values()) {
+ for (ProviderFactory factory : factories.values()) {
+ factory.close();
+ }
+ }
}
}
diff --git a/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java b/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java
index 97a5f0f..68106f9 100755
--- a/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java
+++ b/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java
@@ -32,9 +32,7 @@ public class KeycloakSessionServletFilter implements Filter {
ResteasyProviderFactory.pushContext(ProviderSession.class, providerSession);
- KeycloakSessionFactory factory = (KeycloakSessionFactory) servletRequest.getServletContext().getAttribute(KeycloakSessionFactory.class.getName());
- if (factory == null) throw new ServletException("Factory was null");
- KeycloakSession session = factory.createSession();
+ KeycloakSession session = providerSession.getProvider(KeycloakSession.class);
ResteasyProviderFactory.pushContext(KeycloakSession.class, session);
KeycloakTransaction tx = session.getTransaction();
ResteasyProviderFactory.pushContext(KeycloakTransaction.class, tx);
@@ -56,7 +54,6 @@ public class KeycloakSessionServletFilter implements Filter {
if (tx.isActive()) tx.rollback();
throw ex;
} finally {
- session.close();
providerSession.close();
ResteasyProviderFactory.clearContextData();
}
diff --git a/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java b/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
index 1ef7d7c..653cdc6 100755
--- a/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
+++ b/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
@@ -6,14 +6,15 @@ import org.jboss.logging.Logger;
import org.keycloak.models.AdminRoles;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.AuthenticationProviderModel;
-import org.keycloak.models.Config;
+import org.keycloak.Config;
import org.keycloak.models.Constants;
import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
+import org.keycloak.provider.ProviderSession;
+import org.keycloak.provider.ProviderSessionFactory;
import org.keycloak.representations.idm.CredentialRepresentation;
import java.util.Collections;
@@ -26,26 +27,25 @@ public class ApplianceBootstrap {
private static final Logger logger = Logger.getLogger(ApplianceBootstrap.class);
- public void bootstrap(KeycloakSessionFactory factory, String contextPath) {
- KeycloakSession session = factory.createSession();
+ public void bootstrap(ProviderSessionFactory factory, String contextPath) {
+ ProviderSession providerSession = factory.createSession();
+ KeycloakSession session = providerSession.getProvider(KeycloakSession.class);
session.getTransaction().begin();
try {
bootstrap(session, contextPath);
session.getTransaction().commit();
} finally {
- session.close();
+ providerSession.close();
}
-
}
public void bootstrap(KeycloakSession session, String contextPath) {
- if (session.getRealm(Config.getAdminRealm()) != null) {
+ String adminRealmName = Config.getAdminRealm();
+ if (session.getRealm(adminRealmName) != null) {
return;
}
- String adminRealmName = Config.getAdminRealm();
-
logger.info("Initializing " + adminRealmName + " realm");
RealmManager manager = new RealmManager(session);
diff --git a/services/src/main/java/org/keycloak/services/managers/BruteForceProtector.java b/services/src/main/java/org/keycloak/services/managers/BruteForceProtector.java
index a941f89..f231825 100755
--- a/services/src/main/java/org/keycloak/services/managers/BruteForceProtector.java
+++ b/services/src/main/java/org/keycloak/services/managers/BruteForceProtector.java
@@ -6,6 +6,8 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UsernameLoginFailureModel;
+import org.keycloak.provider.ProviderSession;
+import org.keycloak.provider.ProviderSessionFactory;
import org.keycloak.services.ClientConnection;
import java.util.ArrayList;
@@ -25,7 +27,7 @@ public class BruteForceProtector implements Runnable {
protected volatile boolean run = true;
protected int maxDeltaTimeSeconds = 60 * 60 * 12; // 12 hours
- protected KeycloakSessionFactory factory;
+ protected ProviderSessionFactory factory;
protected CountDownLatch shutdownLatch = new CountDownLatch(1);
protected volatile long failures;
@@ -73,7 +75,7 @@ public class BruteForceProtector implements Runnable {
}
}
- public BruteForceProtector(KeycloakSessionFactory factory) {
+ public BruteForceProtector(ProviderSessionFactory factory) {
this.factory = factory;
}
@@ -160,7 +162,8 @@ public class BruteForceProtector implements Runnable {
events.add(take);
queue.drainTo(events, TRANSACTION_SIZE);
Collections.sort(events); // we sort to avoid deadlock due to ordered updates. Maybe I'm overthinking this.
- KeycloakSession session = factory.createSession();
+ ProviderSession providerSession = factory.createSession();
+ KeycloakSession session = providerSession.getProvider(KeycloakSession.class);
session.getTransaction().begin();
try {
for (LoginEvent event : events) {
@@ -179,7 +182,7 @@ public class BruteForceProtector implements Runnable {
}
}
events.clear();
- session.close();
+ providerSession.close();
}
} catch (Exception e) {
logger.error("Failed processing event", e);
diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
index 43e9630..19c441f 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -7,7 +7,7 @@ import org.keycloak.models.ApplicationModel;
import org.keycloak.models.AuthenticationLinkModel;
import org.keycloak.models.AuthenticationProviderModel;
import org.keycloak.models.ClientModel;
-import org.keycloak.models.Config;
+import org.keycloak.Config;
import org.keycloak.models.Constants;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.OAuthClientModel;
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java
index 889990f..ad5cd03 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java
@@ -10,14 +10,12 @@ import org.keycloak.freemarker.Theme;
import org.keycloak.freemarker.ThemeLoader;
import org.keycloak.models.AdminRoles;
import org.keycloak.models.ApplicationModel;
-import org.keycloak.models.Config;
import org.keycloak.models.Constants;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderSession;
-import org.keycloak.services.ForbiddenException;
import org.keycloak.services.managers.AppAuthManager;
import org.keycloak.services.managers.ApplicationManager;
import org.keycloak.services.managers.RealmManager;
@@ -280,12 +278,7 @@ public class AdminConsole {
try {
//logger.info("getting resource: " + path + " uri: " + uriInfo.getRequestUri().toString());
- String themeName = realm.getAdminTheme();
- if (themeName == null || themeName.trim().equals("")) {
- themeName = Config.getThemeAdmin();
- }
-
- Theme theme = ThemeLoader.createTheme(themeName, Theme.Type.ADMIN);
+ Theme theme = ThemeLoader.createTheme(realm.getAdminTheme(), Theme.Type.ADMIN);
InputStream resource = theme.getResourceAsStream(path);
if (resource != null) {
String contentType = mimeTypes.getContentType(path);
diff --git a/services/src/main/java/org/keycloak/services/resources/Cors.java b/services/src/main/java/org/keycloak/services/resources/Cors.java
index a391ab3..9dbcd39 100755
--- a/services/src/main/java/org/keycloak/services/resources/Cors.java
+++ b/services/src/main/java/org/keycloak/services/resources/Cors.java
@@ -1,5 +1,7 @@
package org.keycloak.services.resources;
+import java.util.Arrays;
+import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -8,7 +10,7 @@ import javax.ws.rs.core.Response.ResponseBuilder;
import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.models.ClientModel;
-import org.keycloak.models.UserModel;
+import org.keycloak.util.CollectionUtil;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -16,20 +18,25 @@ import org.keycloak.models.UserModel;
public class Cors {
public static final long DEFAULT_MAX_AGE = TimeUnit.HOURS.toSeconds(1);
- public static final String DEFAULT_ALLOW_METHODS = "GET, OPTIONS";
+ public static final String DEFAULT_ALLOW_METHODS = "GET, HEAD, OPTIONS";
+ public static final String DEFAULT_ALLOW_HEADERS = "Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers";
- public static final String ORIGIN = "Origin";
+ public static final String ORIGIN_HEADER = "Origin";
+ public static final String AUTHORIZATION_HEADER = "Authorization";
public static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin";
public static final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods";
public static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers";
+ public static final String ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers";
public static final String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials";
public static final String ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age";
+
private HttpRequest request;
private ResponseBuilder response;
private Set<String> allowedOrigins;
- private String[] allowedMethods;
+ private Set<String> allowedMethods;
+ private Set<String> exposedHeaders;
private boolean preflight;
private boolean auth;
@@ -61,12 +68,17 @@ public class Cors {
}
public Cors allowedMethods(String... allowedMethods) {
- this.allowedMethods = allowedMethods;
+ this.allowedMethods = new HashSet<String>(Arrays.asList(allowedMethods));
+ return this;
+ }
+
+ public Cors exposedHeaders(String... exposedHeaders) {
+ this.exposedHeaders = new HashSet<String>(Arrays.asList(exposedHeaders));
return this;
}
public Response build() {
- String origin = request.getHttpHeaders().getRequestHeaders().getFirst(ORIGIN);
+ String origin = request.getHttpHeaders().getRequestHeaders().getFirst(ORIGIN_HEADER);
if (origin == null) {
return response.build();
}
@@ -78,21 +90,20 @@ public class Cors {
response.header(ACCESS_CONTROL_ALLOW_ORIGIN, origin);
if (allowedMethods != null) {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < allowedMethods.length; i++) {
- if (i > 0) {
- sb.append(", ");
- }
- sb.append(allowedMethods[i]);
- }
- response.header(ACCESS_CONTROL_ALLOW_METHODS, sb.toString());
+ response.header(ACCESS_CONTROL_ALLOW_METHODS, CollectionUtil.join(allowedMethods));
} else {
response.header(ACCESS_CONTROL_ALLOW_METHODS, DEFAULT_ALLOW_METHODS);
}
+ if (exposedHeaders != null) {
+ response.header(ACCESS_CONTROL_EXPOSE_HEADERS, CollectionUtil.join(exposedHeaders));
+ }
+
response.header(ACCESS_CONTROL_ALLOW_CREDENTIALS, Boolean.toString(auth));
if (auth) {
- response.header(ACCESS_CONTROL_ALLOW_HEADERS, "Authorization");
+ response.header(ACCESS_CONTROL_ALLOW_HEADERS, String.format("%s, %s", DEFAULT_ALLOW_HEADERS, AUTHORIZATION_HEADER));
+ } else {
+ response.header(ACCESS_CONTROL_ALLOW_HEADERS, DEFAULT_ALLOW_HEADERS);
}
response.header(ACCESS_CONTROL_MAX_AGE, DEFAULT_MAX_AGE);
diff --git a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
index 63396a1..dec4752 100755
--- a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
+++ b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
@@ -1,39 +1,30 @@
package org.keycloak.services.resources;
-import org.jboss.resteasy.core.Dispatcher;
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.map.ObjectMapper;
import org.jboss.logging.Logger;
+import org.jboss.resteasy.core.Dispatcher;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.keycloak.Config;
import org.keycloak.SkeletonKeyContextResolver;
-import org.keycloak.audit.AuditListener;
-import org.keycloak.audit.AuditListenerFactory;
-import org.keycloak.audit.AuditProvider;
-import org.keycloak.audit.AuditProviderFactory;
-import org.keycloak.authentication.AuthenticationProvider;
-import org.keycloak.authentication.AuthenticationProviderFactory;
import org.keycloak.exportimport.ExportImportProvider;
-import org.keycloak.models.Config;
import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.ModelProvider;
import org.keycloak.models.RealmModel;
-import org.keycloak.provider.ProviderFactory;
-import org.keycloak.provider.ProviderFactoryLoader;
import org.keycloak.provider.ProviderSession;
+import org.keycloak.provider.ProviderSessionFactory;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.DefaultProviderSessionFactory;
-import org.keycloak.provider.ProviderSessionFactory;
import org.keycloak.services.managers.ApplianceBootstrap;
import org.keycloak.services.managers.BruteForceProtector;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.SocialRequestManager;
import org.keycloak.services.managers.TokenManager;
import org.keycloak.services.resources.admin.AdminRoot;
-import org.keycloak.models.utils.ModelProviderUtils;
import org.keycloak.services.scheduled.ClearExpiredAuditEvents;
import org.keycloak.services.scheduled.ClearExpiredUserSessions;
import org.keycloak.services.scheduled.ScheduledTaskRunner;
+import org.keycloak.services.util.JsonConfigProvider;
import org.keycloak.timer.TimerProvider;
-import org.keycloak.timer.TimerProviderFactory;
import org.keycloak.util.JsonSerialization;
import org.keycloak.util.ProviderLoader;
@@ -41,12 +32,13 @@ import javax.servlet.ServletContext;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
+import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
-import java.util.Date;
+import java.net.URL;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
@@ -63,22 +55,21 @@ public class KeycloakApplication extends Application {
protected Set<Object> singletons = new HashSet<Object>();
protected Set<Class<?>> classes = new HashSet<Class<?>>();
- protected KeycloakSessionFactory factory;
protected ProviderSessionFactory providerSessionFactory;
protected String contextPath;
public KeycloakApplication(@Context ServletContext context, @Context Dispatcher dispatcher) {
+ loadConfig();
+
+ this.providerSessionFactory = createProviderSessionFactory();
+
dispatcher.getDefaultContextObjects().put(KeycloakApplication.class, this);
this.contextPath = context.getContextPath();
- this.factory = createSessionFactory();
- BruteForceProtector protector = new BruteForceProtector(factory);
+ BruteForceProtector protector = new BruteForceProtector(providerSessionFactory);
dispatcher.getDefaultContextObjects().put(BruteForceProtector.class, protector);
ResteasyProviderFactory.pushContext(BruteForceProtector.class, protector); // for injection
protector.start();
context.setAttribute(BruteForceProtector.class.getName(), protector);
- this.providerSessionFactory = createProviderSessionFactory();
- context.setAttribute(KeycloakSessionFactory.class.getName(), factory);
-
context.setAttribute(ProviderSessionFactory.class.getName(), this.providerSessionFactory);
TokenManager tokenManager = new TokenManager();
@@ -95,7 +86,7 @@ public class KeycloakApplication extends Application {
setupDefaultRealm(context.getContextPath());
- setupScheduledTasks(providerSessionFactory, factory);
+ setupScheduledTasks(providerSessionFactory);
importRealms(context);
checkExportImportProvider();
@@ -115,55 +106,38 @@ public class KeycloakApplication extends Application {
return uriInfo.getBaseUriBuilder().replacePath(getContextPath()).build();
}
- protected void setupDefaultRealm(String contextPath) {
- new ApplianceBootstrap().bootstrap(factory, contextPath);
- }
-
+ protected void loadConfig() {
+ try {
+ URL config = Thread.currentThread().getContextClassLoader().getResource("META-INF/keycloak-server.json");
- public static KeycloakSessionFactory createSessionFactory() {
- ModelProvider provider = ModelProviderUtils.getConfiguredModelProvider();
+ if (config != null) {
+ JsonNode node = new ObjectMapper().readTree(config);
+ Config.init(new JsonConfigProvider(node));
- if (provider != null) {
- log.debug("Model provider: " + provider.getId());
- return provider.createFactory();
+ log.info("Loaded config from " + config);
+ return;
+ }
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to load config", e);
}
+ }
- throw new RuntimeException("Model provider not found");
+ protected void setupDefaultRealm(String contextPath) {
+ new ApplianceBootstrap().bootstrap(providerSessionFactory, contextPath);
}
public static DefaultProviderSessionFactory createProviderSessionFactory() {
DefaultProviderSessionFactory factory = new DefaultProviderSessionFactory();
-
- factory.registerLoader(AuditProvider.class, ProviderFactoryLoader.create(AuditProviderFactory.class), Config.getAuditProvider());
- factory.registerLoader(AuditListener.class, ProviderFactoryLoader.create(AuditListenerFactory.class));
- factory.registerLoader(TimerProvider.class, ProviderFactoryLoader.create(TimerProviderFactory.class), Config.getTimerProvider());
- try {
- Class identityManagerProvider = Class.forName("org.keycloak.picketlink.IdentityManagerProvider");
- Class identityManagerProviderFactory = Class.forName("org.keycloak.picketlink.IdentityManagerProviderFactory");
- factory.registerLoader(identityManagerProvider, ProviderFactoryLoader.create(identityManagerProviderFactory), Config.getIdentityManagerProvider());
- } catch (ClassNotFoundException e) {
- log.warn("Picketlink libraries not installed for IdentityManagerProviderFactory");
- }
-
- factory.registerLoader(AuthenticationProvider.class, ProviderFactoryLoader.create(AuthenticationProviderFactory.class));
factory.init();
-
return factory;
}
- public static void setupScheduledTasks(final ProviderSessionFactory providerSessionFactory, final KeycloakSessionFactory keycloakSessionFactory) {
- ProviderFactory<TimerProvider> timerFactory = providerSessionFactory.getProviderFactory(TimerProvider.class);
- if (timerFactory == null) {
- log.error("Can't setup schedule tasks, no timer provider found");
- return;
- }
- TimerProvider timer = timerFactory.create(null);
- timer.schedule(new ScheduledTaskRunner(keycloakSessionFactory, providerSessionFactory, new ClearExpiredAuditEvents()), Config.getAuditExpirationSchedule());
- timer.schedule(new ScheduledTaskRunner(keycloakSessionFactory, providerSessionFactory, new ClearExpiredUserSessions()), Config.getUserExpirationSchedule());
- }
+ public static void setupScheduledTasks(final ProviderSessionFactory providerSessionFactory) {
+ long interval = Config.scope("scheduled").getLong("interval") * 1000;
- public KeycloakSessionFactory getFactory() {
- return factory;
+ TimerProvider timer = providerSessionFactory.createSession().getProvider(TimerProvider.class);
+ timer.schedule(new ScheduledTaskRunner(providerSessionFactory, new ClearExpiredAuditEvents()), interval);
+ timer.schedule(new ScheduledTaskRunner(providerSessionFactory, new ClearExpiredUserSessions()), interval);
}
public ProviderSessionFactory getProviderSessionFactory() {
@@ -215,7 +189,8 @@ public class KeycloakApplication extends Application {
}
public void importRealm(RealmRepresentation rep, String from) {
- KeycloakSession session = factory.createSession();
+ ProviderSession providerSession = providerSessionFactory.createSession();
+ KeycloakSession session = providerSession.getProvider(KeycloakSession.class);
try {
session.getTransaction().begin();
RealmManager manager = new RealmManager(session);
@@ -238,7 +213,7 @@ public class KeycloakApplication extends Application {
session.getTransaction().commit();
} finally {
- session.close();
+ providerSession.close();
}
}
@@ -255,7 +230,7 @@ public class KeycloakApplication extends Application {
if (providers.hasNext()) {
ExportImportProvider exportImport = providers.next();
- exportImport.checkExportImport(factory);
+ exportImport.checkExportImport(providerSessionFactory);
} else {
log.warn("No ExportImportProvider found!");
}
diff --git a/services/src/main/java/org/keycloak/services/resources/TokenService.java b/services/src/main/java/org/keycloak/services/resources/TokenService.java
index d1e51ac..d9c12de 100755
--- a/services/src/main/java/org/keycloak/services/resources/TokenService.java
+++ b/services/src/main/java/org/keycloak/services/resources/TokenService.java
@@ -125,8 +125,7 @@ public class TokenService {
}
public static UriBuilder tokenServiceBaseUrl(UriBuilder baseUriBuilder) {
- UriBuilder base = baseUriBuilder.path(RealmsResource.class).path(RealmsResource.class, "getTokenService");
- return base;
+ return baseUriBuilder.path(RealmsResource.class).path(RealmsResource.class, "getTokenService");
}
public static UriBuilder accessCodeToTokenUrl(UriInfo uriInfo) {
@@ -295,7 +294,7 @@ public class TokenService {
ClientModel client = authorizeClient(authorizationHeader, form, audit);
String refreshToken = form.getFirst(OAuth2Constants.REFRESH_TOKEN);
- AccessToken accessToken = null;
+ AccessToken accessToken;
try {
accessToken = tokenManager.refreshAccessToken(uriInfo, realm, client, refreshToken, audit);
} catch (OAuthErrorException e) {
@@ -314,7 +313,7 @@ public class TokenService {
audit.success();
- return Cors.add(request, Response.ok(res, MediaType.APPLICATION_JSON_TYPE)).auth().allowedOrigins(client).allowedMethods("POST").build();
+ return Cors.add(request, Response.ok(res, MediaType.APPLICATION_JSON_TYPE)).auth().allowedOrigins(client).allowedMethods("POST").exposedHeaders(Cors.ACCESS_CONTROL_ALLOW_METHODS).build();
}
@Path("auth/request/login")
@@ -502,7 +501,7 @@ public class TokenService {
credentials.setValue(formData.getFirst("password"));
boolean passwordUpdateSuccessful;
- String passwordUpdateError = null;
+ String passwordUpdateError;
try {
passwordUpdateSuccessful = AuthenticationProviderManager.getManager(realm, providerSession).updatePassword(user, formData.getFirst("password"));
passwordUpdateError = "Password update failed";
@@ -658,12 +657,12 @@ public class TokenService {
audit.success();
- return Cors.add(request, Response.ok(res)).auth().allowedOrigins(client).allowedMethods("POST").build();
+ return Cors.add(request, Response.ok(res)).auth().allowedOrigins(client).allowedMethods("POST").exposedHeaders(Cors.ACCESS_CONTROL_ALLOW_METHODS).build();
}
protected ClientModel authorizeClient(String authorizationHeader, MultivaluedMap<String, String> formData, Audit audit) {
- String client_id = null;
- String clientSecret = null;
+ String client_id;
+ String clientSecret;
if (authorizationHeader != null) {
String[] usernameSecret = BasicAuthHelper.parseHeader(authorizationHeader);
if (usernameSecret == null) {
@@ -1008,11 +1007,7 @@ public class TokenService {
}
private boolean checkSsl() {
- if (realm.isSslNotRequired()) {
- return true;
- }
-
- return uriInfo.getBaseUri().getScheme().equals("https");
+ return realm.isSslNotRequired() || uriInfo.getBaseUri().getScheme().equals("https");
}
}
diff --git a/services/src/main/java/org/keycloak/services/scheduled/ScheduledTaskRunner.java b/services/src/main/java/org/keycloak/services/scheduled/ScheduledTaskRunner.java
index 1caa290..275b43b 100644
--- a/services/src/main/java/org/keycloak/services/scheduled/ScheduledTaskRunner.java
+++ b/services/src/main/java/org/keycloak/services/scheduled/ScheduledTaskRunner.java
@@ -13,20 +13,18 @@ public class ScheduledTaskRunner implements Runnable {
private static final Logger logger = Logger.getLogger(ScheduledTaskRunner.class);
- private final KeycloakSessionFactory keycloakSessionFactory;
private final ProviderSessionFactory providerSessionFactory;
private final ScheduledTask task;
- public ScheduledTaskRunner(KeycloakSessionFactory keycloakSessionFactory, ProviderSessionFactory providerSessionFactory, ScheduledTask task) {
- this.keycloakSessionFactory = keycloakSessionFactory;
+ public ScheduledTaskRunner(ProviderSessionFactory providerSessionFactory, ScheduledTask task) {
this.providerSessionFactory = providerSessionFactory;
this.task = task;
}
@Override
public void run() {
- KeycloakSession keycloakSession = keycloakSessionFactory.createSession();
ProviderSession providerSession = providerSessionFactory.createSession();
+ KeycloakSession keycloakSession = providerSession.getProvider(KeycloakSession.class);
try {
keycloakSession.getTransaction().begin();
task.run(keycloakSession, providerSession);
@@ -39,11 +37,6 @@ public class ScheduledTaskRunner implements Runnable {
keycloakSession.getTransaction().rollback();
} finally {
try {
- keycloakSession.close();
- } catch (Throwable t) {
- logger.error("Failed to close KeycloakSession", t);
- }
- try {
providerSession.close();
} catch (Throwable t) {
logger.error("Failed to close ProviderSession", t);
diff --git a/services/src/main/java/org/keycloak/services/util/JsonConfigProvider.java b/services/src/main/java/org/keycloak/services/util/JsonConfigProvider.java
new file mode 100644
index 0000000..181de11
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/util/JsonConfigProvider.java
@@ -0,0 +1,129 @@
+package org.keycloak.services.util;
+
+import org.codehaus.jackson.JsonNode;
+import org.keycloak.Config;
+import org.keycloak.util.StringPropertyReplacer;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class JsonConfigProvider implements Config.ConfigProvider {
+
+ private JsonNode config;
+
+ public JsonConfigProvider(JsonNode config) {
+ this.config = config;
+ }
+
+ @Override
+ public String getProvider(String spi) {
+ JsonNode n = getNode(spi, "provider");
+ return n != null ? StringPropertyReplacer.replaceProperties(n.getTextValue()) : null;
+ }
+
+ @Override
+ public Config.Scope scope(String... path) {
+ return new JsonScope(getNode(path));
+ }
+
+ private JsonNode getNode(String... path) {
+ JsonNode n = config;
+ for (String p : path) {
+ n = n.get(p);
+ if (n == null) {
+ return null;
+ }
+ }
+ return n;
+ }
+
+ public class JsonScope implements Config.Scope {
+
+ private JsonNode config;
+
+ public JsonScope(JsonNode config) {
+ this.config = config;
+ }
+
+ @Override
+ public String get(String key) {
+ return get(key, null);
+ }
+
+ @Override
+ public String get(String key, String defaultValue) {
+ if (config == null) {
+ return defaultValue;
+ }
+ JsonNode n = config.get(key);
+ if (n == null) {
+ return defaultValue;
+ }
+ return StringPropertyReplacer.replaceProperties(n.getTextValue());
+ }
+
+ @Override
+ public Integer getInt(String key) {
+ return getInt(key, null);
+ }
+
+ @Override
+ public Integer getInt(String key, Integer defaultValue) {
+ if (config == null) {
+ return defaultValue;
+ }
+ JsonNode n = config.get(key);
+ if (n == null) {
+ return defaultValue;
+ }
+ if (n.isTextual()) {
+ return Integer.parseInt(StringPropertyReplacer.replaceProperties(n.getTextValue()));
+ } else {
+ return n.getIntValue();
+ }
+ }
+
+ @Override
+ public Long getLong(String key) {
+ return getLong(key, null);
+ }
+
+ @Override
+ public Long getLong(String key, Long defaultValue) {
+ if (config == null) {
+ return defaultValue;
+ }
+ JsonNode n = config.get(key);
+ if (n == null) {
+ return defaultValue;
+ }
+ if (n.isTextual()) {
+ return Long.parseLong(StringPropertyReplacer.replaceProperties(n.getTextValue()));
+ } else {
+ return n.getLongValue();
+ }
+ }
+
+ @Override
+ public Boolean getBoolean(String key) {
+ return getBoolean(key, null);
+ }
+
+ @Override
+ public Boolean getBoolean(String key, Boolean defaultValue) {
+ if (config == null) {
+ return defaultValue;
+ }
+ JsonNode n = config.get(key);
+ if (n == null) {
+ return defaultValue;
+ }
+ if (n.isTextual()) {
+ return Boolean.parseBoolean(StringPropertyReplacer.replaceProperties(n.getTextValue()));
+ } else {
+ return n.getBooleanValue();
+ }
+ }
+ }
+
+}
diff --git a/social/core/src/main/java/org/keycloak/social/SocialLoader.java b/social/core/src/main/java/org/keycloak/social/SocialLoader.java
index 6d24535..23876e1 100644
--- a/social/core/src/main/java/org/keycloak/social/SocialLoader.java
+++ b/social/core/src/main/java/org/keycloak/social/SocialLoader.java
@@ -2,8 +2,6 @@ package org.keycloak.social;
import org.keycloak.util.ProviderLoader;
-import java.util.ServiceLoader;
-
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
diff --git a/social/core/src/main/test/java/org/keycloak/social/utils/SimpleHttpTest.java b/social/core/src/main/test/java/org/keycloak/social/utils/SimpleHttpTest.java
index 6f3103d..e901be7 100644
--- a/social/core/src/main/test/java/org/keycloak/social/utils/SimpleHttpTest.java
+++ b/social/core/src/main/test/java/org/keycloak/social/utils/SimpleHttpTest.java
@@ -90,10 +90,9 @@ public class SimpleHttpTest {
@Test
public void testGetCustomHeader() throws IOException {
- JsonNode o = SimpleHttp.doGet("http://localhost:8081/tojson").header("Accept", "application/json").header("Authorization", "bearer dsfsadfsdf").asJson();
+ JsonNode o = SimpleHttp.doGet("http://localhost:8081/tojson").header("Authorization", "bearer dsfsadfsdf").asJson();
JsonNode h = o.get("headers");
- assertEquals("application/json", h.get("Accept"));
assertEquals("bearer dsfsadfsdf", h.get("Authorization").getTextValue());
}
testsuite/integration/pom.xml 27(+14 -13)
diff --git a/testsuite/integration/pom.xml b/testsuite/integration/pom.xml
index 74c30bb..f54b269 100755
--- a/testsuite/integration/pom.xml
+++ b/testsuite/integration/pom.xml
@@ -430,10 +430,10 @@
</activation>
<properties>
- <keycloak.mongo.host>localhost</keycloak.mongo.host>
- <keycloak.mongo.port>27018</keycloak.mongo.port>
- <keycloak.mongo.db>keycloak</keycloak.mongo.db>
- <keycloak.mongo.clearOnStartup>true</keycloak.mongo.clearOnStartup>
+ <keycloak.model.mongo.host>localhost</keycloak.model.mongo.host>
+ <keycloak.model.mongo.port>27018</keycloak.model.mongo.port>
+ <keycloak.model.mongo.db>keycloak</keycloak.model.mongo.db>
+ <keycloak.model.mongo.clearOnStartup>true</keycloak.model.mongo.clearOnStartup>
</properties>
<build>
@@ -452,16 +452,17 @@
</goals>
<configuration>
<systemPropertyVariables>
- <keycloak.mongo.host>${keycloak.mongo.host}</keycloak.mongo.host>
- <keycloak.mongo.port>${keycloak.mongo.port}</keycloak.mongo.port>
- <keycloak.mongo.db>${keycloak.mongo.db}</keycloak.mongo.db>
+ <keycloak.model.provider>mongo</keycloak.model.provider>
+ <keycloak.model.mongo.host>${keycloak.model.mongo.host}</keycloak.model.mongo.host>
+ <keycloak.model.mongo.port>${keycloak.model.mongo.port}</keycloak.model.mongo.port>
+ <keycloak.model.mongo.db>${keycloak.model.mongo.db}</keycloak.model.mongo.db>
- <keycloak.audit>mongo</keycloak.audit>
- <keycloak.audit.mongo.host>${keycloak.mongo.host}</keycloak.audit.mongo.host>
- <keycloak.audit.mongo.port>${keycloak.mongo.port}</keycloak.audit.mongo.port>
- <keycloak.audit.mongo.db>${keycloak.mongo.db}</keycloak.audit.mongo.db>
+ <keycloak.audit.provider>mongo</keycloak.audit.provider>
+ <keycloak.audit.mongo.host>${keycloak.model.mongo.host}</keycloak.audit.mongo.host>
+ <keycloak.audit.mongo.port>${keycloak.model.mongo.port}</keycloak.audit.mongo.port>
+ <keycloak.audit.mongo.db>${keycloak.model.mongo.db}</keycloak.audit.mongo.db>
- <keycloak.mongo.clearOnStartup>${keycloak.mongo.clearOnStartup}</keycloak.mongo.clearOnStartup>
+ <keycloak.model.mongo.clearOnStartup>${keycloak.model.mongo.clearOnStartup}</keycloak.model.mongo.clearOnStartup>
</systemPropertyVariables>
</configuration>
</execution>
@@ -486,7 +487,7 @@
<goal>start</goal>
</goals>
<configuration>
- <port>${keycloak.mongo.port}</port>
+ <port>${keycloak.model.mongo.port}</port>
<logging>file</logging>
<logFile>${project.build.directory}/mongodb.log</logFile>
</configuration>
testsuite/integration/README.md 6(+3 -3)
diff --git a/testsuite/integration/README.md b/testsuite/integration/README.md
index 1b3ed3e..003c215 100644
--- a/testsuite/integration/README.md
+++ b/testsuite/integration/README.md
@@ -11,7 +11,7 @@ To run the tests with Firefox add `-Dbrowser=firefox` or for Chrome add `-Dbrows
Mongo
-----
-The testsuite is executed with JPA model implementation with data saved in H2 database by default. To run testsuite with Mongo model, just add property `-Dkeycloak.model=mongo` when executing it.
+The testsuite is executed with JPA model implementation with data saved in H2 database by default. To run testsuite with Mongo model, just add property `-Dkeycloak.model.provider=mongo` when executing it.
Note that this will automatically run embedded Mongo database on localhost/27018 and it will stop it after whole testsuite is finished.
So you don't need to have Mongo installed on your laptop to run mongo execution tests.
@@ -52,11 +52,11 @@ For example to use the example themes run the server with:
To start a Keycloak server with identity model data persisted in Mongo database instead of default JPA/H2 you can run:
- mvn exec:java -Pkeycloak-server -Dkeycloak.model=mongo
+ mvn exec:java -Pkeycloak-server -Dkeycloak.model.provider=mongo
By default it's using database `keycloak` on localhost/27017 and it uses already existing data from this DB (no cleanup of existing data during bootstrap). Assumption is that you already have DB running on localhost/27017 . Use system properties to configure things differently:
- mvn exec:java -Pkeycloak-server -Dkeycloak.model=mongo -Dkeycloak.mongo.host=localhost -Dkeycloak.mongo.port=27017 -Dkeycloak.mongo.db=keycloak -Dkeycloak.mongo.clearCollectionsOnStartup=false
+ mvn exec:java -Pkeycloak-server -Dkeycloak.model.provider=mongo -Dkeycloak.model.mongo.host=localhost -Dkeycloak.model.mongo.port=27017 -Dkeycloak.model.mongo.db=keycloak -Dkeycloak.model.mongo.clearOnStartup=false
TOTP codes
----------
diff --git a/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java b/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
index f3eb078..da3dc68 100755
--- a/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
+++ b/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
@@ -30,18 +30,16 @@ import io.undertow.servlet.api.FilterInfo;
import org.jboss.logging.Logger;
import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer;
import org.jboss.resteasy.spi.ResteasyDeployment;
-import org.keycloak.models.Config;
import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
+import org.keycloak.provider.ProviderSession;
import org.keycloak.provider.ProviderSessionFactory;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.filters.ClientConnectionFilter;
import org.keycloak.services.filters.KeycloakSessionServletFilter;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.resources.KeycloakApplication;
-import org.keycloak.theme.DefaultKeycloakThemeProvider;
import org.keycloak.util.JsonSerialization;
import javax.servlet.DispatcherType;
@@ -129,9 +127,8 @@ public class KeycloakServer {
throw new RuntimeException("Invalid resources directory");
}
- if (Config.getThemeDir() == null) {
- System.setProperty(DefaultKeycloakThemeProvider.class.getName() + ".disabled", "");
- Config.setThemeDir(file(dir.getAbsolutePath(), "forms", "common-themes", "src", "main", "resources", "theme").getAbsolutePath());
+ if (!System.getProperties().containsKey("keycloak.theme.dir")) {
+ System.setProperty("keycloak.theme.dir", file(dir.getAbsolutePath(), "forms", "common-themes", "src", "main", "resources", "theme").getAbsolutePath());
}
config.setResourcesHome(dir.getAbsolutePath());
@@ -162,8 +159,6 @@ public class KeycloakServer {
private KeycloakServerConfig config;
- private KeycloakSessionFactory factory;
-
private ProviderSessionFactory providerSessionFactory;
private UndertowJaxrsServer server;
@@ -176,10 +171,6 @@ public class KeycloakServer {
this.config = config;
}
- public KeycloakSessionFactory getKeycloakSessionFactory() {
- return factory;
- }
-
public ProviderSessionFactory getProviderSessionFactory() {
return providerSessionFactory;
}
@@ -194,7 +185,8 @@ public class KeycloakServer {
}
public void importRealm(RealmRepresentation rep) {
- KeycloakSession session = factory.createSession();
+ ProviderSession providerSession = providerSessionFactory.createSession();
+ KeycloakSession session = providerSession.getProvider(KeycloakSession.class);
session.getTransaction().begin();
try {
@@ -217,12 +209,13 @@ public class KeycloakServer {
session.getTransaction().commit();
} finally {
- session.close();
+ providerSession.close();
}
}
protected void setupDevConfig() {
- KeycloakSession session = factory.createSession();
+ ProviderSession providerSession = providerSessionFactory.createSession();
+ KeycloakSession session = providerSession.getProvider(KeycloakSession.class);
session.getTransaction().begin();
try {
@@ -234,7 +227,7 @@ public class KeycloakServer {
session.getTransaction().commit();
} finally {
- session.close();
+ providerSession.close();
}
}
@@ -266,7 +259,6 @@ public class KeycloakServer {
server.deploy(di);
- factory = ((KeycloakApplication) deployment.getApplication()).getFactory();
providerSessionFactory = ((KeycloakApplication) deployment.getApplication()).getProviderSessionFactory();
setupDevConfig();
@@ -289,7 +281,6 @@ public class KeycloakServer {
public void stop() {
providerSessionFactory.close();
- factory.close();
server.stop();
info("Stopped Keycloak");
diff --git a/testsuite/integration/src/main/resources/META-INF/keycloak-server.json b/testsuite/integration/src/main/resources/META-INF/keycloak-server.json
new file mode 100644
index 0000000..ee6c8fc
--- /dev/null
+++ b/testsuite/integration/src/main/resources/META-INF/keycloak-server.json
@@ -0,0 +1,26 @@
+{
+ "admin": {
+ "realm": "keycloak-admin"
+ },
+
+ "audit": {
+ "provider": "${keycloak.audit.provider:jpa}"
+ },
+
+ "model": {
+ "provider": "${keycloak.model.provider:jpa}"
+ },
+
+ "timer": {
+ "provider": "basic"
+ },
+
+ "theme": {
+ "default": "keycloak",
+ "dir": "${keycloak.theme.dir}"
+ },
+
+ "scheduled": {
+ "interval": 900
+ }
+}
\ No newline at end of file
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java
index 8290d3f..393c3f7 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java
@@ -22,18 +22,14 @@
package org.keycloak.testsuite.account;
import org.junit.After;
-import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
-import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.keycloak.audit.Details;
import org.keycloak.audit.Event;
-import org.keycloak.audit.jpa.JpaAuditProviderFactory;
import org.keycloak.models.ApplicationModel;
-import org.keycloak.models.Config;
import org.keycloak.models.PasswordPolicy;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserCredentialModel;
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java
index ba5aaab..4051a6e 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java
@@ -32,6 +32,7 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
+import org.keycloak.provider.ProviderSession;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.adapters.action.SessionStats;
import org.keycloak.representations.idm.RealmRepresentation;
@@ -171,11 +172,11 @@ public class AdapterTest {
System.out.println(pageSource);
Assert.assertTrue(pageSource.contains("Bill Burke") && pageSource.contains("Stian Thorgersen"));
- KeycloakSession session = keycloakRule.startSession();
- RealmModel realm = session.getRealmByName("demo");
+ ProviderSession providerSession = keycloakRule.startSession();
+ RealmModel realm = providerSession.getProvider(KeycloakSession.class).getRealmByName("demo");
int originalIdle = realm.getSsoSessionIdleTimeout();
realm.setSsoSessionIdleTimeout(1);
- keycloakRule.stopSession(session, true);
+ keycloakRule.stopSession(providerSession, true);
Thread.sleep(2000);
@@ -184,10 +185,10 @@ public class AdapterTest {
driver.navigate().to("http://localhost:8081/product-portal");
Assert.assertTrue(driver.getCurrentUrl().startsWith(LOGIN_URL));
- session = keycloakRule.startSession();
- realm = session.getRealmByName("demo");
+ providerSession = keycloakRule.startSession();
+ realm = providerSession.getProvider(KeycloakSession.class).getRealmByName("demo");
realm.setSsoSessionIdleTimeout(originalIdle);
- keycloakRule.stopSession(session, true);
+ keycloakRule.stopSession(providerSession, true);
}
@Test
public void testLoginSSOMax() throws Exception {
@@ -202,11 +203,11 @@ public class AdapterTest {
System.out.println(pageSource);
Assert.assertTrue(pageSource.contains("Bill Burke") && pageSource.contains("Stian Thorgersen"));
- KeycloakSession session = keycloakRule.startSession();
- RealmModel realm = session.getRealmByName("demo");
+ ProviderSession providerSession = keycloakRule.startSession();
+ RealmModel realm = providerSession.getProvider(KeycloakSession.class).getRealmByName("demo");
int original = realm.getSsoSessionMaxLifespan();
realm.setSsoSessionMaxLifespan(1);
- keycloakRule.stopSession(session, true);
+ keycloakRule.stopSession(providerSession, true);
Thread.sleep(2000);
@@ -215,9 +216,9 @@ public class AdapterTest {
driver.navigate().to("http://localhost:8081/product-portal");
Assert.assertTrue(driver.getCurrentUrl().startsWith(LOGIN_URL));
- session = keycloakRule.startSession();
- realm = session.getRealmByName("demo");
+ providerSession = keycloakRule.startSession();
+ realm = providerSession.getProvider(KeycloakSession.class).getRealmByName("demo");
realm.setSsoSessionMaxLifespan(original);
- keycloakRule.stopSession(session, true);
+ keycloakRule.stopSession(providerSession, true);
}
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/AssertEvents.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/AssertEvents.java
index a57aff1..4a8543e 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/AssertEvents.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/AssertEvents.java
@@ -4,10 +4,10 @@ import org.hamcrest.CoreMatchers;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
-import org.jboss.logging.Logger;
import org.junit.Assert;
import org.junit.rules.TestRule;
import org.junit.runners.model.Statement;
+import org.keycloak.Config;
import org.keycloak.audit.AuditListener;
import org.keycloak.audit.AuditListenerFactory;
import org.keycloak.audit.Details;
@@ -59,11 +59,6 @@ public class AssertEvents implements TestRule, AuditListenerFactory {
}
@Override
- public boolean lazyLoad() {
- return false;
- }
-
- @Override
public Statement apply(final Statement base, org.junit.runner.Description description) {
return new Statement() {
@Override
@@ -194,7 +189,7 @@ public class AssertEvents implements TestRule, AuditListenerFactory {
}
@Override
- public void init() {
+ public void init(Config.Scope config) {
}
@Override
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/RefreshTokenTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/RefreshTokenTest.java
index cead905..4b1645e 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/RefreshTokenTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/RefreshTokenTest.java
@@ -29,14 +29,12 @@ import org.keycloak.OAuth2Constants;
import org.keycloak.audit.Details;
import org.keycloak.audit.Errors;
import org.keycloak.audit.Event;
-import org.keycloak.models.Config;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.provider.ProviderSession;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.RefreshToken;
-import org.keycloak.services.managers.RealmManager;
import org.keycloak.testsuite.AssertEvents;
import org.keycloak.testsuite.OAuthClient;
import org.keycloak.testsuite.OAuthClient.AccessTokenResponse;
@@ -47,7 +45,11 @@ import org.keycloak.testsuite.rule.WebRule;
import org.keycloak.util.Time;
import org.openqa.selenium.WebDriver;
-import static org.hamcrest.Matchers.*;
+import static org.hamcrest.Matchers.allOf;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
+import static org.hamcrest.Matchers.lessThan;
+import static org.hamcrest.Matchers.lessThanOrEqualTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
@@ -181,8 +183,8 @@ public class RefreshTokenTest {
String refreshId = oauth.verifyRefreshToken(tokenResponse.getRefreshToken()).getId();
- KeycloakSession session = keycloakRule.startSession();
- RealmModel realm = session.getRealmByName("test");
+ ProviderSession session = keycloakRule.startSession();
+ RealmModel realm = session.getProvider(KeycloakSession.class).getRealmByName("test");
UserSessionModel userSession = realm.getUserSession(sessionId);
int last = userSession.getLastSessionRefresh();
keycloakRule.stopSession(session, false);
@@ -197,7 +199,7 @@ public class RefreshTokenTest {
Assert.assertEquals(200, tokenResponse.getStatusCode());
session = keycloakRule.startSession();
- realm = session.getRealmByName("test");
+ realm = session.getProvider(KeycloakSession.class).getRealmByName("test");
userSession = realm.getUserSession(sessionId);
int next = userSession.getLastSessionRefresh();
keycloakRule.stopSession(session, false);
@@ -208,7 +210,7 @@ public class RefreshTokenTest {
session = keycloakRule.startSession();
- realm = session.getRealmByName("test");
+ realm = session.getProvider(KeycloakSession.class).getRealmByName("test");
int lastAccessTokenLifespan = realm.getAccessTokenLifespan();
realm.setAccessTokenLifespan(100000);
keycloakRule.stopSession(session, true);
@@ -217,7 +219,7 @@ public class RefreshTokenTest {
tokenResponse = oauth.doRefreshTokenRequest(tokenResponse.getRefreshToken(), "password");
session = keycloakRule.startSession();
- realm = session.getRealmByName("test");
+ realm = session.getProvider(KeycloakSession.class).getRealmByName("test");
userSession = realm.getUserSession(sessionId);
next = userSession.getLastSessionRefresh();
keycloakRule.stopSession(session, false);
@@ -226,7 +228,7 @@ public class RefreshTokenTest {
Assert.assertThat(next, allOf(greaterThan(last), lessThan(last + 6)));
session = keycloakRule.startSession();
- realm = session.getRealmByName("test");
+ realm = session.getProvider(KeycloakSession.class).getRealmByName("test");
int originalIdle = realm.getSsoSessionIdleTimeout();
realm.setSsoSessionIdleTimeout(1);
keycloakRule.stopSession(session, true);
@@ -243,7 +245,7 @@ public class RefreshTokenTest {
events.expectRefresh(refreshId, sessionId).error(Errors.INVALID_TOKEN);
session = keycloakRule.startSession();
- realm = session.getRealmByName("test");
+ realm = session.getProvider(KeycloakSession.class).getRealmByName("test");
realm.setSsoSessionIdleTimeout(originalIdle);
realm.setAccessTokenLifespan(lastAccessTokenLifespan);
keycloakRule.stopSession(session, true);
@@ -266,8 +268,8 @@ public class RefreshTokenTest {
String refreshId = oauth.verifyRefreshToken(tokenResponse.getRefreshToken()).getId();
- KeycloakSession session = keycloakRule.startSession();
- RealmModel realm = session.getRealmByName("test");
+ ProviderSession session = keycloakRule.startSession();
+ RealmModel realm = session.getProvider(KeycloakSession.class).getRealmByName("test");
int maxLifespan = realm.getSsoSessionMaxLifespan();
realm.setSsoSessionMaxLifespan(1);
keycloakRule.stopSession(session, true);
@@ -281,7 +283,7 @@ public class RefreshTokenTest {
assertNull(tokenResponse.getRefreshToken());
session = keycloakRule.startSession();
- realm = session.getRealmByName("test");
+ realm = session.getProvider(KeycloakSession.class).getRealmByName("test");
realm.setSsoSessionMaxLifespan(maxLifespan);
keycloakRule.stopSession(session, true);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java
index 9312eee..47e91ec 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java
@@ -6,10 +6,11 @@ import io.undertow.servlet.api.SecurityConstraint;
import io.undertow.servlet.api.ServletInfo;
import io.undertow.servlet.api.WebResourceCollection;
import org.junit.rules.ExternalResource;
-import org.keycloak.models.Config;
+import org.keycloak.Config;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
+import org.keycloak.provider.ProviderSession;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.services.managers.ModelToRepresentation;
@@ -33,31 +34,33 @@ public abstract class AbstractKeycloakRule extends ExternalResource {
server = new KeycloakServer();
server.start();
-
setupKeycloak();
}
public UserRepresentation getUser(String realm, String name) {
- KeycloakSession session = server.getKeycloakSessionFactory().createSession();
+ ProviderSession providerSession = server.getProviderSessionFactory().createSession();
+ KeycloakSession session = providerSession.getProvider(KeycloakSession.class);
try {
UserModel user = session.getRealmByName(realm).getUser(name);
return user != null ? ModelToRepresentation.toRepresentation(user) : null;
} finally {
- session.close();
+ providerSession.close();
}
}
public UserRepresentation getUserById(String realm, String id) {
- KeycloakSession session = server.getKeycloakSessionFactory().createSession();
+ ProviderSession providerSession = server.getProviderSessionFactory().createSession();
+ KeycloakSession session = providerSession.getProvider(KeycloakSession.class);
try {
return ModelToRepresentation.toRepresentation(session.getRealmByName(realm).getUserById(id));
} finally {
- session.close();
+ providerSession.close();
}
}
protected void setupKeycloak() {
- KeycloakSession session = server.getKeycloakSessionFactory().createSession();
+ ProviderSession providerSession = server.getProviderSessionFactory().createSession();
+ KeycloakSession session = providerSession.getProvider(KeycloakSession.class);
session.getTransaction().begin();
try {
@@ -69,9 +72,8 @@ public abstract class AbstractKeycloakRule extends ExternalResource {
session.getTransaction().commit();
} finally {
- session.close();
+ providerSession.close();
}
-
}
protected void configure(RealmManager manager, RealmModel adminRealm) {
@@ -134,15 +136,16 @@ public abstract class AbstractKeycloakRule extends ExternalResource {
return JsonSerialization.readValue(bytes, RealmRepresentation.class);
}
- public KeycloakSession startSession() {
- KeycloakSession session = server.getKeycloakSessionFactory().createSession();
+ public ProviderSession startSession() {
+ ProviderSession providerSession = server.getProviderSessionFactory().createSession();
+ KeycloakSession session = providerSession.getProvider(KeycloakSession.class);
session.getTransaction().begin();
- return session;
+ return providerSession;
}
- public void stopSession(KeycloakSession session, boolean commit) {
+ public void stopSession(ProviderSession session, boolean commit) {
if (commit) {
- session.getTransaction().commit();
+ session.getProvider(KeycloakSession.class).getTransaction().commit();
}
session.close();
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/KeycloakRule.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/KeycloakRule.java
index 4096658..f520d19 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/KeycloakRule.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/KeycloakRule.java
@@ -21,7 +21,7 @@
*/
package org.keycloak.testsuite.rule;
-import org.keycloak.models.Config;
+import org.keycloak.Config;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
@@ -61,8 +61,8 @@ public class KeycloakRule extends AbstractKeycloakRule {
}
public void configure(KeycloakSetup configurer) {
- KeycloakSession session = server.getKeycloakSessionFactory().createSession();
ProviderSession providerSession = server.getProviderSessionFactory().createSession();
+ KeycloakSession session = providerSession.getProvider(KeycloakSession.class);
session.getTransaction().begin();
try {
@@ -77,17 +77,16 @@ public class KeycloakRule extends AbstractKeycloakRule {
session.getTransaction().commit();
} finally {
providerSession.close();
- session.close();
}
}
public void removeUserSession(String sessionId) {
- KeycloakSession keycloakSession = startSession();
- RealmModel realm = keycloakSession.getRealm("test");
+ ProviderSession providerSession = startSession();
+ RealmModel realm = providerSession.getProvider(KeycloakSession.class).getRealm("test");
UserSessionModel session = realm.getUserSession(sessionId);
assertNotNull(session);
realm.removeUserSession(session);
- stopSession(keycloakSession, true);
+ stopSession(providerSession, true);
}
public abstract static class KeycloakSetup {
diff --git a/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/BaseJMeterPerformanceTest.java b/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/BaseJMeterPerformanceTest.java
index eda2761..c78cb61 100755
--- a/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/BaseJMeterPerformanceTest.java
+++ b/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/BaseJMeterPerformanceTest.java
@@ -6,6 +6,8 @@ import org.apache.jmeter.samplers.SampleResult;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.KeycloakTransaction;
+import org.keycloak.provider.ProviderSession;
+import org.keycloak.provider.ProviderSessionFactory;
import org.keycloak.services.resources.KeycloakApplication;
import java.util.concurrent.Callable;
@@ -18,17 +20,17 @@ import java.util.concurrent.atomic.AtomicInteger;
public class BaseJMeterPerformanceTest extends AbstractJavaSamplerClient {
- private static FutureTask<KeycloakSessionFactory> factoryProvider = new FutureTask<KeycloakSessionFactory>(new Callable() {
+ private static FutureTask<ProviderSessionFactory> factoryProvider = new FutureTask<ProviderSessionFactory>(new Callable() {
@Override
- public KeycloakSessionFactory call() throws Exception {
- return KeycloakApplication.createSessionFactory();
+ public ProviderSessionFactory call() throws Exception {
+ return KeycloakApplication.createProviderSessionFactory();
}
});
private static AtomicInteger counter = new AtomicInteger();
- private KeycloakSessionFactory factory;
+ private ProviderSessionFactory factory;
// private KeycloakSession identitySession;
private Worker worker;
private boolean setupSuccess = false;
@@ -42,7 +44,8 @@ public class BaseJMeterPerformanceTest extends AbstractJavaSamplerClient {
worker = getWorker();
factory = getFactory();
- KeycloakSession identitySession = factory.createSession();
+ ProviderSession providerSession = factory.createSession();
+ KeycloakSession identitySession = providerSession.getProvider(KeycloakSession.class);
KeycloakTransaction transaction = identitySession.getTransaction();
transaction.begin();
@@ -56,11 +59,11 @@ public class BaseJMeterPerformanceTest extends AbstractJavaSamplerClient {
} else {
transaction.rollback();
}
- identitySession.close();
+ providerSession.close();
}
}
- private static KeycloakSessionFactory getFactory() {
+ private static ProviderSessionFactory getFactory() {
factoryProvider.run();
try {
return factoryProvider.get();
@@ -98,7 +101,8 @@ public class BaseJMeterPerformanceTest extends AbstractJavaSamplerClient {
return result;
}
- KeycloakSession identitySession = factory.createSession();
+ ProviderSession providerSession = factory.createSession();
+ KeycloakSession identitySession = providerSession.getProvider(KeycloakSession.class);
KeycloakTransaction transaction = identitySession.getTransaction();
try {
transaction.begin();
@@ -114,7 +118,7 @@ public class BaseJMeterPerformanceTest extends AbstractJavaSamplerClient {
} finally {
result.sampleEnd();
result.setSuccessful(true);
- identitySession.close();
+ providerSession.close();
}
return result;
diff --git a/testsuite/performance/src/test/jmeter/system.properties b/testsuite/performance/src/test/jmeter/system.properties
index 26d24aa..c1cdda4 100644
--- a/testsuite/performance/src/test/jmeter/system.properties
+++ b/testsuite/performance/src/test/jmeter/system.properties
@@ -8,11 +8,11 @@ keycloak.jpa.hbm2ddl.auto=create
## Configure MongoDB (Useful just when keycloak.sessionFactory=mongo)
-keycloak.mongodb.host=localhost
-keycloak.mongodb.port=27017
-keycloak.mongodb.databaseName=keycloakPerfTest
+keycloak.model.mongo.host=localhost
+keycloak.model.mongo.port=27017
+keycloak.model.mongo.databaseName=keycloakPerfTest
# Should be DB dropped at startup of the test?
-keycloak.mongodb.dropDatabaseOnStartup=true
+keycloak.model.mongo.dropDatabaseOnStartup=true
## Specify Keycloak worker class
diff --git a/timer/api/src/main/java/org/keycloak/timer/TimerProvider.java b/timer/api/src/main/java/org/keycloak/timer/TimerProvider.java
index e701b5f..627f00e 100644
--- a/timer/api/src/main/java/org/keycloak/timer/TimerProvider.java
+++ b/timer/api/src/main/java/org/keycloak/timer/TimerProvider.java
@@ -7,6 +7,6 @@ import org.keycloak.provider.Provider;
*/
public interface TimerProvider extends Provider {
- public void schedule(Runnable runnable, String config);
+ public void schedule(Runnable runnable, long interval);
}
diff --git a/timer/api/src/main/java/org/keycloak/timer/TimerSpi.java b/timer/api/src/main/java/org/keycloak/timer/TimerSpi.java
new file mode 100644
index 0000000..d0e57f9
--- /dev/null
+++ b/timer/api/src/main/java/org/keycloak/timer/TimerSpi.java
@@ -0,0 +1,25 @@
+package org.keycloak.timer;
+
+import org.keycloak.provider.Provider;
+import org.keycloak.provider.ProviderFactory;
+import org.keycloak.provider.Spi;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class TimerSpi implements Spi {
+ @Override
+ public String getName() {
+ return "timer";
+ }
+
+ @Override
+ public Class<? extends Provider> getProviderClass() {
+ return TimerProvider.class;
+ }
+
+ @Override
+ public Class<? extends ProviderFactory> getProviderFactoryClass() {
+ return TimerProviderFactory.class;
+ }
+}
diff --git a/timer/api/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/timer/api/src/main/resources/META-INF/services/org.keycloak.provider.Spi
new file mode 100644
index 0000000..e8219ff
--- /dev/null
+++ b/timer/api/src/main/resources/META-INF/services/org.keycloak.provider.Spi
@@ -0,0 +1 @@
+org.keycloak.timer.TimerSpi
\ No newline at end of file
diff --git a/timer/basic/src/main/java/org/keycloak/timer/basic/BasicTimerProvider.java b/timer/basic/src/main/java/org/keycloak/timer/basic/BasicTimerProvider.java
index bda150b..267f17c 100644
--- a/timer/basic/src/main/java/org/keycloak/timer/basic/BasicTimerProvider.java
+++ b/timer/basic/src/main/java/org/keycloak/timer/basic/BasicTimerProvider.java
@@ -18,9 +18,7 @@ public class BasicTimerProvider implements TimerProvider {
}
@Override
- public void schedule(final Runnable runnable, String config) {
- long interval = Long.parseLong(config);
-
+ public void schedule(final Runnable runnable, final long interval) {
TimerTask task = new TimerTask() {
@Override
public void run() {
diff --git a/timer/basic/src/main/java/org/keycloak/timer/basic/BasicTimerProviderFactory.java b/timer/basic/src/main/java/org/keycloak/timer/basic/BasicTimerProviderFactory.java
index 466167d..3454d87 100644
--- a/timer/basic/src/main/java/org/keycloak/timer/basic/BasicTimerProviderFactory.java
+++ b/timer/basic/src/main/java/org/keycloak/timer/basic/BasicTimerProviderFactory.java
@@ -1,5 +1,6 @@
package org.keycloak.timer.basic;
+import org.keycloak.Config;
import org.keycloak.provider.ProviderSession;
import org.keycloak.timer.TimerProvider;
import org.keycloak.timer.TimerProviderFactory;
@@ -19,7 +20,7 @@ public class BasicTimerProviderFactory implements TimerProviderFactory {
}
@Override
- public void init() {
+ public void init(Config.Scope config) {
timer = new Timer();
}
@@ -34,8 +35,4 @@ public class BasicTimerProviderFactory implements TimerProviderFactory {
return "basic";
}
- @Override
- public boolean lazyLoad() {
- return true;
- }
}