Use service loader to load model provider
This commit is contained in:
parent
70f3ffa40c
commit
2e9a474eac
17 changed files with 142 additions and 62 deletions
|
@ -5,5 +5,7 @@ package org.keycloak.models;
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public interface ModelProvider {
|
public interface ModelProvider {
|
||||||
|
String getId();
|
||||||
|
|
||||||
KeycloakSessionFactory createFactory();
|
KeycloakSessionFactory createFactory();
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,12 @@ import javax.persistence.Persistence;
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class JpaModelProvider implements ModelProvider {
|
public class JpaModelProvider implements ModelProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return "jpa";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KeycloakSessionFactory createFactory() {
|
public KeycloakSessionFactory createFactory() {
|
||||||
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpa-keycloak-identity-store");
|
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpa-keycloak-identity-store");
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
org.keycloak.models.jpa.JpaModelProvider
|
58
model/mongo/src/main/java/org/keycloak/models/mongo/PropertiesManager.java
Executable file
58
model/mongo/src/main/java/org/keycloak/models/mongo/PropertiesManager.java
Executable file
|
@ -0,0 +1,58 @@
|
||||||
|
package org.keycloak.models.mongo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public class PropertiesManager {
|
||||||
|
|
||||||
|
private static final String MONGO_HOST = "keycloak.mongodb.host";
|
||||||
|
private static final String MONGO_PORT = "keycloak.mongodb.port";
|
||||||
|
private static final String MONGO_DB_NAME = "keycloak.mongodb.databaseName";
|
||||||
|
private static final String MONGO_DROP_DB_ON_STARTUP = "keycloak.mongodb.dropDatabaseOnStartup";
|
||||||
|
private static final String BOOTSTRAP_EMBEDDED_MONGO_AT_CONTEXT_INIT = "keycloak.mongodb.bootstrapEmbeddedMongoAtContextInit";
|
||||||
|
|
||||||
|
// Port where embedded MongoDB will be started during keycloak bootstrap. Same port will be used by KeycloakApplication then
|
||||||
|
private static final int MONGO_DEFAULT_PORT_KEYCLOAK_WAR_EMBEDDED = 37017;
|
||||||
|
|
||||||
|
// Port where MongoDB instance is normally started on linux. This port should be used if we're not starting embedded instance (keycloak.mongodb.bootstrapEmbeddedMongoAtContextInit is false)
|
||||||
|
private static final int MONGO_DEFAULT_PORT_KEYCLOAK_WAR = 27017;
|
||||||
|
|
||||||
|
// Port where unit tests will start embedded MongoDB instance
|
||||||
|
public static final int MONGO_DEFAULT_PORT_UNIT_TESTS = 27777;
|
||||||
|
|
||||||
|
public static String getMongoHost() {
|
||||||
|
return System.getProperty(MONGO_HOST, "localhost");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setMongoHost(String mongoHost) {
|
||||||
|
System.setProperty(MONGO_HOST, mongoHost);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getMongoPort() {
|
||||||
|
return Integer.parseInt(System.getProperty(MONGO_PORT, String.valueOf(MONGO_DEFAULT_PORT_KEYCLOAK_WAR_EMBEDDED)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setMongoPort(int mongoPort) {
|
||||||
|
System.setProperty(MONGO_PORT, String.valueOf(mongoPort));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getMongoDbName() {
|
||||||
|
return System.getProperty(MONGO_DB_NAME, "keycloak");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setMongoDbName(String mongoMongoDbName) {
|
||||||
|
System.setProperty(MONGO_DB_NAME, mongoMongoDbName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean dropDatabaseOnStartup() {
|
||||||
|
return Boolean.parseBoolean(System.getProperty(MONGO_DROP_DB_ON_STARTUP, "true"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setDropDatabaseOnStartup(boolean dropDatabaseOnStartup) {
|
||||||
|
System.setProperty(MONGO_DROP_DB_ON_STARTUP, String.valueOf(dropDatabaseOnStartup));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean bootstrapEmbeddedMongoAtContextInit() {
|
||||||
|
return isMongoSessionFactory() && Boolean.parseBoolean(System.getProperty(BOOTSTRAP_EMBEDDED_MONGO_AT_CONTEXT_INIT, "true"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,13 +3,31 @@ package org.keycloak.models.mongo.keycloak;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
import org.keycloak.models.ModelProvider;
|
import org.keycloak.models.ModelProvider;
|
||||||
|
|
||||||
|
import java.lang.Override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class MongoModelProvider implements ModelProvider {
|
public class MongoModelProvider implements ModelProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return "mongo";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KeycloakSessionFactory createFactory() {
|
public KeycloakSessionFactory createFactory() {
|
||||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
String host = PropertiesManager.getMongoHost();
|
||||||
|
int port = PropertiesManager.getMongoPort();
|
||||||
|
String dbName = PropertiesManager.getMongoDbName();
|
||||||
|
boolean dropDatabaseOnStartup = PropertiesManager.dropDatabaseOnStartup();
|
||||||
|
|
||||||
|
// Create MongoDBSessionFactory via reflection now
|
||||||
|
try {
|
||||||
|
return new MongoDBSessionFactory(host, port, dbName, dropDatabaseOnStartup);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
org.keycloak.models.mongo.keycloak.MongoModelProvider
|
|
@ -37,6 +37,11 @@ public class PicketlinkModelProvider implements ModelProvider {
|
||||||
return new PicketlinkKeycloakSessionFactory(emf, buildPartitionManager());
|
return new PicketlinkKeycloakSessionFactory(emf, buildPartitionManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return "picketlink";
|
||||||
|
}
|
||||||
|
|
||||||
public static PartitionManager buildPartitionManager() {
|
public static PartitionManager buildPartitionManager() {
|
||||||
IdentityConfigurationBuilder builder = new IdentityConfigurationBuilder();
|
IdentityConfigurationBuilder builder = new IdentityConfigurationBuilder();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
org.keycloak.models.picketlink.PicketlinkModelProvider
|
|
@ -31,14 +31,15 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-model-picketlink</artifactId>
|
<artifactId>keycloak-model-jpa</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<scope>provided</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-model-jpa</artifactId>
|
<artifactId>keycloak-model-picketlink</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--<dependency>
|
<!--<dependency>
|
||||||
|
|
|
@ -1,18 +1,19 @@
|
||||||
package org.keycloak.services.resources;
|
package org.keycloak.services.resources;
|
||||||
|
|
||||||
|
import org.jboss.resteasy.logging.Logger;
|
||||||
import org.keycloak.SkeletonKeyContextResolver;
|
import org.keycloak.SkeletonKeyContextResolver;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
import org.keycloak.models.ModelProvider;
|
import org.keycloak.models.ModelProvider;
|
||||||
import org.keycloak.services.managers.SocialRequestManager;
|
import org.keycloak.services.managers.SocialRequestManager;
|
||||||
import org.keycloak.services.managers.TokenManager;
|
import org.keycloak.services.managers.TokenManager;
|
||||||
import org.keycloak.services.utils.PropertiesManager;
|
|
||||||
|
|
||||||
import javax.annotation.PreDestroy;
|
import javax.annotation.PreDestroy;
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
import javax.ws.rs.core.Application;
|
import javax.ws.rs.core.Application;
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.ServiceLoader;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21,14 +22,19 @@ import java.util.Set;
|
||||||
*/
|
*/
|
||||||
public class KeycloakApplication extends Application {
|
public class KeycloakApplication extends Application {
|
||||||
|
|
||||||
|
private static final Logger log = Logger.getLogger(KeycloakApplication.class);
|
||||||
|
|
||||||
|
private static final String MODEL_PROVIDER = "keycloak.model";
|
||||||
|
private static final String DEFAULT_MODEL_PROVIDER = "jpa";
|
||||||
|
|
||||||
protected Set<Object> singletons = new HashSet<Object>();
|
protected Set<Object> singletons = new HashSet<Object>();
|
||||||
protected Set<Class<?>> classes = new HashSet<Class<?>>();
|
protected Set<Class<?>> classes = new HashSet<Class<?>>();
|
||||||
|
|
||||||
protected KeycloakSessionFactory factory;
|
protected KeycloakSessionFactory factory;
|
||||||
|
|
||||||
public KeycloakApplication(@Context ServletContext context) {
|
public KeycloakApplication(@Context ServletContext context) {
|
||||||
KeycloakSessionFactory f = createSessionFactory();
|
this.factory = createSessionFactory();
|
||||||
this.factory = f;
|
|
||||||
context.setAttribute(KeycloakSessionFactory.class.getName(), factory);
|
context.setAttribute(KeycloakSessionFactory.class.getName(), factory);
|
||||||
//classes.add(KeycloakSessionCleanupFilter.class);
|
//classes.add(KeycloakSessionCleanupFilter.class);
|
||||||
|
|
||||||
|
@ -41,57 +47,36 @@ public class KeycloakApplication extends Application {
|
||||||
classes.add(QRCodeResource.class);
|
classes.add(QRCodeResource.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected KeycloakSessionFactory createSessionFactory() {
|
public static KeycloakSessionFactory createSessionFactory() {
|
||||||
return buildSessionFactory();
|
ServiceLoader<ModelProvider> providers = ServiceLoader.load(ModelProvider.class);
|
||||||
}
|
String configuredProvider = System.getProperty(MODEL_PROVIDER);
|
||||||
|
ModelProvider provider = null;
|
||||||
|
|
||||||
public static KeycloakSessionFactory buildSessionFactory() {
|
if (configuredProvider != null) {
|
||||||
if (PropertiesManager.isMongoSessionFactory()) {
|
for (ModelProvider p : providers) {
|
||||||
return buildMongoDBSessionFactory();
|
if (p.getId().equals(configuredProvider)) {
|
||||||
} else if (PropertiesManager.isPicketlinkSessionFactory()) {
|
provider = p;
|
||||||
return buildPicketlinkSessionFactory();
|
}
|
||||||
} else if (PropertiesManager.isJpaSessionFactory()) {
|
}
|
||||||
return buildJpaSessionFactory();
|
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException("Unknown session factory type: " + PropertiesManager.getSessionFactoryType());
|
for (ModelProvider p : providers) {
|
||||||
|
if (provider == null) {
|
||||||
|
provider = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p.getId().equals(DEFAULT_MODEL_PROVIDER)) {
|
||||||
|
provider = p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static KeycloakSessionFactory buildJpaSessionFactory() {
|
if (provider != null) {
|
||||||
ModelProvider provider = null;
|
log.debug("Model provider: " + provider.getId());
|
||||||
try {
|
|
||||||
provider = (ModelProvider)Class.forName("org.keycloak.models.jpa.JpaModelProvider").newInstance();
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
return provider.createFactory();
|
return provider.createFactory();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw new RuntimeException("Model provider not found");
|
||||||
private static KeycloakSessionFactory buildPicketlinkSessionFactory() {
|
|
||||||
ModelProvider provider = null;
|
|
||||||
try {
|
|
||||||
provider = (ModelProvider)Class.forName("org.keycloak.models.picketlink.PicketlinkModelProvider").newInstance();
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
return provider.createFactory();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static KeycloakSessionFactory buildMongoDBSessionFactory() {
|
|
||||||
String host = PropertiesManager.getMongoHost();
|
|
||||||
int port = PropertiesManager.getMongoPort();
|
|
||||||
String dbName = PropertiesManager.getMongoDbName();
|
|
||||||
boolean dropDatabaseOnStartup = PropertiesManager.dropDatabaseOnStartup();
|
|
||||||
|
|
||||||
// Create MongoDBSessionFactory via reflection now
|
|
||||||
try {
|
|
||||||
Class<? extends KeycloakSessionFactory> mongoDBSessionFactoryClass = (Class<? extends KeycloakSessionFactory>)Class.forName("org.keycloak.models.mongo.keycloak.adapters.MongoDBSessionFactory");
|
|
||||||
Constructor<? extends KeycloakSessionFactory> constr = mongoDBSessionFactoryClass.getConstructor(String.class, int.class, String.class, boolean.class);
|
|
||||||
return constr.newInstance(host, port, dbName, dropDatabaseOnStartup);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeycloakSessionFactory getFactory() {
|
public KeycloakSessionFactory getFactory() {
|
||||||
|
@ -103,9 +88,6 @@ public class KeycloakApplication extends Application {
|
||||||
factory.close();
|
factory.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<Class<?>> getClasses() {
|
public Set<Class<?>> getClasses() {
|
||||||
return classes;
|
return classes;
|
||||||
|
|
|
@ -31,7 +31,7 @@ public class ApplicationModelTest extends AbstractKeycloakServerTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void before() throws Exception {
|
public void before() throws Exception {
|
||||||
factory = KeycloakApplication.buildSessionFactory();
|
factory = KeycloakApplication.createSessionFactory();
|
||||||
identitySession = factory.createSession();
|
identitySession = factory.createSession();
|
||||||
identitySession.getTransaction().begin();
|
identitySession.getTransaction().begin();
|
||||||
manager = new RealmManager(identitySession);
|
manager = new RealmManager(identitySession);
|
||||||
|
|
|
@ -23,7 +23,7 @@ public class ModelTest extends AbstractKeycloakServerTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void before() throws Exception {
|
public void before() throws Exception {
|
||||||
factory = KeycloakApplication.buildSessionFactory();
|
factory = KeycloakApplication.createSessionFactory();
|
||||||
identitySession = factory.createSession();
|
identitySession = factory.createSession();
|
||||||
identitySession.getTransaction().begin();
|
identitySession.getTransaction().begin();
|
||||||
manager = new RealmManager(identitySession);
|
manager = new RealmManager(identitySession);
|
||||||
|
|
|
@ -26,7 +26,7 @@ public class UserModelTest extends AbstractKeycloakServerTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void before() throws Exception {
|
public void before() throws Exception {
|
||||||
factory = KeycloakApplication.buildSessionFactory();
|
factory = KeycloakApplication.createSessionFactory();
|
||||||
identitySession = factory.createSession();
|
identitySession = factory.createSession();
|
||||||
identitySession.getTransaction().begin();
|
identitySession.getTransaction().begin();
|
||||||
manager = new RealmManager(identitySession);
|
manager = new RealmManager(identitySession);
|
||||||
|
|
|
@ -72,7 +72,7 @@ public abstract class AbstractKeycloakTest {
|
||||||
@Before
|
@Before
|
||||||
public void before() throws Exception {
|
public void before() throws Exception {
|
||||||
testContext.initEnvironment();
|
testContext.initEnvironment();
|
||||||
factory = KeycloakApplication.buildSessionFactory();
|
factory = KeycloakApplication.createSessionFactory();
|
||||||
identitySession = factory.createSession();
|
identitySession = factory.createSession();
|
||||||
identitySession.getTransaction().begin();
|
identitySession.getTransaction().begin();
|
||||||
realmManager = new RealmManager(identitySession);
|
realmManager = new RealmManager(identitySession);
|
||||||
|
|
|
@ -51,6 +51,11 @@
|
||||||
<artifactId>keycloak-services</artifactId>
|
<artifactId>keycloak-services</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-model-jpa</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-social-core</artifactId>
|
<artifactId>keycloak-social-core</artifactId>
|
||||||
|
|
|
@ -271,7 +271,7 @@ public class KeycloakServer {
|
||||||
|
|
||||||
server.deploy(di);
|
server.deploy(di);
|
||||||
|
|
||||||
factory = KeycloakApplication.buildSessionFactory();
|
factory = KeycloakApplication.createSessionFactory();
|
||||||
|
|
||||||
setupDefaultRealm();
|
setupDefaultRealm();
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ public class BaseJMeterPerformanceTest extends AbstractJavaSamplerClient {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KeycloakSessionFactory call() throws Exception {
|
public KeycloakSessionFactory call() throws Exception {
|
||||||
return KeycloakApplication.buildSessionFactory();
|
return KeycloakApplication.createSessionFactory();
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue