Author: bdaw
Date: 2008-12-15 13:10:32 -0500 (Mon, 15 Dec 2008)
New Revision: 164
Modified:
trunk/identity-impl/src/main/java/org/jboss/identity/impl/api/RoleManagerImpl.java
trunk/identity-impl/src/main/java/org/jboss/identity/impl/repository/FallbackIdentityStoreRepository.java
trunk/identity-impl/src/main/java/org/jboss/identity/impl/store/FeaturesMetaDataImpl.java
trunk/identity-impl/src/main/java/org/jboss/identity/impl/store/hibernate/HibernateIdentityStoreImpl.java
trunk/identity-impl/src/main/java/org/jboss/identity/impl/store/ldap/LDAPIdentityStoreImpl.java
trunk/identity-impl/src/test/resources/organization-test-config.xml
trunk/identity-spi/src/main/java/org/jboss/identity/spi/store/FeaturesMetaData.java
Log:
improvements to Fallback repository
Modified:
trunk/identity-impl/src/main/java/org/jboss/identity/impl/api/RoleManagerImpl.java
===================================================================
---
trunk/identity-impl/src/main/java/org/jboss/identity/impl/api/RoleManagerImpl.java 2008-12-15
09:53:22 UTC (rev 163)
+++
trunk/identity-impl/src/main/java/org/jboss/identity/impl/api/RoleManagerImpl.java 2008-12-15
18:10:32 UTC (rev 164)
@@ -225,7 +225,7 @@
}
catch (OperationNotSupportedException e)
{
- throw new IdentityException("Role management not supported");
+ throw new IdentityException("Role management not supported", e);
}
}
Modified:
trunk/identity-impl/src/main/java/org/jboss/identity/impl/repository/FallbackIdentityStoreRepository.java
===================================================================
---
trunk/identity-impl/src/main/java/org/jboss/identity/impl/repository/FallbackIdentityStoreRepository.java 2008-12-15
09:53:22 UTC (rev 163)
+++
trunk/identity-impl/src/main/java/org/jboss/identity/impl/repository/FallbackIdentityStoreRepository.java 2008-12-15
18:10:32 UTC (rev 164)
@@ -36,22 +36,46 @@
import org.jboss.identity.spi.configuration.metadata.IdentityStoreConfigurationMetaData;
import
org.jboss.identity.spi.configuration.metadata.IdentityRepositoryConfigurationMetaData;
import org.jboss.identity.spi.credential.IdentityObjectCredential;
+import org.jboss.identity.spi.credential.IdentityObjectCredentialType;
import org.jboss.identity.exception.IdentityException;
import org.jboss.identity.impl.store.SimpleIdentityStoreInvocationContext;
+import org.jboss.identity.impl.api.PageSearchControl;
+import org.jboss.identity.impl.api.SortByNameSearchControl;
+import org.jboss.identity.impl.api.AttributeFilterSearchControl;
+import org.jboss.identity.impl.api.NameFilterSearchControl;
+import org.jboss.identity.api.Identity;
import java.util.Map;
import java.util.Collection;
import java.util.Set;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.LinkedList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Arrays;
+import com.sun.corba.se.spi.activation._ActivatorImplBase;
+
/**
- * LADP + DB
+ * <p>In FallbackIdentityStoreRepository one IdentityStore plays the role of
default store. Any operation that cannot be
+ * handled with other IdentityObjectType/IdentityStore mappings will fallback to such
IdentityStore. The most common example
+ * is RDBMS + LDAP configuration. LDAP has limmited schema for possible profile
attributes so for LDAP entries part of
+ * profile can be stored in RDBMS by syncing entries into default store.</p>
+ * <p>For any relationship that is not supported in other stores, or between
entries persisted in two different stores,
+ * proper IdentityObjects will be synced to default store and if possible, such
relationship will be created. </p>
*
+ *
* @author <a href="mailto:boleslaw.dawidowicz at redhat.com">Boleslaw
Dawidowicz</a>
* @version : 0.1 $
*/
public class FallbackIdentityStoreRepository extends AbstractIdentityStoreRepository
{
+ //TODO: filter out controls based on features MD before passing
+ //TODO: configuration option to store not mapped attributes in default store
+ //TODO: configuration option to fallback named relationships to default store when not
supported in mapped one
+
private final String id;
private IdentityStore defaultIdentityStore;
@@ -61,6 +85,12 @@
//TODO: rewrite this to other config object?
private IdentityRepositoryConfigurationMetaData configurationMD;
+ public static final String ALLOW_NOT_DEFINED_ATTRIBUTES =
"allowNotDefinedAttributes";
+
+ private FeaturesMetaData featuresMetaData;
+
+ private boolean allowNotDefinedAttributes = false;
+
public FallbackIdentityStoreRepository(String id)
{
this.id = id;
@@ -87,6 +117,94 @@
defaultIdentityStore = bootstrappedIdentityStores.get(isId);
}
+ String allowNotDefineAttributes =
configurationMD.getOptionSingleValue(ALLOW_NOT_DEFINED_ATTRIBUTES);
+
+ if (allowNotDefineAttributes != null &&
allowNotDefineAttributes.equalsIgnoreCase("true"))
+ {
+ this.allowNotDefinedAttributes = true;
+ }
+
+ // A wrapper around all stores features meta data
+ featuresMetaData = new FeaturesMetaData()
+ {
+
+ public boolean isNamedRelationshipsSupported()
+ {
+ // If there is any IdentityStore that supports named relationships...
+ for (IdentityStore identityStore : getIdentityStoreMappings().values())
+ {
+ if (identityStore.getSupportedFeatures().isNamedRelationshipsSupported())
+ {
+ return true;
+ }
+ }
+ return
defaultIdentityStore.getSupportedFeatures().isNamedRelationshipsSupported();
+ }
+
+ public boolean isControlSupported(IdentityObjectType identityObjectType,
IdentityObjectSearchControl control)
+ {
+ return
resolveIdentityStore(identityObjectType).getSupportedFeatures().isControlSupported(identityObjectType,
control);
+ }
+
+ public boolean isControlSupported(IdentityObjectType identityObjectType, Class
controlClazz)
+ {
+ return
resolveIdentityStore(identityObjectType).getSupportedFeatures().isControlSupported(identityObjectType,
controlClazz);
+ }
+
+ public Set<String> getSupportedIdentityObjectTypes()
+ {
+ Set<String> supportedIOTs = new HashSet<String>();
+
+ for (IdentityStore identityStore : getIdentityStoreMappings().values())
+ {
+
supportedIOTs.addAll(identityStore.getSupportedFeatures().getSupportedIdentityObjectTypes());
+ }
+
supportedIOTs.addAll(defaultIdentityStore.getSupportedFeatures().getSupportedRelationshipTypes());
+
+ return supportedIOTs;
+ }
+
+ public boolean isIdentityObjectTypeSupported(IdentityObjectType
identityObjectType)
+ {
+ return
resolveIdentityStore(identityObjectType).getSupportedFeatures().isIdentityObjectTypeSupported(identityObjectType);
+ }
+
+ public boolean isRelationshipTypeSupported(IdentityObjectType fromType,
IdentityObjectType toType, IdentityObjectRelationshipType relationshipType) throws
IdentityException
+ {
+ IdentityStore fromStore = resolveIdentityStore(fromType);
+
+ IdentityStore toStore = resolveIdentityStore(toType);
+
+ if (fromStore == toStore)
+ {
+ return
fromStore.getSupportedFeatures().isRelationshipTypeSupported(fromType, toType,
relationshipType);
+ }
+ else
+ {
+ return
defaultIdentityStore.getSupportedFeatures().isRelationshipTypeSupported(fromType, toType,
relationshipType);
+ }
+
+ }
+
+ public Set<String> getSupportedRelationshipTypes()
+ {
+ Set<String> supportedRelTypes = new HashSet<String>();
+
+ for (IdentityStore identityStore : getIdentityStoreMappings().values())
+ {
+
supportedRelTypes.addAll(identityStore.getSupportedFeatures().getSupportedRelationshipTypes());
+ }
+
supportedRelTypes.addAll(defaultIdentityStore.getSupportedFeatures().getSupportedRelationshipTypes());
+
+ return supportedRelTypes;
+ }
+
+ public boolean isCredentialSupported(IdentityObjectType identityObjectType,
IdentityObjectCredentialType credentialType)
+ {
+ return
resolveIdentityStore(identityObjectType).getSupportedFeatures().isCredentialSupported(identityObjectType,
credentialType);
+ }
+ };
+
}
public void bootstrap(IdentityStoreConfigurationMetaData configurationMD) throws
IdentityException
@@ -131,8 +249,7 @@
public FeaturesMetaData getSupportedFeatures()
{
- //TODO: a wrapper around all stores metadata
- return null;
+ return featuresMetaData;
}
IdentityStore resolveIdentityStore(IdentityObject io)
@@ -221,7 +338,7 @@
public IdentityObject findIdentityObject(IdentityStoreInvocationContext
invocationContext, String id) throws IdentityException
{
- //TODO: store
+ //TODO: information about the store mapping should be encoded in type as now its
like random guess...
for (IdentityStore identityStore : getIdentityStoreMappings().values())
{
@@ -251,11 +368,63 @@
boolean parent,
IdentityObjectSearchControl[]
controls) throws IdentityException
{
- //TODO:
- IdentityStoreInvocationContext targetCtx =
resolveInvocationContext(defaultIdentityStore, invocationCxt);
+ // Check in the mapped store and merge with default
- return defaultIdentityStore.findIdentityObject(targetCtx, identity,
relationshipType, parent, controls);
+ IdentityStore mappedStore = resolveIdentityStore(identity);
+ IdentityStoreInvocationContext mappedCtx = resolveInvocationContext(mappedStore,
invocationCxt);
+
+ IdentityStoreInvocationContext defaultCtx =
resolveInvocationContext(defaultIdentityStore, invocationCxt);
+
+
+ if (mappedStore == defaultIdentityStore)
+ {
+ return defaultIdentityStore.findIdentityObject(defaultCtx, identity,
relationshipType, parent, controls);
+ }
+
+ Collection<IdentityObject> results =
mappedStore.findIdentityObject(mappedCtx, identity, relationshipType, parent, controls);
+
+ Collection<IdentityObject> objects =
defaultIdentityStore.findIdentityObject(defaultCtx, identity, relationshipType, parent,
controls);
+
+ PageSearchControl pageSearchControl = null;
+ SortByNameSearchControl sortSearchControl = null;
+
+ if (controls != null)
+ {
+ for (IdentityObjectSearchControl control : controls)
+ {
+ if (control instanceof PageSearchControl)
+ {
+ pageSearchControl = (PageSearchControl)control;
+ }
+ else if (control instanceof SortByNameSearchControl)
+ {
+ sortSearchControl = (SortByNameSearchControl)control;
+ }
+ }
+ }
+
+
+ // If default store contain related relationships merge and sort/page once more
+ if (objects != null && objects.size() != 0)
+ {
+ results.addAll(objects);
+
+ //TODO: hardcoded List
+ if (pageSearchControl != null && results instanceof List)
+ {
+ results = cutPageFromResults((List<IdentityObject>)results,
pageSearchControl);
+ }
+
+ //TODO: hardcoded List
+ if (sortSearchControl != null && results instanceof List)
+ {
+ sortByName((List<IdentityObject>)results,
sortSearchControl.isAscending());
+ }
+ }
+
+ return results;
+
}
public IdentityObjectRelationship createRelationship(IdentityStoreInvocationContext
invocationCxt, IdentityObject fromIdentity, IdentityObject toIdentity,
IdentityObjectRelationshipType relationshipType, String relationshipName, boolean
createNames) throws IdentityException
@@ -270,7 +439,12 @@
if (fromStore == toStore)
{
- return fromStore.createRelationship(toTargetCtx, fromIdentity, toIdentity,
relationshipType, relationshipName, createNames);
+ // If relationship is named and target store doesn't support named
relationships it need to be put in default store anyway
+ if (relationshipName == null ||
+ (relationshipName != null &&
fromStore.getSupportedFeatures().isNamedRelationshipsSupported()))
+ {
+ return fromStore.createRelationship(toTargetCtx, fromIdentity, toIdentity,
relationshipType, relationshipName, createNames);
+ }
}
if (!hasIdentityObject(defaultTargetCtx, defaultIdentityStore, fromIdentity))
@@ -298,8 +472,12 @@
if (fromStore == toStore)
{
- fromStore.removeRelationship(toTargetCtx, fromIdentity, toIdentity,
relationshipType, relationshipName);
- return;
+ if (relationshipName == null ||
+ (relationshipName != null &&
fromStore.getSupportedFeatures().isNamedRelationshipsSupported()))
+ {
+ fromStore.removeRelationship(toTargetCtx, fromIdentity, toIdentity,
relationshipType, relationshipName);
+ return;
+ }
}
if (!hasIdentityObject(defaultTargetCtx, defaultIdentityStore, fromIdentity))
@@ -373,41 +551,101 @@
}
return defaultIdentityStore.resolveRelationships(defaultTargetCtx, fromIdentity,
toIdentity);
- }
+ }
public String createRelationshipName(IdentityStoreInvocationContext ctx, String name)
throws IdentityException, OperationNotSupportedException
{
- IdentityStoreInvocationContext defaultCtx =
resolveInvocationContext(defaultIdentityStore, ctx);
+ Set<IdentityStore> stores = new
HashSet<IdentityStore>(getIdentityStoreMappings().values());
- //TODO: For now just assume that named relationships are in default one
- return defaultIdentityStore.createRelationshipName(defaultCtx, name);
+ // For any IdentityStore that supports named relationships...
+ for (IdentityStore identityStore : stores)
+ {
+ if (identityStore.getSupportedFeatures().isNamedRelationshipsSupported())
+ {
+ IdentityStoreInvocationContext storeCtx =
resolveInvocationContext(identityStore, ctx);
+ identityStore.createRelationshipName(storeCtx, name);
+
+ }
+ }
+
+ if (!getIdentityStoreMappings().values().contains(defaultIdentityStore) &&
+ defaultIdentityStore.getSupportedFeatures().isNamedRelationshipsSupported())
+ {
+ IdentityStoreInvocationContext defaultCtx =
resolveInvocationContext(defaultIdentityStore, ctx);
+
+ defaultIdentityStore.createRelationshipName(defaultCtx, name);
+ }
+
+ return name;
}
public String removeRelationshipName(IdentityStoreInvocationContext ctx, String name)
throws IdentityException, OperationNotSupportedException
{
- IdentityStoreInvocationContext defaultCtx =
resolveInvocationContext(defaultIdentityStore, ctx);
+ Set<IdentityStore> stores = new
HashSet<IdentityStore>(getIdentityStoreMappings().values());
- //TODO: For now just assume that named relationships are in default one
- return defaultIdentityStore.removeRelationshipName(defaultCtx, name);
+ // For any IdentityStore that supports named relationships...
+ for (IdentityStore identityStore : stores)
+ {
+ if (identityStore.getSupportedFeatures().isNamedRelationshipsSupported())
+ {
+ IdentityStoreInvocationContext storeCtx =
resolveInvocationContext(identityStore, ctx);
+ identityStore.removeRelationshipName(storeCtx, name);
+
+ }
+ }
+
+ if (!getIdentityStoreMappings().values().contains(defaultIdentityStore) &&
+ defaultIdentityStore.getSupportedFeatures().isNamedRelationshipsSupported())
+ {
+ IdentityStoreInvocationContext defaultCtx =
resolveInvocationContext(defaultIdentityStore, ctx);
+
+ defaultIdentityStore.removeRelationshipName(defaultCtx, name);
+ }
+
+ return name;
}
public Set<String> getRelationshipNames(IdentityStoreInvocationContext ctx,
IdentityObjectSearchControl[] controls) throws IdentityException,
OperationNotSupportedException
{
- IdentityStoreInvocationContext defaultCtx =
resolveInvocationContext(defaultIdentityStore, ctx);
+ Set<IdentityStore> stores = new
HashSet<IdentityStore>(getIdentityStoreMappings().values());
+ Set<String> results = new HashSet<String>();
- //TODO: For now just assume that named relationships are in default one
- return defaultIdentityStore.getRelationshipNames(defaultCtx, controls);
+ // For any IdentityStore that supports named relationships...
+ for (IdentityStore identityStore : stores)
+ {
+ if (identityStore.getSupportedFeatures().isNamedRelationshipsSupported())
+ {
+ IdentityStoreInvocationContext storeCtx =
resolveInvocationContext(identityStore, ctx);
+ results.addAll(identityStore.getRelationshipNames(storeCtx, controls));
+
+ }
+ }
+
+ if (defaultIdentityStore.getSupportedFeatures().isNamedRelationshipsSupported())
+ {
+ IdentityStoreInvocationContext defaultCtx =
resolveInvocationContext(defaultIdentityStore, ctx);
+
+ results.addAll(defaultIdentityStore.getRelationshipNames(defaultCtx,
controls));
+ }
+
+ return results;
}
public Set<String> getRelationshipNames(IdentityStoreInvocationContext ctx,
IdentityObject identity, IdentityObjectSearchControl[] controls) throws IdentityException,
OperationNotSupportedException
{
+
+ IdentityStore toStore = resolveIdentityStore(identity);
+ IdentityStoreInvocationContext targetCtx = resolveInvocationContext(toStore, ctx);
+
+ if (toStore.getSupportedFeatures().isNamedRelationshipsSupported())
+ {
+ return toStore.getRelationshipNames(targetCtx, identity, controls);
+ }
IdentityStoreInvocationContext defaultCtx =
resolveInvocationContext(defaultIdentityStore, ctx);
-
- //TODO: For now just assume that named relationships are in default one
- return defaultIdentityStore.getRelationshipNames(defaultCtx, identity, controls);
+ return defaultIdentityStore.getRelationshipNames(defaultCtx, identity, controls);
}
public boolean validateCredential(IdentityStoreInvocationContext ctx, IdentityObject
identityObject, IdentityObjectCredential credential) throws IdentityException
@@ -427,55 +665,262 @@
}
- public <T extends IdentityObjectType> Set<String>
getSupportedAttributeNames(IdentityStoreInvocationContext invocationContext, T
identityType) throws IdentityException
+ public Set<String> getSupportedAttributeNames(IdentityStoreInvocationContext
invocationContext, IdentityObjectType identityType) throws IdentityException
{
- //TODO: for profile stored in two stores this need to be merged with results from
defaultAttributeStore. For now just use the default one.
+ Set<String> results;
- IdentityStoreInvocationContext targetCtx =
resolveInvocationContext(defaultAttributeStore, invocationContext);
+ IdentityStore toStore = resolveIdentityStore(identityType);
+ IdentityStoreInvocationContext targetCtx = resolveInvocationContext(toStore,
invocationContext);
- return defaultAttributeStore.getSupportedAttributeNames(targetCtx, identityType);
- //return
resolveIdentityStore(identityType).getSupportedAttributeNames(invocationContext,
identityType);
+ results = toStore.getSupportedAttributeNames(targetCtx, identityType);
+
+ if (toStore != defaultAttributeStore)
+ {
+ IdentityStoreInvocationContext defaultCtx =
resolveInvocationContext(defaultAttributeStore, invocationContext);
+
+ results.addAll(defaultAttributeStore.getSupportedAttributeNames(defaultCtx,
identityType));
+ }
+
+ return results;
}
public Map<String, String[]> getAttributes(IdentityStoreInvocationContext
invocationContext, IdentityObject identity) throws IdentityException
{
- //TODO: for profile stored in two stores this need to be merged with results from
defaultAttributeStore. For now just use the default one.
+ Map<String, String[]> results;
- IdentityStoreInvocationContext targetCtx =
resolveInvocationContext(defaultAttributeStore, invocationContext);
+ IdentityStore toStore = resolveIdentityStore(identity);
+ IdentityStoreInvocationContext targetCtx = resolveInvocationContext(toStore,
invocationContext);
- return defaultAttributeStore.getAttributes(targetCtx, identity);
- //return resolveIdentityStore(identity).getAttributes(invocationContext,
identity);
+ results = toStore.getAttributes(targetCtx, identity);
+
+ if (toStore != defaultAttributeStore)
+ {
+ IdentityStoreInvocationContext defaultCtx =
resolveInvocationContext(defaultAttributeStore, invocationContext);
+
+ Map<String, String[]> defaultAttrs =
defaultAttributeStore.getAttributes(defaultCtx, identity);
+
+ // Add only those attributes which are missing - don't overwrite or merge
existing values
+ for (Map.Entry<String, String[]> entry : defaultAttrs.entrySet())
+ {
+ if (!results.keySet().contains(entry.getKey()))
+ {
+ results.put(entry.getKey(), entry.getValue());
+ }
+ }
+ }
+
+ return results;
}
public void updateAttributes(IdentityStoreInvocationContext invocationCtx,
IdentityObject identity, Map<String, String[]> attributes) throws IdentityException
{
- //TODO: for profile stored in two stores this need to be merged with results from
defaultAttributeStore. For now just use the default one.
+ Map<String, String[]> filteredAttrs = new HashMap<String, String[]>();
+ Map<String, String[]> leftAttrs = new HashMap<String, String[]>();
- IdentityStoreInvocationContext targetCtx =
resolveInvocationContext(defaultAttributeStore, invocationCtx);
+ IdentityStore toStore = resolveIdentityStore(identity);
+ IdentityStoreInvocationContext targetCtx = resolveInvocationContext(toStore,
invocationCtx);
- defaultAttributeStore.updateAttributes(targetCtx, identity, attributes);
- //resolveIdentityStore(identity).updateAttributes(invocationCtx, identity,
attributes);
+ // Put supported attrs to the main store
+ if (toStore != defaultAttributeStore)
+ {
+ Set<String> supportedAttrs = toStore.getSupportedAttributeNames(targetCtx,
identity.getIdentityType());
+
+ // Filter out supported and not supported attributes
+ for (Map.Entry<String, String[]> entry : attributes.entrySet())
+ {
+ if (supportedAttrs.contains(entry.getKey()))
+ {
+ filteredAttrs.put(entry.getKey(), entry.getValue());
+ }
+ else
+ {
+ leftAttrs.put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ toStore.updateAttributes(targetCtx, identity, filteredAttrs);
+
+
+ }
+ else
+ {
+ leftAttrs = attributes;
+ }
+
+ IdentityStoreInvocationContext defaultCtx =
resolveInvocationContext(defaultAttributeStore, invocationCtx);
+
+ if (isAllowNotDefinedAttributes())
+ {
+ defaultAttributeStore.updateAttributes(defaultCtx, identity, leftAttrs);
+ }
+ else
+ {
+ Set<String> supportedAttrs =
defaultAttributeStore.getSupportedAttributeNames(defaultCtx, identity.getIdentityType());
+ for (Map.Entry<String, String[]> entry : leftAttrs.entrySet())
+ {
+ if (!supportedAttrs.contains(entry.getKey()))
+ {
+ throw new IdentityException("Cannot update not defined attribute. Use
'"
+ + ALLOW_NOT_DEFINED_ATTRIBUTES + "' option to pass such
attributes to default IdentityStore anyway." +
+ "Attribute name: " + entry.getKey());
+ }
+ }
+ defaultAttributeStore.updateAttributes(defaultCtx, identity, leftAttrs);
+ }
+
}
public void addAttributes(IdentityStoreInvocationContext invocationCtx, IdentityObject
identity, Map<String, String[]> attributes) throws IdentityException
{
- //TODO: for profile stored in two stores this need to be merged with results from
defaultAttributeStore. For now just use the default one.
- IdentityStoreInvocationContext targetCtx =
resolveInvocationContext(defaultAttributeStore, invocationCtx);
+ Map<String, String[]> filteredAttrs = new HashMap<String, String[]>();
+ Map<String, String[]> leftAttrs = new HashMap<String, String[]>();
- defaultAttributeStore.addAttributes(targetCtx, identity, attributes);
- //resolveIdentityStore(identity).addAttributes(invocationCtx, identity,
attributes);
+ IdentityStore toStore = resolveIdentityStore(identity);
+ IdentityStoreInvocationContext targetCtx = resolveInvocationContext(toStore,
invocationCtx);
+
+ // Put supported attrs to the main store
+ if (toStore != defaultAttributeStore)
+ {
+ Set<String> supportedAttrs = toStore.getSupportedAttributeNames(targetCtx,
identity.getIdentityType());
+
+ // Filter out supported and not supported attributes
+ for (Map.Entry<String, String[]> entry : attributes.entrySet())
+ {
+ if (supportedAttrs.contains(entry.getKey()))
+ {
+ filteredAttrs.put(entry.getKey(), entry.getValue());
+ }
+ else
+ {
+ leftAttrs.put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ toStore.addAttributes(targetCtx, identity, filteredAttrs);
+
+
+ }
+ else
+ {
+ leftAttrs = attributes;
+ }
+
+ IdentityStoreInvocationContext defaultCtx =
resolveInvocationContext(defaultAttributeStore, invocationCtx);
+
+ if (isAllowNotDefinedAttributes())
+ {
+ defaultAttributeStore.addAttributes(defaultCtx, identity, leftAttrs);
+ }
+ else
+ {
+ Set<String> supportedAttrs =
defaultAttributeStore.getSupportedAttributeNames(defaultCtx, identity.getIdentityType());
+ for (Map.Entry<String, String[]> entry : leftAttrs.entrySet())
+ {
+ // if we hit some unsupported attribute at this stage that we cannot
store...
+ if (!supportedAttrs.contains(entry.getKey()))
+ {
+ throw new IdentityException("Cannot add not defined attribute. Use
'"
+ + ALLOW_NOT_DEFINED_ATTRIBUTES + "' option to pass such
attributes to default IdentityStore anyway." +
+ "Attribute name: " + entry.getKey());
+ }
+
+ }
+ defaultAttributeStore.addAttributes(defaultCtx, identity, filteredAttrs);
+ }
+
}
public void removeAttributes(IdentityStoreInvocationContext invocationCtx,
IdentityObject identity, String[] attributes) throws IdentityException
{
- //TODO: for profile stored in two stores this need to be merged with results from
defaultAttributeStore. For now just use the default one.
+ List<String> filteredAttrs = new LinkedList<String>();
+ List<String> leftAttrs = new LinkedList<String>();
- IdentityStoreInvocationContext targetCtx =
resolveInvocationContext(defaultAttributeStore, invocationCtx);
+ IdentityStore toStore = resolveIdentityStore(identity);
+ IdentityStoreInvocationContext targetCtx = resolveInvocationContext(toStore,
invocationCtx);
- defaultAttributeStore.removeAttributes(targetCtx, identity, attributes);
- //resolveIdentityStore(identity).removeAttributes(invocationCtx, identity,
attributes);
+ // Put supported attrs to the main store
+ if (toStore != defaultAttributeStore)
+ {
+ Set<String> supportedAttrs = toStore.getSupportedAttributeNames(targetCtx,
identity.getIdentityType());
+
+ // Filter out supported and not supported attributes
+ for (String name : attributes)
+ {
+ if (supportedAttrs.contains(name))
+ {
+ filteredAttrs.add(name);
+ }
+ else
+ {
+ leftAttrs.add(name);
+ }
+ }
+
+ toStore.removeAttributes(targetCtx, identity, filteredAttrs.toArray(new
String[filteredAttrs.size()]));
+
+
+ }
+ else
+ {
+ leftAttrs = Arrays.asList(attributes);
+ }
+
+ IdentityStoreInvocationContext defaultCtx =
resolveInvocationContext(defaultAttributeStore, invocationCtx);
+
+ if (isAllowNotDefinedAttributes())
+ {
+ defaultAttributeStore.removeAttributes(defaultCtx, identity,
leftAttrs.toArray(new String[leftAttrs.size()]));
+ }
+ else
+ {
+ Set<String> supportedAttrs =
defaultAttributeStore.getSupportedAttributeNames(defaultCtx, identity.getIdentityType());
+ for (String name : leftAttrs)
+ {
+ if (!supportedAttrs.contains(name))
+ {
+ throw new IdentityException("Cannot remove not defined attribute. Use
'"
+ + ALLOW_NOT_DEFINED_ATTRIBUTES + "' option to pass such
attributes to default IdentityStore anyway." +
+ "Attribute name: " + name);
+ }
+ }
+ defaultAttributeStore.removeAttributes(defaultCtx, identity,
leftAttrs.toArray(new String[leftAttrs.size()]));
+ }
}
+ private void sortByName(List<IdentityObject> objects, final boolean ascending)
+ {
+ Collections.sort(objects, new Comparator<IdentityObject>(){
+ public int compare(IdentityObject o1, IdentityObject o2)
+ {
+ if (ascending)
+ {
+ return o1.getName().compareTo(o2.getName());
+ }
+ else
+ {
+ return o2.getName().compareTo(o1.getName());
+ }
+ }
+ });
+ }
+ //TODO: other way?
+ private List<IdentityObject> cutPageFromResults(List<IdentityObject>
objects, PageSearchControl pageControl)
+ {
+ List<IdentityObject> results = new LinkedList<IdentityObject>();
+ for (int i = pageControl.getOffset(); i < pageControl.getOffset() +
pageControl.getLimit(); i++)
+ {
+ if (i < objects.size())
+ {
+ results.add(objects.get(i));
+ }
+ }
+ return results;
+ }
+
+ public boolean isAllowNotDefinedAttributes()
+ {
+ return allowNotDefinedAttributes;
+ }
}
\ No newline at end of file
Modified:
trunk/identity-impl/src/main/java/org/jboss/identity/impl/store/FeaturesMetaDataImpl.java
===================================================================
---
trunk/identity-impl/src/main/java/org/jboss/identity/impl/store/FeaturesMetaDataImpl.java 2008-12-15
09:53:22 UTC (rev 163)
+++
trunk/identity-impl/src/main/java/org/jboss/identity/impl/store/FeaturesMetaDataImpl.java 2008-12-15
18:10:32 UTC (rev 164)
@@ -52,15 +52,20 @@
private final Map<String, Set<String>> supportedCredentials;
+ private final boolean namedRelationshipsSupport;
+
// <Relationship Type, <From IdentityType, To IdentityType>>
private final Map<String, Map<String, Set<String>>>
supportedRelationshipMappings = new HashMap<String, Map<String,
Set<String>>>();
public FeaturesMetaDataImpl(IdentityStoreConfigurationMetaData configurationMD,
- Set<Class> supportedControls)
+ Set<Class> supportedControls,
+ boolean namedRelationshipsSupport)
{
- Map<String, Set<String>> supportedCredentials = new HashMap<String,
Set<String>>();
+ this.namedRelationshipsSupport = namedRelationshipsSupport;
+ Map<String, Set<String>> supportedCredentials = new HashMap<String,
Set<String>>();
+
for (IdentityObjectTypeMetaData typeMetaData :
configurationMD.getSupportedIdentityTypes())
{
supportedTypeNames.add(typeMetaData.getName());
@@ -137,10 +142,11 @@
}
+ }
-
-
-
+ public boolean isNamedRelationshipsSupported()
+ {
+ return namedRelationshipsSupport;
}
public boolean isControlSupported(IdentityObjectType identityObjectType,
IdentityObjectSearchControl control)
Modified:
trunk/identity-impl/src/main/java/org/jboss/identity/impl/store/hibernate/HibernateIdentityStoreImpl.java
===================================================================
---
trunk/identity-impl/src/main/java/org/jboss/identity/impl/store/hibernate/HibernateIdentityStoreImpl.java 2008-12-15
09:53:22 UTC (rev 163)
+++
trunk/identity-impl/src/main/java/org/jboss/identity/impl/store/hibernate/HibernateIdentityStoreImpl.java 2008-12-15
18:10:32 UTC (rev 164)
@@ -163,7 +163,7 @@
id = configurationMD.getId();
- supportedFeatures = new FeaturesMetaDataImpl(configurationMD,
supportedIdentityObjectSearchControls);
+ supportedFeatures = new FeaturesMetaDataImpl(configurationMD,
supportedIdentityObjectSearchControls, true);
String persistenceUnit = configurationMD.getOptionSingleValue(PERSISTENCE_UNIT);
@@ -1227,6 +1227,14 @@
throw new IdentityException("Cannot update readonly attribute: "
+ entry.getKey());
}
}
+ else
+ {
+ if (!isAllowNotDefinedAttributes)
+ {
+ throw new IdentityException("Cannot update not defined attribute. Use
'" + ALLOW_NOT_DEFINED_ATTRIBUTES +
+ "' option if needed. Attribute name: " +
entry.getKey());
+ }
+ }
}
HibernateIdentityObject hibernateObject = safeGet(ctx, identity);
@@ -1260,13 +1268,21 @@
AttributeMetaData amd = mdMap.get(entry.getKey());
if (amd != null && !amd.isMultivalued() &&
entry.getValue().length > 1)
{
- throw new IdentityException("Cannot assigned multiply values to
single valued attribute: " + entry.getKey());
+ throw new IdentityException("Cannot add multiply values to single
valued attribute: " + entry.getKey());
}
if (amd != null && amd.isReadonly())
{
- throw new IdentityException("Cannot update readonly attribute: "
+ entry.getKey());
+ throw new IdentityException("Cannot add readonly attribute: " +
entry.getKey());
}
}
+ else
+ {
+ if (!isAllowNotDefinedAttributes)
+ {
+ throw new IdentityException("Cannot add not defined attribute. Use
'" + ALLOW_NOT_DEFINED_ATTRIBUTES +
+ "' option if needed. Attribute name: " +
entry.getKey());
+ }
+ }
}
HibernateIdentityObject hibernateObject = safeGet(ctx, identity);
@@ -1302,6 +1318,14 @@
throw new IdentityException("Cannot remove required attribute: "
+ attributes[i]);
}
}
+ else
+ {
+ if (!isAllowNotDefinedAttributes)
+ {
+ throw new IdentityException("Cannot remove not defined attribute. Use
'" + ALLOW_NOT_DEFINED_ATTRIBUTES +
+ "' option if needed. Attribute name: " + attributes[i]);
+ }
+ }
}
Modified:
trunk/identity-impl/src/main/java/org/jboss/identity/impl/store/ldap/LDAPIdentityStoreImpl.java
===================================================================
---
trunk/identity-impl/src/main/java/org/jboss/identity/impl/store/ldap/LDAPIdentityStoreImpl.java 2008-12-15
09:53:22 UTC (rev 163)
+++
trunk/identity-impl/src/main/java/org/jboss/identity/impl/store/ldap/LDAPIdentityStoreImpl.java 2008-12-15
18:10:32 UTC (rev 164)
@@ -88,6 +88,10 @@
public class LDAPIdentityStoreImpl implements IdentityStore
{
+ //TODO: external JNDI
+ //TODO: more options for connection configuration
+ //TODO: JNDI connection credentials encoding (pluggable?)
+
private static Logger log = Logger.getLogger(LDAPIdentityStoreImpl.class.getName());
private final String id;
@@ -106,7 +110,7 @@
static {
// List all supported controls classes
- //TODO:
+ //TODO: attribute filter
supportedSearchControls.add(SortByNameSearchControl.class);
supportedSearchControls.add(PageSearchControl.class);
supportedSearchControls.add(NameFilterSearchControl.class);
@@ -129,7 +133,7 @@
configuration = new SimpleLDAPIdentityStoreConfiguration(configurationMD);
- supportedFeatures = new FeaturesMetaDataImpl(configurationMD,
supportedSearchControls);
+ supportedFeatures = new FeaturesMetaDataImpl(configurationMD,
supportedSearchControls, false);
// Attribute mappings - helper structures
@@ -927,17 +931,16 @@
}
}
- if (sortSearchControl != null)
+ if (pageSearchControl != null)
{
- sortByName(objects, sortSearchControl.isAscending());
+ objects = cutPageFromResults(objects, pageSearchControl);
}
- if (pageSearchControl != null)
+ if (sortSearchControl != null)
{
- objects = cutPageFromResults(objects, pageSearchControl);
+ sortByName(objects, sortSearchControl.isAscending());
}
-
return objects;
}
Modified: trunk/identity-impl/src/test/resources/organization-test-config.xml
===================================================================
--- trunk/identity-impl/src/test/resources/organization-test-config.xml 2008-12-15
09:53:22 UTC (rev 163)
+++ trunk/identity-impl/src/test/resources/organization-test-config.xml 2008-12-15
18:10:32 UTC (rev 164)
@@ -54,6 +54,12 @@
<options/>
</identity-store-mapping>
</identity-store-mappings>
+ <options>
+ <option>
+ <name>allowNotDefinedAttributes</name>
+ <value>true</value>
+ </option>
+ </options>
</repository>
<repository>
<id>Sample Portal Repository DB</id>
@@ -80,6 +86,12 @@
<options/>
</identity-store-mapping>
</identity-store-mappings>
+ <options>
+ <option>
+ <name>allowNotDefinedAttributes</name>
+ <value>true</value>
+ </option>
+ </options>
</repository>
<repository>
<id>RedHat Repository DB+LDAP</id>
@@ -108,6 +120,12 @@
<options/>
</identity-store-mapping>
</identity-store-mappings>
+ <options>
+ <option>
+ <name>allowNotDefinedAttributes</name>
+ <value>true</value>
+ </option>
+ </options>
</repository>
<repository>
<id>Sample Portal Repository DB+LDAP</id>
@@ -140,6 +158,12 @@
<options/>
</identity-store-mapping>
</identity-store-mappings>
+ <options>
+ <option>
+ <name>allowNotDefinedAttributes</name>
+ <value>true</value>
+ </option>
+ </options>
</repository>
</repositories>
<stores>
@@ -262,6 +286,10 @@
<name>isRealmAware</name>
<value>true</value>
</option>
+ <option>
+ <name>allowNotDefinedAttributes</name>
+ <value>true</value>
+ </option>
</options>
</identity-store>
<identity-store>
Modified:
trunk/identity-spi/src/main/java/org/jboss/identity/spi/store/FeaturesMetaData.java
===================================================================
---
trunk/identity-spi/src/main/java/org/jboss/identity/spi/store/FeaturesMetaData.java 2008-12-15
09:53:22 UTC (rev 163)
+++
trunk/identity-spi/src/main/java/org/jboss/identity/spi/store/FeaturesMetaData.java 2008-12-15
18:10:32 UTC (rev 164)
@@ -81,6 +81,13 @@
throws IdentityException;
/**
+ *
+ * @return
+ */
+ boolean isNamedRelationshipsSupported();
+
+
+ /**
* @return Set of relationship type names supported in this store
*/
Set<String> getSupportedRelationshipTypes();