From 772ef3cd10205fb52be42bf8ee81ddb3d5316335 Mon Sep 17 00:00:00 2001 From: mposolda Date: Fri, 24 Jul 2015 12:46:47 +0200 Subject: [PATCH] Mongo model fix --- .../impl/updates/Update1_2_0_Beta1.java | 2 +- .../mongo/api/types/MapperRegistry.java | 8 +++++ .../mongo/impl/MongoStoreImpl.java | 6 ++-- .../impl/types/BasicDBObjectToMapMapper.java | 36 ++++++++++++++++--- .../mongo/impl/types/MapMapper.java | 13 ++++--- .../mongo/keycloak/adapters/RealmAdapter.java | 1 + 6 files changed, 54 insertions(+), 12 deletions(-) diff --git a/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_Beta1.java b/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_Beta1.java index abaae4cd42..aedd9f9af2 100644 --- a/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_Beta1.java +++ b/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_Beta1.java @@ -249,7 +249,7 @@ public class Update1_2_0_Beta1 extends Update { dbMapper.put("protocolMapper", protocolMapper.getProtocolMapper()); Map config = protocolMapper.getConfig(); - BasicDBObject dbConfig = MapMapper.convertMap(config); + BasicDBObject dbConfig = MapMapper.convertMap(config, null); dbMapper.put("config", dbConfig); dbProtocolMappers.add(dbMapper); diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/api/types/MapperRegistry.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/api/types/MapperRegistry.java index bafda1ef22..90c9355668 100755 --- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/api/types/MapperRegistry.java +++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/api/types/MapperRegistry.java @@ -47,6 +47,10 @@ public class MapperRegistry { public S convertDBObjectToApplicationObject(MapperContext context) { + if (context.getObjectToConvert() == null) { + return null; + } + Object dbObject = context.getObjectToConvert(); Class expectedApplicationObjectType = context.getExpectedReturnType(); @@ -74,6 +78,10 @@ public class MapperRegistry { public S convertApplicationObjectToDBObject(Object applicationObject, Class expectedDBObjectType) { + if (applicationObject == null) { + return null; + } + Class appObjectType = applicationObject.getClass(); Mapper mapper = (Mapper)getAppConverterForType(appObjectType, appObjectMappers); if (mapper == null) { diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/MongoStoreImpl.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/MongoStoreImpl.java index a496c0b1ec..94049f5674 100755 --- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/MongoStoreImpl.java +++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/MongoStoreImpl.java @@ -79,9 +79,9 @@ public class MongoStoreImpl implements MongoStore { mapperRegistry.addAppObjectMapper(new ListMapper(mapperRegistry, Set.class)); mapperRegistry.addDBObjectMapper(new BasicDBListToSetMapper(mapperRegistry)); - mapperRegistry.addAppObjectMapper(new MapMapper(HashMap.class)); - mapperRegistry.addAppObjectMapper(new MapMapper(Map.class)); - mapperRegistry.addDBObjectMapper(new BasicDBObjectToMapMapper()); + mapperRegistry.addAppObjectMapper(new MapMapper(mapperRegistry, HashMap.class)); + mapperRegistry.addAppObjectMapper(new MapMapper(mapperRegistry, Map.class)); + mapperRegistry.addDBObjectMapper(new BasicDBObjectToMapMapper(mapperRegistry)); // Enum converters mapperRegistry.addAppObjectMapper(new EnumToStringMapper()); diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/types/BasicDBObjectToMapMapper.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/types/BasicDBObjectToMapMapper.java index 14ada88dab..316d7712c6 100644 --- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/types/BasicDBObjectToMapMapper.java +++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/types/BasicDBObjectToMapMapper.java @@ -3,31 +3,44 @@ package org.keycloak.connections.mongo.impl.types; import com.mongodb.BasicDBObject; import org.keycloak.connections.mongo.api.types.Mapper; import org.keycloak.connections.mongo.api.types.MapperContext; +import org.keycloak.connections.mongo.api.types.MapperRegistry; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; /** - * For now, there is support just for convert to Map * * @author Marek Posolda */ public class BasicDBObjectToMapMapper implements Mapper { + private final MapperRegistry mapperRegistry; + + public BasicDBObjectToMapMapper(MapperRegistry mapperRegistry) { + this.mapperRegistry = mapperRegistry; + } + @Override public Map convertObject(MapperContext context) { BasicDBObject dbObjectToConvert = context.getObjectToConvert(); + Type expectedElementValueType = context.getGenericTypes().get(1); HashMap result = new HashMap(); for (Map.Entry entry : dbObjectToConvert.entrySet()) { String key = entry.getKey(); - Object value = entry.getValue(); + Object dbValue = entry.getValue(); // Workaround as manually inserted numbers into mongo may be treated as "Double" - if (value instanceof Double && context.getGenericTypes().get(1) == Integer.class) { - value = ((Double)value).intValue(); + if (dbValue instanceof Double && expectedElementValueType == Integer.class) { + dbValue = ((Double)dbValue).intValue(); } + MapperContext newContext = getMapperContext(dbValue, expectedElementValueType); + Object value = mapperRegistry.convertDBObjectToApplicationObject(newContext); + if (key.contains(MapMapper.DOT_PLACEHOLDER)) { key = key.replaceAll(MapMapper.DOT_PLACEHOLDER, "."); } @@ -46,4 +59,19 @@ public class BasicDBObjectToMapMapper implements Mapper { public Class getExpectedReturnType() { return Map.class; } + + private MapperContext getMapperContext(Object dbValue, Type expectedElementValueType) { + if (expectedElementValueType instanceof Class) { + Class clazz = (Class) expectedElementValueType; + return new MapperContext<>(dbValue, clazz, null); + } else if (expectedElementValueType instanceof ParameterizedType) { + ParameterizedType parameterized = (ParameterizedType) expectedElementValueType; + Class expectedClazz = (Class) parameterized.getRawType(); + Type[] generics = parameterized.getActualTypeArguments(); + + return new MapperContext<>(dbValue, expectedClazz, Arrays.asList(generics)); + } else { + throw new IllegalArgumentException("Unexpected type: '" + expectedElementValueType + "' for converting " + dbValue); + } + } } diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/types/MapMapper.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/types/MapMapper.java index d4f0d29afb..5ec174bd08 100644 --- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/types/MapMapper.java +++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/impl/types/MapMapper.java @@ -3,6 +3,7 @@ package org.keycloak.connections.mongo.impl.types; import com.mongodb.BasicDBObject; import org.keycloak.connections.mongo.api.types.Mapper; import org.keycloak.connections.mongo.api.types.MapperContext; +import org.keycloak.connections.mongo.api.types.MapperRegistry; import java.util.Map; import java.util.Set; @@ -17,30 +18,34 @@ public class MapMapper implements Mapper { // Just some dummy way of encoding . character as it's not allowed by mongo in key fields static final String DOT_PLACEHOLDER = "###"; + private final MapperRegistry mapperRegistry; private final Class mapType; - public MapMapper(Class mapType) { + public MapMapper(MapperRegistry mapperRegistry, Class mapType) { + this.mapperRegistry = mapperRegistry; this.mapType = mapType; } @Override public BasicDBObject convertObject(MapperContext context) { T mapToConvert = context.getObjectToConvert(); - return convertMap(mapToConvert); + return convertMap(mapToConvert, mapperRegistry); } - public static BasicDBObject convertMap(Map mapToConvert) { + public static BasicDBObject convertMap(Map mapToConvert, MapperRegistry mapperRegistry) { BasicDBObject dbObject = new BasicDBObject(); Set entries = mapToConvert.entrySet(); for (Map.Entry entry : entries) { String key = (String)entry.getKey(); Object value = entry.getValue(); + Object dbValue = mapperRegistry==null ? entry.getValue() : mapperRegistry.convertApplicationObjectToDBObject(value, Object.class); + if (key.contains(".")) { key = key.replaceAll("\\.", DOT_PLACEHOLDER); } - dbObject.put(key, value); + dbObject.put(key, dbValue); } return dbObject; } diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java index 3a6368734a..823a51b3c7 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java @@ -1310,6 +1310,7 @@ public class RealmAdapter extends AbstractMongoAdapter impleme model.setDescription(entity.getDescription()); model.setBuiltIn(entity.isBuiltIn()); model.setTopLevel(entity.isTopLevel()); + model.setProviderId(entity.getProviderId()); return model; }