diff --git a/model/api/pom.xml b/model/api/pom.xml
index 2c64294f4ac..a5260d49d5f 100755
--- a/model/api/pom.xml
+++ b/model/api/pom.xml
@@ -17,6 +17,17 @@
net.iharder
base64
+
+ org.bouncycastle
+ bcprov-jdk16
+ provided
+
+
+ org.keycloak
+ keycloak-core
+ ${project.version}
+ provided
+
junit
junit
diff --git a/model/api/src/main/java/org/keycloak/models/IdGenerator.java b/model/api/src/main/java/org/keycloak/models/IdGenerator.java
deleted file mode 100755
index 3a1b028200e..00000000000
--- a/model/api/src/main/java/org/keycloak/models/IdGenerator.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.keycloak.models;
-
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- * @author Bill Burke
- * @version $Revision: 1 $
- */
-public class IdGenerator {
- private static AtomicLong counter = new AtomicLong(1);
- public static String generateId() {
- return counter.getAndIncrement() + "-" + System.currentTimeMillis();
- }
-
-}
diff --git a/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java b/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java
new file mode 100644
index 00000000000..4582a032740
--- /dev/null
+++ b/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java
@@ -0,0 +1,86 @@
+package org.keycloak.models.utils;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.security.Key;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.bouncycastle.openssl.PEMWriter;
+import org.keycloak.models.RoleModel;
+import org.keycloak.util.PemUtils;
+
+/**
+ * Set of helper methods, which are useful in various model implementations.
+ *
+ * @author Marek Posolda
+ */
+public final class KeycloakModelUtils {
+
+ private KeycloakModelUtils() {
+ }
+
+ private static AtomicLong counter = new AtomicLong(1);
+
+ public static String generateId() {
+ return counter.getAndIncrement() + "-" + System.currentTimeMillis();
+ }
+
+ public static PublicKey getPublicKey(String publicKeyPem) {
+ if (publicKeyPem != null) {
+ try {
+ return PemUtils.decodePublicKey(publicKeyPem);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ } else {
+ return null;
+ }
+ }
+
+ public static PrivateKey getPrivateKey(String privateKeyPem) {
+ if (privateKeyPem != null) {
+ try {
+ return PemUtils.decodePrivateKey(privateKeyPem);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ return null;
+ }
+
+ public static String getPemFromKey(Key key) {
+ StringWriter writer = new StringWriter();
+ PEMWriter pemWriter = new PEMWriter(writer);
+ try {
+ pemWriter.writeObject(key);
+ pemWriter.flush();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ String s = writer.toString();
+ return PemUtils.removeBeginEnd(s);
+ }
+
+ /**
+ * Deep search if given role is descendant of composite role
+ *
+ * @param role role to check
+ * @param composite composite role
+ * @param visited set of already visited roles (used for recursion)
+ * @return true if "role" is descendant of "composite"
+ */
+ public static boolean searchFor(RoleModel role, RoleModel composite, Set visited) {
+ if (visited.contains(composite)) return false;
+ visited.add(composite);
+ Set composites = composite.getComposites();
+ if (composites.contains(role)) return true;
+ for (RoleModel contained : composites) {
+ if (!contained.isComposite()) continue;
+ if (searchFor(role, contained, visited)) return true;
+ }
+ return false;
+ }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/utils/KeycloakSessionUtils.java b/model/api/src/main/java/org/keycloak/models/utils/KeycloakSessionUtils.java
deleted file mode 100644
index 57285db0046..00000000000
--- a/model/api/src/main/java/org/keycloak/models/utils/KeycloakSessionUtils.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.keycloak.models.utils;
-
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- * @author Marek Posolda
- */
-public final class KeycloakSessionUtils {
-
- private KeycloakSessionUtils() {
- }
-
- private static AtomicLong counter = new AtomicLong(1);
-
- public static String generateId() {
- return counter.getAndIncrement() + "-" + System.currentTimeMillis();
- }
-}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakSession.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakSession.java
index 7b7db282377..a072c75cc63 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakSession.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakSession.java
@@ -2,7 +2,7 @@ package org.keycloak.models.jpa;
import org.keycloak.models.*;
import org.keycloak.models.jpa.entities.*;
-import org.keycloak.models.utils.KeycloakSessionUtils;
+import org.keycloak.models.utils.KeycloakModelUtils;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
@@ -28,7 +28,7 @@ public class JpaKeycloakSession implements KeycloakSession {
@Override
public RealmModel createRealm(String name) {
- return createRealm(KeycloakSessionUtils.generateId(), name);
+ return createRealm(KeycloakModelUtils.generateId(), name);
}
@Override
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
index 965cbbee4fb..467953ca546 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
@@ -13,6 +13,7 @@ import org.keycloak.models.jpa.entities.SocialLinkEntity;
import org.keycloak.models.jpa.entities.UserEntity;
import org.keycloak.models.jpa.entities.UserRoleMappingEntity;
import org.keycloak.models.jpa.entities.UserScopeMappingEntity;
+import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
import org.keycloak.util.PemUtils;
import org.keycloak.models.ApplicationModel;
@@ -187,59 +188,29 @@ public class RealmAdapter implements RealmModel {
@Override
public PublicKey getPublicKey() {
if (publicKey != null) return publicKey;
- String pem = getPublicKeyPem();
- if (pem != null) {
- try {
- publicKey = PemUtils.decodePublicKey(pem);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
+ publicKey = KeycloakModelUtils.getPublicKey(getPublicKeyPem());
return publicKey;
}
@Override
public void setPublicKey(PublicKey publicKey) {
this.publicKey = publicKey;
- StringWriter writer = new StringWriter();
- PEMWriter pemWriter = new PEMWriter(writer);
- try {
- pemWriter.writeObject(publicKey);
- pemWriter.flush();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- String s = writer.toString();
- setPublicKeyPem(PemUtils.removeBeginEnd(s));
+ String publicKeyPem = KeycloakModelUtils.getPemFromKey(publicKey);
+ setPublicKeyPem(publicKeyPem);
}
@Override
public PrivateKey getPrivateKey() {
if (privateKey != null) return privateKey;
- String pem = getPrivateKeyPem();
- if (pem != null) {
- try {
- privateKey = PemUtils.decodePrivateKey(pem);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
+ privateKey = KeycloakModelUtils.getPrivateKey(getPrivateKeyPem());
return privateKey;
}
@Override
public void setPrivateKey(PrivateKey privateKey) {
this.privateKey = privateKey;
- StringWriter writer = new StringWriter();
- PEMWriter pemWriter = new PEMWriter(writer);
- try {
- pemWriter.writeObject(privateKey);
- pemWriter.flush();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- String s = writer.toString();
- setPrivateKeyPem(PemUtils.removeBeginEnd(s));
+ String privateKeyPem = KeycloakModelUtils.getPemFromKey(privateKey);
+ setPrivateKeyPem(privateKeyPem);
}
protected RequiredCredentialModel initRequiredCredentialModel(String type) {
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java
index 2c9a8c95a94..e418441de2c 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java
@@ -6,6 +6,7 @@ import org.keycloak.models.RoleModel;
import org.keycloak.models.jpa.entities.ApplicationRoleEntity;
import org.keycloak.models.jpa.entities.RealmRoleEntity;
import org.keycloak.models.jpa.entities.RoleEntity;
+import org.keycloak.models.utils.KeycloakModelUtils;
import javax.persistence.EntityManager;
import java.util.HashSet;
@@ -94,27 +95,13 @@ public class RoleAdapter implements RoleModel {
return set;
}
- public static boolean searchFor(RoleModel role, RoleModel composite, Set visited) {
- if (visited.contains(composite)) return false;
- visited.add(composite);
- Set composites = composite.getComposites();
- if (composites.contains(role)) return true;
- for (RoleModel contained : composites) {
- if (!contained.isComposite()) continue;
- if (searchFor(role, contained, visited)) return true;
- }
- return false;
- }
-
-
-
@Override
public boolean hasRole(RoleModel role) {
if (this.equals(role)) return true;
if (!isComposite()) return false;
Set visited = new HashSet();
- return searchFor(role, this, visited);
+ return KeycloakModelUtils.searchFor(role, this, visited);
}
@Override
diff --git a/model/mongo/pom.xml b/model/mongo/pom.xml
index 537112a6185..d1b5952dd4c 100755
--- a/model/mongo/pom.xml
+++ b/model/mongo/pom.xml
@@ -5,7 +5,7 @@
keycloak-parent
org.keycloak
- 1.0-alpha-1
+ 1.0-alpha-2-SNAPSHOT
../../pom.xml
4.0.0
@@ -41,11 +41,6 @@
picketlink-common
provided
-
- org.picketlink
- picketlink-idm-api
- provided
-
org.mongodb
mongo-java-driver
@@ -54,7 +49,7 @@
de.flapdoodle.embed
de.flapdoodle.embed.mongo
- test
+ provided
junit
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/MongoDBSessionFactoryTestContext.java b/model/mongo/src/main/java/org/keycloak/models/mongo/MongoDBSessionFactoryTestContext.java
deleted file mode 100755
index 1b00fa5b542..00000000000
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/MongoDBSessionFactoryTestContext.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package org.keycloak.test.common;
-
-import de.flapdoodle.embed.mongo.MongodExecutable;
-import de.flapdoodle.embed.mongo.MongodProcess;
-import de.flapdoodle.embed.mongo.MongodStarter;
-import de.flapdoodle.embed.mongo.config.MongodConfig;
-import de.flapdoodle.embed.mongo.distribution.Version;
-import de.flapdoodle.embed.process.runtime.Network;
-import org.jboss.resteasy.logging.Logger;
-import org.keycloak.services.utils.PropertiesManager;
-
-/**
- * @author Marek Posolda
- */
-public class MongoDBSessionFactoryTestContext implements SessionFactoryTestContext {
-
- protected static final Logger logger = Logger.getLogger(MongoDBSessionFactoryTestContext.class);
- private static final int PORT = PropertiesManager.MONGO_DEFAULT_PORT_UNIT_TESTS;
-
- private MongodExecutable mongodExe;
- private MongodProcess mongod;
-
- @Override
- public void beforeTestClass() {
- logger.info("Bootstrapping MongoDB on localhost, port " + PORT);
- try {
- mongodExe = MongodStarter.getDefaultInstance().prepare(new MongodConfig(Version.V2_0_5, PORT, Network.localhostIsIPv6()));
- mongod = mongodExe.start();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- logger.info("MongoDB bootstrapped successfully");
- }
-
- @Override
- public void afterTestClass() {
- if (mongodExe != null) {
- if (mongod != null) {
- mongod.stop();
- }
- mongodExe.stop();
- }
- logger.info("MongoDB stopped successfully");
-
- // Reset this, so other tests are not affected
- PropertiesManager.setDefaultSessionFactoryType();
- }
-
- @Override
- public void initEnvironment() {
- PropertiesManager.setSessionFactoryType(PropertiesManager.SESSION_FACTORY_MONGO);
- PropertiesManager.setMongoHost("localhost");
- PropertiesManager.setMongoPort(PORT);
- PropertiesManager.setMongoDbName("keycloakTest");
- PropertiesManager.setDropDatabaseOnStartup(true);
- }
-}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/MongoRunnerListener.java b/model/mongo/src/main/java/org/keycloak/models/mongo/MongoRunnerListener.java
deleted file mode 100755
index a1f67883c82..00000000000
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/MongoRunnerListener.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.keycloak.services.listeners;
-
-import de.flapdoodle.embed.mongo.MongodExecutable;
-import de.flapdoodle.embed.mongo.MongodProcess;
-import de.flapdoodle.embed.mongo.MongodStarter;
-import de.flapdoodle.embed.mongo.config.MongodConfig;
-import de.flapdoodle.embed.mongo.distribution.Version;
-import de.flapdoodle.embed.process.runtime.Network;
-import org.jboss.resteasy.logging.Logger;
-import org.keycloak.services.utils.PropertiesManager;
-
-import javax.servlet.ServletContextEvent;
-import javax.servlet.ServletContextListener;
-
-/**
- * @author Marek Posolda
- */
-public class MongoRunnerListener implements ServletContextListener {
-
- protected static final Logger logger = Logger.getLogger(MongoRunnerListener.class);
-
- private MongodExecutable mongodExe;
- private MongodProcess mongod;
-
- @Override
- public void contextInitialized(ServletContextEvent sce) {
- if (PropertiesManager.bootstrapEmbeddedMongoAtContextInit()) {
- int port = PropertiesManager.getMongoPort();
- logger.info("Going to start embedded MongoDB on port=" + port);
-
- try {
- mongodExe = MongodStarter.getDefaultInstance().prepare(new MongodConfig(Version.V2_0_5, port, Network.localhostIsIPv6()));
- mongod = mongodExe.start();
- } catch (Exception e) {
- logger.warn("Couldn't start Embedded Mongo on port " + port + ". Maybe it's already started? Cause: " + e.getClass() + " " + e.getMessage());
- if (logger.isDebugEnabled()) {
- logger.debug("Failed to start MongoDB", e);
- }
- }
- }
- }
-
- @Override
- public void contextDestroyed(ServletContextEvent sce) {
- if (mongodExe != null) {
- if (mongod != null) {
- logger.info("Going to stop embedded MongoDB.");
- mongod.stop();
- }
- mongodExe.stop();
- }
- }
-}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/PropertiesManager.java b/model/mongo/src/main/java/org/keycloak/models/mongo/PropertiesManager.java
deleted file mode 100755
index 9e897ae238d..00000000000
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/PropertiesManager.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package org.keycloak.models.mongo;
-
-/**
- * @author Marek Posolda
- */
-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"));
- }
-}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/api/AbstractAttributedNoSQLObject.java b/model/mongo/src/main/java/org/keycloak/models/mongo/api/AbstractAttributedNoSQLObject.java
deleted file mode 100644
index 81546ba4698..00000000000
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/api/AbstractAttributedNoSQLObject.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package org.keycloak.models.mongo.api;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author Marek Posolda
- */
-public abstract class AbstractAttributedNoSQLObject extends AbstractNoSQLObject implements AttributedNoSQLObject {
-
- // Simple hashMap for now (no thread-safe)
- private Map attributes = new HashMap();
-
- @Override
- public void setAttribute(String name, String value) {
- attributes.put(name, value);
- }
-
- @Override
- public void removeAttribute(String name) {
- // attributes.remove(name);
-
- // ensure that particular attribute has null value, so it will be deleted in DB. TODO: needs to be improved
- attributes.put(name, null);
- }
-
- @Override
- public String getAttribute(String name) {
- return attributes.get(name);
- }
-
- @Override
- public Map getAttributes() {
- return Collections.unmodifiableMap(attributes);
- }
-}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/api/AbstractNoSQLObject.java b/model/mongo/src/main/java/org/keycloak/models/mongo/api/AbstractMongoEntity.java
similarity index 58%
rename from model/mongo/src/main/java/org/keycloak/models/mongo/api/AbstractNoSQLObject.java
rename to model/mongo/src/main/java/org/keycloak/models/mongo/api/AbstractMongoEntity.java
index 837e5e46441..aaaffabe07f 100644
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/api/AbstractNoSQLObject.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/api/AbstractMongoEntity.java
@@ -3,10 +3,10 @@ package org.keycloak.models.mongo.api;
/**
* @author Marek Posolda
*/
-public abstract class AbstractNoSQLObject implements NoSQLObject {
+public abstract class AbstractMongoEntity implements MongoEntity {
@Override
- public void afterRemove(NoSQL noSQL) {
+ public void afterRemove(MongoStore mongoStore) {
// Empty by default
}
}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/api/AttributedNoSQLObject.java b/model/mongo/src/main/java/org/keycloak/models/mongo/api/AttributedNoSQLObject.java
deleted file mode 100644
index 45accd1c1ca..00000000000
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/api/AttributedNoSQLObject.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.keycloak.models.mongo.api;
-
-import java.util.Map;
-
-/**
- * @author Marek Posolda
- */
-public interface AttributedNoSQLObject extends NoSQLObject {
-
- void setAttribute(String name, String value);
-
- void removeAttribute(String name);
-
- String getAttribute(String name);
-
- Map getAttributes();
-}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/api/NoSQLCollection.java b/model/mongo/src/main/java/org/keycloak/models/mongo/api/MongoCollection.java
similarity index 92%
rename from model/mongo/src/main/java/org/keycloak/models/mongo/api/NoSQLCollection.java
rename to model/mongo/src/main/java/org/keycloak/models/mongo/api/MongoCollection.java
index 80b63326f0f..8695d12393c 100644
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/api/NoSQLCollection.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/api/MongoCollection.java
@@ -15,7 +15,7 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Documented
@Retention(RUNTIME)
@Inherited
-public @interface NoSQLCollection {
+public @interface MongoCollection {
String collectionName();
}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/api/NoSQLObject.java b/model/mongo/src/main/java/org/keycloak/models/mongo/api/MongoEntity.java
similarity index 62%
rename from model/mongo/src/main/java/org/keycloak/models/mongo/api/NoSQLObject.java
rename to model/mongo/src/main/java/org/keycloak/models/mongo/api/MongoEntity.java
index 02422439367..6af6bbc0ead 100644
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/api/NoSQLObject.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/api/MongoEntity.java
@@ -1,16 +1,16 @@
package org.keycloak.models.mongo.api;
/**
- * Base interface for object, which is persisted in NoSQL database
+ * Base interface for object, which is persisted in Mongo
*
* @author Marek Posolda
*/
-public interface NoSQLObject {
+public interface MongoEntity {
/**
- * Lifecycle callback, which is called after removal of this object from NoSQL database.
+ * Lifecycle callback, which is called after removal of this object from Mongo.
* It may be useful for triggering removal of wired objects.
*/
- void afterRemove(NoSQL noSQL);
+ void afterRemove(MongoStore mongoStore);
}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/api/NoSQLField.java b/model/mongo/src/main/java/org/keycloak/models/mongo/api/MongoField.java
similarity index 94%
rename from model/mongo/src/main/java/org/keycloak/models/mongo/api/NoSQLField.java
rename to model/mongo/src/main/java/org/keycloak/models/mongo/api/MongoField.java
index 3af69a71357..4f19f83e7de 100644
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/api/NoSQLField.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/api/MongoField.java
@@ -14,7 +14,7 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Target({METHOD, FIELD})
@Documented
@Retention(RUNTIME)
-public @interface NoSQLField {
+public @interface MongoField {
// TODO: fieldName add lazy loading?
}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/api/NoSQLId.java b/model/mongo/src/main/java/org/keycloak/models/mongo/api/MongoId.java
similarity index 94%
rename from model/mongo/src/main/java/org/keycloak/models/mongo/api/NoSQLId.java
rename to model/mongo/src/main/java/org/keycloak/models/mongo/api/MongoId.java
index 06ed01e655b..6799635cc54 100644
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/api/NoSQLId.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/api/MongoId.java
@@ -14,5 +14,5 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Target({METHOD, FIELD})
@Documented
@Retention(RUNTIME)
-public @interface NoSQLId {
+public @interface MongoId {
}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/api/MongoStore.java b/model/mongo/src/main/java/org/keycloak/models/mongo/api/MongoStore.java
new file mode 100755
index 00000000000..89e4bb744c4
--- /dev/null
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/api/MongoStore.java
@@ -0,0 +1,43 @@
+package org.keycloak.models.mongo.api;
+
+import com.mongodb.DBObject;
+
+import java.util.List;
+
+/**
+ * @author Marek Posolda
+ */
+public interface MongoStore {
+
+ /**
+ * Insert new object
+ *
+ * @param object to update
+ */
+ void insertObject(MongoEntity object);
+
+ /**
+ * Update existing object
+ *
+ * @param object to update
+ */
+ void updateObject(MongoEntity object);
+
+
+ T loadObject(Class type, String oid);
+
+ T loadSingleObject(Class type, DBObject query);
+
+ List loadObjects(Class type, DBObject query);
+
+ // Object must have filled oid
+ boolean removeObject(MongoEntity object);
+
+ boolean removeObject(Class extends MongoEntity> type, String oid);
+
+ boolean removeObjects(Class extends MongoEntity> type, DBObject query);
+
+ boolean pushItemToList(MongoEntity object, String listPropertyName, S itemToPush, boolean skipIfAlreadyPresent);
+
+ void pullItemFromList(MongoEntity object, String listPropertyName, S itemToPull);
+}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/api/NoSQL.java b/model/mongo/src/main/java/org/keycloak/models/mongo/api/NoSQL.java
deleted file mode 100755
index 0a63606e2d5..00000000000
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/api/NoSQL.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.keycloak.models.mongo.api;
-
-import org.keycloak.models.mongo.api.query.NoSQLQuery;
-import org.keycloak.models.mongo.api.query.NoSQLQueryBuilder;
-
-import java.util.List;
-
-/**
- * @author Marek Posolda
- */
-public interface NoSQL {
-
- /**
- * Insert object if it's oid is null. Otherwise update
- */
- void saveObject(NoSQLObject object);
-
- T loadObject(Class type, String oid);
-
- T loadSingleObject(Class type, NoSQLQuery query);
-
- List loadObjects(Class type, NoSQLQuery query);
-
- // Object must have filled oid
- void removeObject(NoSQLObject object);
-
- void removeObject(Class extends NoSQLObject> type, String oid);
-
- void removeObjects(Class extends NoSQLObject> type, NoSQLQuery query);
-
- NoSQLQueryBuilder createQueryBuilder();
-
- void pushItemToList(NoSQLObject object, String listPropertyName, S itemToPush);
-
- void pullItemFromList(NoSQLObject object, String listPropertyName, S itemToPull);
-}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/api/query/NoSQLQuery.java b/model/mongo/src/main/java/org/keycloak/models/mongo/api/query/NoSQLQuery.java
deleted file mode 100644
index 29cc0f31ab3..00000000000
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/api/query/NoSQLQuery.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.keycloak.models.mongo.api.query;
-
-import java.util.Collections;
-import java.util.Map;
-
-/**
- * @author Marek Posolda
- */
-public class NoSQLQuery {
-
- private final Map queryAttributes;
-
- NoSQLQuery(Map queryAttributes) {
- this.queryAttributes = queryAttributes;
- };
-
- public Map getQueryAttributes() {
- return Collections.unmodifiableMap(queryAttributes);
- }
-
- @Override
- public String toString() {
- return "NoSQLQuery [" + queryAttributes + "]";
- }
-
-}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/api/query/NoSQLQueryBuilder.java b/model/mongo/src/main/java/org/keycloak/models/mongo/api/query/NoSQLQueryBuilder.java
deleted file mode 100644
index dcdb5752a37..00000000000
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/api/query/NoSQLQueryBuilder.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package org.keycloak.models.mongo.api.query;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author Marek Posolda
- */
-public abstract class NoSQLQueryBuilder {
-
- private Map queryAttributes = new HashMap();
-
- protected NoSQLQueryBuilder() {};
-
- public NoSQLQuery build() {
- return new NoSQLQuery(queryAttributes);
- }
-
- public NoSQLQueryBuilder andCondition(String name, Object value) {
- this.put(name, value);
- return this;
- }
-
- public abstract NoSQLQueryBuilder inCondition(String name, List> values);
-
- protected void put(String name, Object value) {
- queryAttributes.put(name, value);
- }
-
-}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/api/types/Converter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/api/types/Converter.java
index a6b6c869e6d..9c963c14644 100644
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/api/types/Converter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/api/types/Converter.java
@@ -8,7 +8,13 @@ package org.keycloak.models.mongo.api.types;
*/
public interface Converter {
- S convertObject(T objectToConvert);
+ /**
+ * Convert object from one type to expected type
+ *
+ * @param converterContext Encapsulates reference to converted object and other things, which might be helpful in conversion
+ * @return converted object
+ */
+ S convertObject(ConverterContext converterContext);
Class extends T> getConverterObjectType();
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/api/types/ConverterContext.java b/model/mongo/src/main/java/org/keycloak/models/mongo/api/types/ConverterContext.java
new file mode 100644
index 00000000000..aecb8c09ef5
--- /dev/null
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/api/types/ConverterContext.java
@@ -0,0 +1,36 @@
+package org.keycloak.models.mongo.api.types;
+
+import java.util.List;
+
+/**
+ * @author Marek Posolda
+ */
+public class ConverterContext {
+
+ // object to convert
+ private final T objectToConvert;
+
+ // expected return type, which could be useful information in some converters, so they are able to dynamically instantiate types
+ private final Class> expectedReturnType;
+
+ // in case that expected return type is generic type (like "List"), then genericTypes could contain list of expected generic arguments
+ private final List> genericTypes;
+
+ public ConverterContext(T objectToConvert, Class> expectedReturnType, List> genericTypes) {
+ this.objectToConvert = objectToConvert;
+ this.expectedReturnType = expectedReturnType;
+ this.genericTypes = genericTypes;
+ }
+
+ public T getObjectToConvert() {
+ return objectToConvert;
+ }
+
+ public Class> getExpectedReturnType() {
+ return expectedReturnType;
+ }
+
+ public List> getGenericTypes() {
+ return genericTypes;
+ }
+}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/api/types/TypeConverter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/api/types/TypeConverter.java
index e0979307745..05ad4d1b570 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/api/types/TypeConverter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/api/types/TypeConverter.java
@@ -46,19 +46,22 @@ public class TypeConverter {
}
- public S convertDBObjectToApplicationObject(Object dbObject, Class expectedApplicationObjectType) {
+ public Object convertDBObjectToApplicationObject(ConverterContext