/*
* JBoss, a division of Red Hat
* Copyright 2006, Red Hat Middleware, LLC, and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.identity.idm.impl.store.hibernate;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.criterion.Restrictions;
import org.jboss.identity.idm.exception.IdentityException;
import org.jboss.identity.idm.impl.api.AttributeFilterSearchControl;
import org.jboss.identity.idm.impl.api.NameFilterSearchControl;
import org.jboss.identity.idm.impl.api.PageSearchControl;
import org.jboss.identity.idm.impl.api.SortByNameSearchControl;
import org.jboss.identity.idm.impl.model.hibernate.HibernateIdentityObject;
import org.jboss.identity.idm.impl.model.hibernate.HibernateIdentityObjectAttribute;
import org.jboss.identity.idm.impl.model.hibernate.HibernateIdentityObjectBinaryAttribute;
import org.jboss.identity.idm.impl.model.hibernate.HibernateIdentityObjectCredential;
import org.jboss.identity.idm.impl.model.hibernate.HibernateIdentityObjectCredentialType;
import org.jboss.identity.idm.impl.model.hibernate.HibernateIdentityObjectRelationship;
import org.jboss.identity.idm.impl.model.hibernate.HibernateIdentityObjectRelationshipName;
import org.jboss.identity.idm.impl.model.hibernate.HibernateIdentityObjectRelationshipType;
import org.jboss.identity.idm.impl.model.hibernate.HibernateIdentityObjectTextAttribute;
import org.jboss.identity.idm.impl.model.hibernate.HibernateIdentityObjectType;
import org.jboss.identity.idm.impl.model.hibernate.HibernateRealm;
import org.jboss.identity.idm.impl.store.FeaturesMetaDataImpl;
import org.jboss.identity.idm.spi.configuration.metadata.IdentityObjectAttributeMetaData;
import org.jboss.identity.idm.spi.configuration.metadata.IdentityObjectTypeMetaData;
import org.jboss.identity.idm.spi.configuration.metadata.IdentityStoreConfigurationMetaData;
import org.jboss.identity.idm.spi.configuration.IdentityStoreConfigurationContext;
import org.jboss.identity.idm.spi.exception.OperationNotSupportedException;
import org.jboss.identity.idm.spi.model.IdentityObject;
import org.jboss.identity.idm.spi.model.IdentityObjectAttribute;
import org.jboss.identity.idm.spi.model.IdentityObjectCredential;
import org.jboss.identity.idm.spi.model.IdentityObjectCredentialType;
import org.jboss.identity.idm.spi.model.IdentityObjectRelationship;
import org.jboss.identity.idm.spi.model.IdentityObjectRelationshipType;
import org.jboss.identity.idm.spi.model.IdentityObjectType;
import org.jboss.identity.idm.spi.searchcontrol.IdentityObjectSearchControl;
import org.jboss.identity.idm.spi.store.FeaturesMetaData;
import org.jboss.identity.idm.spi.store.IdentityStore;
import org.jboss.identity.idm.spi.store.IdentityStoreInvocationContext;
import org.jboss.identity.idm.spi.store.IdentityStoreSession;
//import javax.persistence.Persistence;
import javax.naming.InitialContext;
import javax.naming.NamingException;
//import javax.persistence.Persistence;
/**
* @author <a href="mailto:boleslaw.dawidowicz at redhat.com">Boleslaw Dawidowicz</a>
* @version : 0.1 $
*/
public class HibernateIdentityStoreImpl implements IdentityStore
{
//TODO: logging
private final String QUERY_RELATIONSHIP_BY_FROM_TO =
"select r from HibernateIdentityObjectRelationship r where r.fromIdentityObject like :fromIO and " +
"r.toIdentityObject like :toIO";
private final String QUERY_RELATIONSHIP_BY_FROM_TO_TYPE =
"select r from HibernateIdentityObjectRelationship r where r.fromIdentityObject like :fromIO and " +
"r.toIdentityObject like :toIO and r.type.name like :typeName";
private final String QUERY_RELATIONSHIP_BY_FROM_TO_TYPE_NAME =
"select r from HibernateIdentityObjectRelationship r where r.fromIdentityObject like :fromIO and " +
"r.toIdentityObject like :toIO and r.type.name like :typeName and r.name.name like :name";
private final String QUERY_RELATIONSHIP_BY_IDENTITIES =
"select r from HibernateIdentityObjectRelationship r where " +
"(r.fromIdentityObject like :IO1 and r.toIdentityObject like :IO2) or " +
"(r.fromIdentityObject like :IO2 and r.toIdentityObject like :IO1)";
public static final String HIBERNATE_SESSION_FACTORY_REGISTRY_NAME = "hibernateSessionFactoryRegistryName";
public static final String HIBERNATE_CONFIGURATION = "hibernateConfiguration";
public static final String ADD_MAPPED_CLASSES = "addMappedClasses";
public static final String HIBERNATE_SESSION_FACTORY_JNDI_NAME = "hibernateSessionFactoryJNDIName";
public static final String POPULATE_MEMBERSHIP_TYPES = "populateRelationshipTypes";
public static final String POPULATE_IDENTITY_OBJECT_TYPES = "populateIdentityObjectTypes";
public static final String IS_REALM_AWARE = "isRealmAware";
public static final String ALLOW_NOT_DEFINED_ATTRIBUTES = "allowNotDefinedAttributes";
public static final String DEFAULT_REALM_NAME = HibernateIdentityStoreImpl.class.getName() + ".DEFAULT_REALM";
public static final String CREDENTIAL_TYPE_PASSWORD = "PASSWORD";
public static final String CREDENTIAL_TYPE_BINARY = "BINARY";
private String id;
private FeaturesMetaData supportedFeatures;
private SessionFactory sessionFactory;
private boolean isRealmAware = false;
private boolean isAllowNotDefinedAttributes = false;
// TODO: rewrite this into some more handy object
private IdentityStoreConfigurationMetaData configurationMD;
private static Set<Class<?>> supportedIdentityObjectSearchControls = new HashSet<Class<?>>();
private static Set<String> supportedCredentialTypes = new HashSet<String>();
// <IdentityObjectType name, Set<Attribute name>>
private Map<String, Set<String>> attributeMappings = new HashMap<String, Set<String>>();
// <IdentityObjectType name, <Attribute name, MD>
private Map<String, Map<String, IdentityObjectAttributeMetaData>> attributesMetaData = new HashMap<String, Map<String, IdentityObjectAttributeMetaData>>();
// <IdentityObjectType name, <Attribute store mapping, Attribute name>
private Map<String, Map<String, String>> reverseAttributeMappings = new HashMap<String, Map<String, String>>();
static {
// List all supported controls classes
supportedIdentityObjectSearchControls.add(PageSearchControl.class);
supportedIdentityObjectSearchControls.add(SortByNameSearchControl.class);
supportedIdentityObjectSearchControls.add(AttributeFilterSearchControl.class);
supportedIdentityObjectSearchControls.add(NameFilterSearchControl.class);
// credential types supported by this impl
supportedCredentialTypes.add(CREDENTIAL_TYPE_PASSWORD);
supportedCredentialTypes.add(CREDENTIAL_TYPE_BINARY);
}
public HibernateIdentityStoreImpl(String id)
{
this.id = id;
}
public void bootstrap(IdentityStoreConfigurationContext configurationContext) throws IdentityException
{
this.configurationMD = configurationContext.getStoreConfigurationMetaData();
id = configurationMD.getId();
supportedFeatures = new FeaturesMetaDataImpl(configurationMD, supportedIdentityObjectSearchControls, true, new HashSet<String>());
String populateMembershipTypes = configurationMD.getOptionSingleValue(POPULATE_MEMBERSHIP_TYPES);
String populateIdentityObjectTypes = configurationMD.getOptionSingleValue(POPULATE_IDENTITY_OBJECT_TYPES);
sessionFactory = bootstrapHibernateSessionFactory(configurationContext);
Session hibernateSession = sessionFactory.openSession();
// Attribute mappings - helper structures
for (IdentityObjectTypeMetaData identityObjectTypeMetaData : configurationMD.getSupportedIdentityTypes())
{
Set<String> names = new HashSet<String>();
Map<String, IdentityObjectAttributeMetaData> metadataMap = new HashMap<String, IdentityObjectAttributeMetaData>();
Map<String, String> reverseMap = new HashMap<String, String>();
for (IdentityObjectAttributeMetaData attributeMetaData : identityObjectTypeMetaData.getAttributes())
{
names.add(attributeMetaData.getName());
metadataMap.put(attributeMetaData.getName(), attributeMetaData);
if (attributeMetaData.getStoreMapping() != null)
{
reverseMap.put(attributeMetaData.getStoreMapping(), attributeMetaData.getName());
}
}
// Use unmodifiableSet as it'll be exposed directly
attributeMappings.put(identityObjectTypeMetaData.getName(), Collections.unmodifiableSet(names));
attributesMetaData.put(identityObjectTypeMetaData.getName(), metadataMap);
reverseAttributeMappings.put(identityObjectTypeMetaData.getName(), reverseMap);
}
attributeMappings = Collections.unmodifiableMap(attributeMappings);
if (populateMembershipTypes != null && populateMembershipTypes.equalsIgnoreCase("true"))
{
List<String> memberships = new LinkedList<String>();
for (String membership : configurationMD.getSupportedRelationshipTypes())
{
memberships.add(membership);
}
try
{
populateRelationshipTypes(hibernateSession, memberships.toArray(new String[memberships.size()]));
}
catch (Exception e)
{
throw new IdentityException("Failed to populate relationship types", e);
}
}
if (populateIdentityObjectTypes != null && populateIdentityObjectTypes.equalsIgnoreCase("true"))
{
List<String> types = new LinkedList<String>();
for (IdentityObjectTypeMetaData metaData : configurationMD.getSupportedIdentityTypes())
{
types.add(metaData.getName());
}
try
{
populateObjectTypes(hibernateSession, types.toArray(new String[types.size()]));
}
catch (Exception e)
{
throw new IdentityException("Failed to populate identity object types", e);
}
}
if (supportedCredentialTypes != null && supportedCredentialTypes.size() > 0)
{
try
{
populateCredentialTypes(hibernateSession, supportedCredentialTypes.toArray(new String[supportedCredentialTypes.size()]));
}
catch (Exception e)
{
throw new IdentityException("Failed to populated credential types");
}
}
String realmAware = configurationMD.getOptionSingleValue(IS_REALM_AWARE);
if (realmAware != null && realmAware.equalsIgnoreCase("true"))
{
this.isRealmAware = true;
}
String allowNotDefineAttributes = configurationMD.getOptionSingleValue(ALLOW_NOT_DEFINED_ATTRIBUTES);
if (allowNotDefineAttributes != null && allowNotDefineAttributes.equalsIgnoreCase("true"))
{
this.isAllowNotDefinedAttributes = true;
}
// Default realm
HibernateRealm realm = null;
try
{
hibernateSession.getTransaction().begin();
realm = (HibernateRealm)hibernateSession.
createCriteria(HibernateRealm.class).add(Restrictions.eq("name", DEFAULT_REALM_NAME)).uniqueResult();
hibernateSession.getTransaction().commit();
}
catch (HibernateException e)
{
// Realm does not exist
}
if (realm == null)
{
addRealm(hibernateSession, DEFAULT_REALM_NAME);
}
hibernateSession.flush();
hibernateSession.close();
}
protected SessionFactory bootstrapHibernateSessionFactory(IdentityStoreConfigurationContext configurationContext) throws IdentityException
{
String sfJNDIName = configurationContext.getStoreConfigurationMetaData().
getOptionSingleValue(HIBERNATE_SESSION_FACTORY_JNDI_NAME);
String sfRegistryName = configurationContext.getStoreConfigurationMetaData().
getOptionSingleValue(HIBERNATE_SESSION_FACTORY_REGISTRY_NAME);
String addMappedClasses = configurationContext.getStoreConfigurationMetaData().
getOptionSingleValue(ADD_MAPPED_CLASSES);
String hibernateConfiguration = configurationContext.getStoreConfigurationMetaData().
getOptionSingleValue(HIBERNATE_CONFIGURATION);
if (sfJNDIName != null)
{
try
{
return (SessionFactory)new InitialContext().lookup(sfJNDIName);
}
catch (NamingException e)
{
throw new IdentityException("Cannot obtain hibernate SessionFactory from provided JNDI name: " + sfJNDIName, e);
}
}
else if (sfRegistryName != null)
{
Object registryObject = configurationContext.getConfigurationRegistry().getObject(sfRegistryName);
if (registryObject == null)
{
throw new IdentityException("Cannot obtain hibernate SessionFactory from provided registry name: " + sfRegistryName);
}
if (!(registryObject instanceof SessionFactory))
{
throw new IdentityException("Cannot obtain hibernate SessionFactory from provided registry name: " + sfRegistryName
+ "; Registered object is not an instance of SessionFactory: " + registryObject.getClass().getName());
}
return (SessionFactory)registryObject;
}
else if (hibernateConfiguration != null)
{
try
{
AnnotationConfiguration config = new AnnotationConfiguration().configure(hibernateConfiguration);
//TODO: make it optional to add annotated classes here
if (addMappedClasses != null && addMappedClasses.equals("false"))
{
return config.buildSessionFactory();
}
else
{
return config.addAnnotatedClass(HibernateIdentityObject.class)
.addAnnotatedClass(HibernateIdentityObjectAttribute.class)
.addAnnotatedClass(HibernateIdentityObjectBinaryAttribute.class)
.addAnnotatedClass(HibernateIdentityObjectTextAttribute.class)
.addAnnotatedClass(HibernateIdentityObjectCredential.class)
.addAnnotatedClass(HibernateIdentityObjectCredentialType.class)
.addAnnotatedClass(HibernateIdentityObjectRelationship.class)
.addAnnotatedClass(HibernateIdentityObjectRelationshipName.class)
.addAnnotatedClass(HibernateIdentityObjectRelationshipType.class)
.addAnnotatedClass(HibernateIdentityObjectType.class)
.addAnnotatedClass(HibernateRealm.class).buildSessionFactory();
}
}
catch (Exception e)
{
throw new IdentityException("Cannot obtain hibernate SessionFactory using provided hibernate configuration: "+ hibernateConfiguration, e);
}
}
throw new IdentityException("Cannot obtain hibernate SessionFactory. None of supported options specified: "
+ HIBERNATE_SESSION_FACTORY_JNDI_NAME + ", " + HIBERNATE_SESSION_FACTORY_REGISTRY_NAME + ", " + HIBERNATE_CONFIGURATION);
}
public IdentityStoreSession createIdentityStoreSession() throws IdentityException
{
try
{
return new HibernateIdentityStoreSessionImpl(sessionFactory);
}
catch (Exception e)
{
throw new IdentityException("Failed to obtain Hibernate SessionFactory",e);
}
}
public String getId()
{
return id;
}
public void setId(String id)
{
this.id = id;
}
public FeaturesMetaData getSupportedFeatures()
{
return supportedFeatures;
}
public IdentityObject createIdentityObject(IdentityStoreInvocationContext invocationCtx, String name, IdentityObjectType identityObjectType) throws IdentityException
{
return createIdentityObject(invocationCtx, name, identityObjectType, null);
}
public IdentityObject createIdentityObject(IdentityStoreInvocationContext ctx,
String name,
IdentityObjectType identityObjectType,
Map<String, String[]> attributes) throws IdentityException
{
if (name == null)
{
throw new IllegalArgumentException("IdentityObject name is null");
}
checkIOType(identityObjectType);
Session session = getHibernateSession(ctx);
HibernateRealm realm = getRealm(session, ctx);
// Check if object with a given name and type is not present already
List<?> results = session.createQuery(HibernateIdentityObject.findIdentityObjectByNameAndType)
.setParameter("realm", realm)
.setParameter("name", name)
.setParameter("typeName", identityObjectType.getName())
.list();
if (results.size() != 0)
{
throw new IdentityException("IdentityObject already present in this IdentityStore:" +
"name=" + name + "; type=" + identityObjectType.getName() + "; realm=" + realm);
}
HibernateIdentityObjectType hibernateType = getHibernateIdentityObjectType(ctx, identityObjectType);
HibernateIdentityObject io = new HibernateIdentityObject(name, hibernateType, realm);
if (attributes != null)
{
for (Map.Entry<String, String[]> entry : attributes.entrySet())
{
io.addTextAttribute(entry.getKey(), entry.getValue());
}
}
try
{
getHibernateSession(ctx).persist(io);
}
catch (Exception e)
{
throw new IdentityException("Cannot persist new IdentityObject" + io, e);
}
return io;
}
public void removeIdentityObject(IdentityStoreInvocationContext ctx, IdentityObject identity) throws IdentityException
{
HibernateIdentityObject hibernateObject = safeGet(ctx, identity);
Session hibernateSession = getHibernateSession(ctx);
try
{
// Remove all related relationships
for (HibernateIdentityObjectRelationship relationship : hibernateObject.getFromRelationships())
{
relationship.getFromIdentityObject().getFromRelationships().remove(relationship);
relationship.getToIdentityObject().getToRelationships().remove(relationship);
hibernateSession.delete(relationship);
}
for (HibernateIdentityObjectRelationship relationship : hibernateObject.getToRelationships())
{
relationship.getFromIdentityObject().getFromRelationships().remove(relationship);
relationship.getToIdentityObject().getToRelationships().remove(relationship);
hibernateSession.delete(relationship);
}
hibernateSession.delete(hibernateObject);
}
catch (Exception e)
{
throw new IdentityException("Cannot remove IdentityObject" + identity, e);
}
}
public int getIdentityObjectsCount(IdentityStoreInvocationContext ctx, IdentityObjectType identityType) throws IdentityException
{
checkIOType(identityType);
HibernateIdentityObjectType jpaType = getHibernateIdentityObjectType(ctx, identityType);
Session hibernateSession = getHibernateSession(ctx);
int count;
try
{
count = ((Number)hibernateSession
.createQuery(HibernateIdentityObject.countIdentityObjectsByType)
.setParameter("typeName", jpaType.getName())
.setParameter("realm", getRealm(hibernateSession, ctx))
.uniqueResult()).intValue();
}
catch (Exception e)
{
throw new IdentityException("Cannot count stored IdentityObjects with type: " + identityType.getName(), e);
}
return count;
}
public IdentityObject findIdentityObject(IdentityStoreInvocationContext ctx, String name, IdentityObjectType type) throws IdentityException
{
if (name == null)
{
throw new IllegalArgumentException("IdentityObject name is null");
}
checkIOType(type);
HibernateIdentityObjectType hibernateType = getHibernateIdentityObjectType(ctx, type);
HibernateIdentityObject hibernateObject = null;
Session em = getHibernateSession(ctx);
try
{
hibernateObject = (HibernateIdentityObject)getHibernateSession(ctx).
createQuery(HibernateIdentityObject.findIdentityObjectByNameAndType)
.setParameter("realm", getRealm(em, ctx))
.setParameter("name", name)
.setParameter("typeName", hibernateType.getName())
.uniqueResult();
}
catch (Exception e)
{
throw new IdentityException("Cannot find IdentityObject with name '" + name + "' and type '" + type.getName() + "'", e);
}
return hibernateObject;
}
public IdentityObject findIdentityObject(IdentityStoreInvocationContext ctx, String id) throws IdentityException
{
if (id == null)
{
throw new IllegalArgumentException("id is null");
}
HibernateIdentityObject hibernateObject;
try
{
hibernateObject = (HibernateIdentityObject)getHibernateSession(ctx).get(HibernateIdentityObject.class, new Long(id));
}
catch(Exception e)
{
throw new IdentityException("Cannot find IdentityObject with id: " + id, e);
}
return hibernateObject;
}
@SuppressWarnings("unchecked")
public Collection<IdentityObject> findIdentityObject(IdentityStoreInvocationContext ctx,
IdentityObjectType identityType,
IdentityObjectSearchControl[] controls) throws IdentityException
{
checkIOType(identityType);
checkControls(controls);
PageSearchControl pageSearchControl = null;
SortByNameSearchControl sortSearchControl = null;
AttributeFilterSearchControl attributeFilterControl = null;
NameFilterSearchControl nameFilterSearchControl = null;
if (controls != null)
{
for (IdentityObjectSearchControl control : controls)
{
if (control instanceof PageSearchControl)
{
pageSearchControl = (PageSearchControl)control;
}
else if (control instanceof SortByNameSearchControl)
{
sortSearchControl = (SortByNameSearchControl)control;
}
else if (control instanceof AttributeFilterSearchControl)
{
attributeFilterControl = (AttributeFilterSearchControl)control;
}
else if (control instanceof NameFilterSearchControl)
{
nameFilterSearchControl = (NameFilterSearchControl)control;
}
}
}
HibernateIdentityObjectType hibernateType = getHibernateIdentityObjectType(ctx, identityType);
List<IdentityObject> results;
Session hibernateSession = getHibernateSession(ctx);
try
{
Query q = null;
if (sortSearchControl != null)
{
if (sortSearchControl.isAscending())
{
q = hibernateSession.createQuery(HibernateIdentityObject.findIdentityObjectsByTypeOrderedByNameAsc);
}
else
{
q = hibernateSession.createQuery(HibernateIdentityObject.findIdentityObjectsByTypeOrderedByNameDesc);
}
}
else
{
q = hibernateSession.createQuery(HibernateIdentityObject.findIdentityObjectsByType);
}
if (pageSearchControl != null)
{
if (pageSearchControl.getLimit() > 0)
{
q.setMaxResults(pageSearchControl.getLimit());
}
q.setFirstResult(pageSearchControl.getOffset());
}
q.setParameter("realm", getRealm(hibernateSession, ctx))
.setParameter("typeName", hibernateType.getName());
if (nameFilterSearchControl != null)
{
q.setParameter("nameFilter", nameFilterSearchControl.getFilter().replaceAll("\\*", "%"));
}
else
{
q.setParameter("nameFilter", "%");
}
results = (List<IdentityObject>)q.list();
}
catch (Exception e)
{
throw new IdentityException("Cannot find IdentityObjects with type '" + identityType.getName() + "'", e);
}
if (attributeFilterControl != null)
{
filterByAttributesValues(results, attributeFilterControl.getValues());
}
return results;
}
public Collection<IdentityObject> findIdentityObject(IdentityStoreInvocationContext ctx, IdentityObjectType identityType) throws IdentityException
{
return findIdentityObject(ctx, identityType, null);
}
@SuppressWarnings("unchecked")
public Collection<IdentityObject> findIdentityObject(IdentityStoreInvocationContext ctx,
IdentityObject identity,
IdentityObjectRelationshipType relationshipType,
boolean parent,
IdentityObjectSearchControl[] controls) throws IdentityException
{
//TODO:test
HibernateIdentityObject hibernateObject = safeGet(ctx, identity);
List<IdentityObject> results;
checkControls(controls);
PageSearchControl pageSearchControl = null;
SortByNameSearchControl sortSearchControl = null;
AttributeFilterSearchControl attributeFilterControl = null;
NameFilterSearchControl nameFilterSearchControl = null;
if (controls != null)
{
for (IdentityObjectSearchControl control : controls)
{
if (control instanceof PageSearchControl)
{
pageSearchControl = (PageSearchControl)control;
}
else if (control instanceof SortByNameSearchControl)
{
sortSearchControl = (SortByNameSearchControl)control;
}
else if (control instanceof AttributeFilterSearchControl)
{
attributeFilterControl = (AttributeFilterSearchControl)control;
}
else if (control instanceof NameFilterSearchControl)
{
nameFilterSearchControl = (NameFilterSearchControl)control;
}
}
}
boolean orderByName = false;
boolean ascending = true;
if (sortSearchControl != null)
{
orderByName = true;
ascending = sortSearchControl.isAscending();
}
try
{
org.hibernate.Query q = null;
StringBuilder hqlString = new StringBuilder("");
// if (orderByName)
// {
// hqlString.append(" orderBy ior.toIdentityObject.name");
// if (ascending)
// {
// hqlString.append(" asc");
// }
// }
if (parent)
{
if (relationshipType != null)
{
hqlString.append("select distinct ior.toIdentityObject from HibernateIdentityObjectRelationship ior where " +
"ior.toIdentityObject.name like :nameFilter and ior.type.name like :relType and ior.fromIdentityObject like :identity");
}
else
{
hqlString.append("select distinct ior.toIdentityObject from HibernateIdentityObjectRelationship ior where " +
"ior.toIdentityObject.name like :nameFilter and ior.fromIdentityObject like :identity");
}
if (orderByName)
{
hqlString.append(" orderBy ior.toIdentityObject.name");
if (ascending)
{
hqlString.append(" asc");
}
}
}
else
{
if (relationshipType != null)
{
hqlString.append("select distinct ior.fromIdentityObject from HibernateIdentityObjectRelationship ior where " +
"ior.fromIdentityObject.name like :nameFilter and ior.type.name like :relType and ior.toIdentityObject like :identity");
}
else
{
hqlString.append("select distinct ior.fromIdentityObject from HibernateIdentityObjectRelationship ior where " +
"ior.fromIdentityObject.name like :nameFilter and ior.toIdentityObject like :identity");
}
if (orderByName)
{
hqlString.append(" orderBy ior.toIdentityObject.name");
if (ascending)
{
hqlString.append(" asc");
}
}
}
q = getHibernateSession(ctx).createQuery(hqlString.toString())
.setParameter("identity",hibernateObject);
if (relationshipType != null)
{
q.setParameter("relType", relationshipType.getName());
}
if (nameFilterSearchControl != null)
{
q.setParameter("nameFilter", nameFilterSearchControl.getFilter().replaceAll("\\*", "%"));
}
else
{
q.setParameter("nameFilter", "%");
}
if (pageSearchControl != null)
{
q.setFirstResult(pageSearchControl.getOffset());
if (pageSearchControl.getLimit() > 0)
{
q.setMaxResults(pageSearchControl.getLimit());
}
}
results = q.list();
}
catch (Exception e)
{
throw new IdentityException("Cannot find IdentityObjects", e);
}
if (attributeFilterControl != null)
{
filterByAttributesValues(results, attributeFilterControl.getValues());
}
return results;
}
public Collection<IdentityObject> findIdentityObject(IdentityStoreInvocationContext ctx,
IdentityObject identity,
IdentityObjectRelationshipType relationshipType,
boolean parent) throws IdentityException
{
return findIdentityObject(ctx, identity, relationshipType, parent, null);
}
public IdentityObjectRelationship createRelationship(IdentityStoreInvocationContext ctx,
IdentityObject fromIdentity,
IdentityObject toIdentity,
IdentityObjectRelationshipType relationshipType,
String name, boolean createNames) throws IdentityException
{
if (relationshipType == null)
{
throw new IllegalArgumentException("RelationshipType is null");
}
HibernateIdentityObject fromIO = safeGet(ctx, fromIdentity);
HibernateIdentityObject toIO = safeGet(ctx, toIdentity);
HibernateIdentityObjectRelationshipType type = getHibernateIdentityObjectRelationshipType(ctx, relationshipType);
if (!getSupportedFeatures().isRelationshipTypeSupported(fromIO.getIdentityType(), toIO.getIdentityType(), relationshipType))
{
throw new IdentityException("Relationship not supported. RelationshipType[ " + relationshipType.getName() + " ] " +
"beetween: [ " + fromIO.getIdentityType().getName() + " ] and [ " + toIO.getIdentityType().getName() + " ]");
}
org.hibernate.Query query = getHibernateSession(ctx).createQuery(QUERY_RELATIONSHIP_BY_FROM_TO_TYPE_NAME)
.setParameter("fromIO", fromIO)
.setParameter("toIO", toIO)
.setParameter("typeName", type.getName())
.setParameter("name", name);
List results = query.list();
if (results.size() != 0)
{
throw new IdentityException("Relationship already present");
}
HibernateIdentityObjectRelationship relationship = null;
if (name != null)
{
HibernateIdentityObjectRelationshipName relationshipName =
(HibernateIdentityObjectRelationshipName)getHibernateSession(ctx).
createCriteria(HibernateIdentityObjectRelationshipName.class).add(Restrictions.eq("name", name)).
uniqueResult();
if (relationshipName == null)
{
throw new IdentityException("Relationship name not present in the store");
}
relationship = new HibernateIdentityObjectRelationship(type, fromIO, toIO, relationshipName);
}
else
{
relationship = new HibernateIdentityObjectRelationship(type, fromIO, toIO);
}
getHibernateSession(ctx).persist(relationship);
return relationship;
}
public void removeRelationship(IdentityStoreInvocationContext ctx, IdentityObject fromIdentity, IdentityObject toIdentity, IdentityObjectRelationshipType relationshipType, String name) throws IdentityException
{
if (relationshipType == null)
{
throw new IllegalArgumentException("RelationshipType is null");
}
HibernateIdentityObject fromIO = safeGet(ctx, fromIdentity);
HibernateIdentityObject toIO = safeGet(ctx, toIdentity);
HibernateIdentityObjectRelationshipType type = getHibernateIdentityObjectRelationshipType(ctx, relationshipType);
getSupportedFeatures().isRelationshipTypeSupported(fromIO.getIdentityType(), toIO.getIdentityType(), relationshipType);
org.hibernate.Query query = null;
if (name == null)
{
query = getHibernateSession(ctx).createQuery(QUERY_RELATIONSHIP_BY_FROM_TO_TYPE)
.setParameter("fromIO", fromIO)
.setParameter("toIO", toIO)
.setParameter("typeName", type.getName());
}
else
{
HibernateIdentityObjectRelationshipName relationshipName =
(HibernateIdentityObjectRelationshipName)getHibernateSession(ctx)
.createCriteria(HibernateIdentityObjectRelationshipName.class).add(Restrictions.eq("name", name))
.uniqueResult();
if (relationshipName == null)
{
throw new IdentityException("Relationship name not present in the store");
}
query = getHibernateSession(ctx).createQuery(QUERY_RELATIONSHIP_BY_FROM_TO_TYPE_NAME)
.setParameter("fromIO", fromIO)
.setParameter("toIO", toIO)
.setParameter("typeName", type.getName())
.setParameter("name", name);
}
List results = query.list();
if (results == null)
{
throw new IdentityException("Relationship already present");
}
HibernateIdentityObjectRelationship relationship = (HibernateIdentityObjectRelationship)results.iterator().next();
fromIO.getFromRelationships().remove(relationship);
toIO.getToRelationships().remove(relationship);
getHibernateSession(ctx).delete(relationship);
}
public void removeRelationships(IdentityStoreInvocationContext ctx, IdentityObject identity1, IdentityObject identity2, boolean named) throws IdentityException
{
HibernateIdentityObject hio1 = safeGet(ctx, identity1);
HibernateIdentityObject hio2 = safeGet(ctx, identity2);
org.hibernate.Query query = getHibernateSession(ctx).createQuery(QUERY_RELATIONSHIP_BY_IDENTITIES)
.setParameter("IO1", hio1)
.setParameter("IO2", hio2);
List results = query.list();
for (Iterator iterator = results.iterator(); iterator.hasNext();)
{
HibernateIdentityObjectRelationship relationship = (HibernateIdentityObjectRelationship) iterator.next();
if ((named && relationship.getName() != null) ||
(!named && relationship.getName() == null))
{
relationship.getFromIdentityObject().getFromRelationships().remove(relationship);
relationship.getToIdentityObject().getToRelationships().remove(relationship);
getHibernateSession(ctx).delete(relationship);
}
}
}
public Set<IdentityObjectRelationship> resolveRelationships(IdentityStoreInvocationContext ctx,
IdentityObject fromIdentity,
IdentityObject toIdentity,
IdentityObjectRelationshipType relationshipType) throws IdentityException
{
HibernateIdentityObject hio1 = safeGet(ctx, fromIdentity);
HibernateIdentityObject hio2 = safeGet(ctx, toIdentity);
org.hibernate.Query query = null;
if (relationshipType == null)
{
query = getHibernateSession(ctx).createQuery(QUERY_RELATIONSHIP_BY_FROM_TO);
}
else
{
query = getHibernateSession(ctx).createQuery(QUERY_RELATIONSHIP_BY_FROM_TO_TYPE)
.setParameter("typeName", relationshipType.getName());
}
query.setParameter("fromIO", hio1)
.setParameter("toIO", hio2);
List<HibernateIdentityObjectRelationship> results = query.list();
return new HashSet<IdentityObjectRelationship>(results);
}
public Set<IdentityObjectRelationship> resolveRelationships(IdentityStoreInvocationContext ctx,
IdentityObject identity,
IdentityObjectRelationshipType type,
boolean parent,
boolean named,
String name) throws IdentityException
{
HibernateIdentityObject hio = safeGet(ctx, identity);
Criteria criteria = getHibernateSession(ctx).createCriteria(HibernateIdentityObjectRelationship.class);
if (type != null)
{
HibernateIdentityObjectRelationshipType hibernateType = getHibernateIdentityObjectRelationshipType(ctx, type);
criteria.add(Restrictions.eq("type", hibernateType));
}
if (name != null)
{
criteria.add(Restrictions.eq("name.name", name));
}
else if (named)
{
criteria.add(Restrictions.isNotNull("name"));
}
else
{
criteria.add(Restrictions.isNull("name"));
}
if (parent)
{
criteria.add(Restrictions.eq("fromIdentityObject", hio));
}
else
{
criteria.add(Restrictions.eq("toIdentityObject", hio));
}
List<HibernateIdentityObjectRelationship> results = criteria.list();
return new HashSet<IdentityObjectRelationship>(results);
}
public String createRelationshipName(IdentityStoreInvocationContext ctx, String name) throws IdentityException, OperationNotSupportedException
{
if (name == null)
{
throw new IllegalArgumentException("name is null");
}
Session em = getHibernateSession(ctx);
HibernateRealm realm = getRealm(em, ctx);
try
{
HibernateIdentityObjectRelationshipName hiorn = (HibernateIdentityObjectRelationshipName)em.createCriteria(HibernateIdentityObjectRelationshipName.class)
.add(Restrictions.eq("name", name)).add(Restrictions.eq("realm", realm)).uniqueResult();
if (hiorn != null)
{
throw new IdentityException("Relationship name already exists");
}
hiorn = new HibernateIdentityObjectRelationshipName(name, realm);
getHibernateSession(ctx).persist(hiorn);
}
catch (Exception e)
{
throw new IdentityException("Cannot create new relationship name: " + name, e);
}
return name;
}
public String removeRelationshipName(IdentityStoreInvocationContext ctx, String name) throws IdentityException, OperationNotSupportedException
{
if (name == null)
{
throw new IllegalArgumentException("name is null");
}
Session em = getHibernateSession(ctx);
try
{
HibernateIdentityObjectRelationshipName hiorn = (HibernateIdentityObjectRelationshipName)em.createCriteria(HibernateIdentityObjectRelationshipName.class)
.add(Restrictions.eq("name", name)).add(Restrictions.eq("realm", getRealm(em, ctx))).uniqueResult();
if (hiorn == null)
{
throw new IdentityException("Relationship name doesn't exist");
}
getHibernateSession(ctx).delete(hiorn);
}
catch (Exception e)
{
throw new IdentityException("Cannot create new relationship name: " + name, e);
}
return name;
}
public Set<String> getRelationshipNames(IdentityStoreInvocationContext ctx, IdentityObjectSearchControl[] controls) throws IdentityException, OperationNotSupportedException
{
Set<String> names = null;
Session em = getHibernateSession(ctx);
checkControls(controls);
PageSearchControl pageSearchControl = null;
SortByNameSearchControl sortSearchControl = null;
AttributeFilterSearchControl attributeFilterControl = null;
NameFilterSearchControl nameFilterSearchControl = null;
if (controls != null)
{
for (IdentityObjectSearchControl control : controls)
{
if (control instanceof PageSearchControl)
{
pageSearchControl = (PageSearchControl)control;
}
else if (control instanceof SortByNameSearchControl)
{
sortSearchControl = (SortByNameSearchControl)control;
}
else if (control instanceof AttributeFilterSearchControl)
{
attributeFilterControl = (AttributeFilterSearchControl)control;
}
else if (control instanceof NameFilterSearchControl)
{
nameFilterSearchControl = (NameFilterSearchControl)control;
}
}
}
try
{
Query q = null;
if (sortSearchControl != null)
{
if (sortSearchControl.isAscending())
{
q = em.createQuery(HibernateIdentityObjectRelationshipName.findIdentityObjectRelationshipNamesOrderedByNameAsc);
}
else
{
q = em.createQuery(HibernateIdentityObjectRelationshipName.findIdentityObjectRelationshipNamesOrderedByNameDesc);
}
}
else
{
q = em.createQuery(HibernateIdentityObjectRelationshipName.findIdentityObjectRelationshipNames);
}
q.setParameter("realm", getRealm(em, ctx));
if (nameFilterSearchControl != null)
{
q.setParameter("nameFilter", nameFilterSearchControl.getFilter().replaceAll("\\*", "%"));
}
else
{
q.setParameter("nameFilter", "%");
}
if (pageSearchControl != null)
{
q.setFirstResult(pageSearchControl.getOffset());
if (pageSearchControl.getLimit() > 0)
{
q.setMaxResults(pageSearchControl.getLimit());
}
}
List<String> results = (List<String>)q.list();
names = new HashSet<String>(results);
}
catch (Exception e)
{
throw new IdentityException("Cannot get relationship names. ", e);
}
return names;
}
public Set<String> getRelationshipNames(IdentityStoreInvocationContext ctx) throws IdentityException, OperationNotSupportedException
{
return getRelationshipNames(ctx, new IdentityObjectSearchControl[]{});
}
public Set<String> getRelationshipNames(IdentityStoreInvocationContext ctx, IdentityObject identity, IdentityObjectSearchControl[] controls) throws IdentityException, OperationNotSupportedException
{
Set<String> names;
HibernateIdentityObject hibernateObject = safeGet(ctx, identity);
Session em = getHibernateSession(ctx);
checkControls(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;
}
}
}
try
{
Query q = null;
if (sortSearchControl != null)
{
if (sortSearchControl.isAscending())
{
q = em.createQuery(HibernateIdentityObjectRelationshipName.findIdentityObjectRelationshipNamesForIdentityObjectOrderedByNameAsc);
}
else
{
q = em.createQuery(HibernateIdentityObjectRelationshipName.findIdentityObjectRelationshipNamesForIdentityObjectOrdereByNameDesc);
}
}
else
{
q = em.createQuery(HibernateIdentityObjectRelationshipName.findIdentityObjectRelationshipNamesForIdentityObject);
}
q.setParameter("identityObject", hibernateObject);
if (pageSearchControl != null)
{
q.setFirstResult(pageSearchControl.getOffset());
if (pageSearchControl.getLimit() > 0)
{
q.setMaxResults(pageSearchControl.getLimit());
}
}
List<String> results = (List<String>)q.list();
names = new HashSet<String>(results);
}
catch (Exception e)
{
throw new IdentityException("Cannot get relationship names. ", e);
}
return names;
}
public Set<String> getRelationshipNames(IdentityStoreInvocationContext ctx, IdentityObject identity) throws IdentityException, OperationNotSupportedException
{
return getRelationshipNames(ctx, identity, null);
}
// Attribute store
public Set<String> getSupportedAttributeNames(IdentityStoreInvocationContext ctx, IdentityObjectType identityType) throws IdentityException
{
checkIOType(identityType);
if (attributeMappings.containsKey(identityType.getName()))
{
return attributeMappings.get(identityType.getName());
}
return new HashSet<String>();
}
public IdentityObjectAttribute getAttribute(IdentityStoreInvocationContext ctx, IdentityObject identity, String name) throws IdentityException
{
HibernateIdentityObject hibernateObject = safeGet(ctx, identity);
Set<HibernateIdentityObjectAttribute> storeAttributes = hibernateObject.getAttributes();
// Remap the names
for (HibernateIdentityObjectAttribute attribute : storeAttributes)
{
String mappedName = resolveAttributeNameFromStoreMapping(identity.getIdentityType(), name);
if (mappedName != null)
{
return attribute;
}
}
return null;
}
public Map<String, IdentityObjectAttribute> getAttributes(IdentityStoreInvocationContext ctx, IdentityObject identity) throws IdentityException
{
HibernateIdentityObject hibernateObject = safeGet(ctx, identity);
Set<HibernateIdentityObjectAttribute> storeAttributes = hibernateObject.getAttributes();
Map<String, IdentityObjectAttribute> result = new HashMap<String, IdentityObjectAttribute>();
// Remap the names
for (HibernateIdentityObjectAttribute attribute : storeAttributes)
{
String name = resolveAttributeNameFromStoreMapping(identity.getIdentityType(), attribute.getName());
if (name != null)
{
result.put(name, attribute);
}
}
return result;
}
public Map<String, IdentityObjectAttributeMetaData> getAttributesMetaData(IdentityStoreInvocationContext invocationContext,
IdentityObjectType identityType)
{
return attributesMetaData.get(identityType.getName());
}
public void updateAttributes(IdentityStoreInvocationContext ctx, IdentityObject identity, IdentityObjectAttribute[] attributes) throws IdentityException
{
if (attributes == null)
{
throw new IllegalArgumentException("attributes are null");
}
//TODO: check if attribute values time is same as MD type
Map<String, IdentityObjectAttribute> mappedAttributes = new HashMap<String, IdentityObjectAttribute>();
Map<String, IdentityObjectAttributeMetaData> mdMap = attributesMetaData.get(identity.getIdentityType().getName());
for (IdentityObjectAttribute attribute : attributes)
{
String name = resolveAttributeStoreMapping(identity.getIdentityType(), attribute.getName());
mappedAttributes.put(name, attribute);
if (mdMap == null || !mdMap.containsKey(attribute.getName()))
{
if (!isAllowNotDefinedAttributes)
{
throw new IdentityException("Cannot add not defined attribute. Use '" + ALLOW_NOT_DEFINED_ATTRIBUTES +
"' option if needed. Attribute name: " + attribute.getName());
}
}
IdentityObjectAttributeMetaData amd = mdMap.get(attribute.getName());
if (amd != null)
{
if (!amd.isMultivalued() && attribute.getSize() > 1)
{
throw new IdentityException("Cannot assigned multiply values to single valued attribute: " + attribute.getName());
}
if (amd.isReadonly())
{
throw new IdentityException("Cannot update readonly attribute: " + attribute.getName());
}
String type = amd.getType();
// check if all values have proper type
for (Object value : attribute.getValues())
{
if (type.equals(IdentityObjectAttributeMetaData.TEXT_TYPE) && !(value instanceof String))
{
throw new IdentityException("Cannot update text type attribute with not String type value: "
+ attribute.getName() + " / " + value);
}
if (type.equals(IdentityObjectAttributeMetaData.BINARY_TYPE) && !(value instanceof byte[]))
{
throw new IdentityException("Cannot update binary type attribute with not byte[] type value: "
+ attribute.getName() + " / " + value);
}
}
}
}
HibernateIdentityObject hibernateObject = safeGet(ctx, identity);
for (String name : mappedAttributes.keySet())
{
IdentityObjectAttribute attribute = mappedAttributes.get(name);
IdentityObjectAttributeMetaData amd = mdMap.get(attribute.getName());
// Default to text
String type = amd != null ? amd.getType() : IdentityObjectAttributeMetaData.TEXT_TYPE;
for (HibernateIdentityObjectAttribute storeAttribute : hibernateObject.getAttributes())
{
if (storeAttribute.getName().equals(name))
{
if (storeAttribute instanceof HibernateIdentityObjectTextAttribute)
{
if (!type.equals(IdentityObjectAttributeMetaData.TEXT_TYPE))
{
throw new IdentityException("Wrong attribute mapping. Attribute persisted as text is mapped with: "
+ type + ". Attribute name: " + name);
}
Set<String> v = new HashSet<String>();
for (Object value : attribute.getValues())
{
v.add(value.toString());
}
((HibernateIdentityObjectTextAttribute)storeAttribute).setValues(v);
}
else if (storeAttribute instanceof HibernateIdentityObjectBinaryAttribute)
{
if (!type.equals(IdentityObjectAttributeMetaData.BINARY_TYPE))
{
throw new IdentityException("Wrong attribute mapping. Attribute persisted as binary is mapped with: "
+ type + ". Attribute name: " + name);
}
Set<byte[]> v = new HashSet<byte[]>();
for (Object value : attribute.getValues())
{
v.add((byte[])value);
}
((HibernateIdentityObjectBinaryAttribute)storeAttribute).setValues(v);
}
else
{
throw new IdentityException("Internal identity store error");
}
break;
}
}
}
}
public void addAttributes(IdentityStoreInvocationContext ctx, IdentityObject identity, IdentityObjectAttribute[] attributes) throws IdentityException
{
if (attributes == null)
{
throw new IllegalArgumentException("attributes are null");
}
Map<String, IdentityObjectAttribute> mappedAttributes = new HashMap<String, IdentityObjectAttribute>();
Map<String, IdentityObjectAttributeMetaData> mdMap = attributesMetaData.get(identity.getIdentityType().getName());
Session hibernateSession = getHibernateSession(ctx);
for (IdentityObjectAttribute attribute : attributes)
{
String name = resolveAttributeStoreMapping(identity.getIdentityType(), attribute.getName());
mappedAttributes.put(name, attribute);
if ((mdMap == null || !mdMap.containsKey(attribute.getName())) &&
!isAllowNotDefinedAttributes)
{
throw new IdentityException("Cannot add not defined attribute. Use '" + ALLOW_NOT_DEFINED_ATTRIBUTES +
"' option if needed. Attribute name: " + attribute.getName());
}
IdentityObjectAttributeMetaData amd = mdMap.get(attribute.getName());
if (amd != null)
{
if (!amd.isMultivalued() && attribute.getSize() > 1)
{
throw new IdentityException("Cannot add multiply values to single valued attribute: " + attribute.getName());
}
if (amd.isReadonly())
{
throw new IdentityException("Cannot add readonly attribute: " + attribute.getName());
}
String type = amd.getType();
// check if all values have proper type
for (Object value : attribute.getValues())
{
if (type.equals(IdentityObjectAttributeMetaData.TEXT_TYPE) && !(value instanceof String))
{
throw new IdentityException("Cannot add text type attribute with not String type value: "
+ attribute.getName() + " / " + value);
}
if (type.equals(IdentityObjectAttributeMetaData.BINARY_TYPE) && !(value instanceof byte[]))
{
throw new IdentityException("Cannot add binary type attribute with not byte[] type value: "
+ attribute.getName() + " / " + value);
}
}
}
}
HibernateIdentityObject hibernateObject = safeGet(ctx, identity);
for (String name : mappedAttributes.keySet())
{
IdentityObjectAttribute attribute = mappedAttributes.get(name);
IdentityObjectAttributeMetaData amd = mdMap.get(attribute.getName());
// Default to text
String type = amd != null ? amd.getType() : IdentityObjectAttributeMetaData.TEXT_TYPE;
HibernateIdentityObjectAttribute hibernateAttribute = null;
for (HibernateIdentityObjectAttribute storeAttribute : hibernateObject.getAttributes())
{
if (storeAttribute.getName().equals(name))
{
hibernateAttribute = storeAttribute;
break;
}
}
if (hibernateAttribute != null)
{
if (hibernateAttribute instanceof HibernateIdentityObjectTextAttribute)
{
if (!type.equals(IdentityObjectAttributeMetaData.TEXT_TYPE))
{
throw new IdentityException("Wrong attribute mapping. Attribute persisted as text is mapped with: "
+ type + ". Attribute name: " + name);
}
Set<String> mergedValues = new HashSet<String>(hibernateAttribute.getValues());
for (Object value : attribute.getValues())
{
mergedValues.add(value.toString());
}
((HibernateIdentityObjectTextAttribute)hibernateAttribute).setValues(mergedValues);
}
else if (hibernateAttribute instanceof HibernateIdentityObjectBinaryAttribute)
{
if (!type.equals(IdentityObjectAttributeMetaData.BINARY_TYPE))
{
throw new IdentityException("Wrong attribute mapping. Attribute persisted as binary is mapped with: "
+ type + ". Attribute name: " + name);
}
Set<byte[]> mergedValues = new HashSet<byte[]>(hibernateAttribute.getValues());
for (Object value : attribute.getValues())
{
mergedValues.add((byte[])value);
}
((HibernateIdentityObjectBinaryAttribute)hibernateAttribute).setValues(mergedValues);
}
else
{
throw new IdentityException("Internal identity store error");
}
break;
}
else
{
if (type.equals(IdentityObjectAttributeMetaData.TEXT_TYPE))
{
Set<String> values = new HashSet<String>();
for (Object value: attribute.getValues())
{
values.add(value.toString());
}
hibernateAttribute = new HibernateIdentityObjectTextAttribute(hibernateObject, name, values);
}
else if (type.equals(IdentityObjectAttributeMetaData.BINARY_TYPE))
{
Set<byte[]> values = new HashSet<byte[]>();
for (Object value: attribute.getValues())
{
values.add((byte[])value);
}
hibernateAttribute = new HibernateIdentityObjectBinaryAttribute(hibernateObject, name, values);
}
hibernateObject.addAttribute(hibernateAttribute);
}
}
}
public void removeAttributes(IdentityStoreInvocationContext ctx, IdentityObject identity, String[] attributes) throws IdentityException
{
if (attributes == null)
{
throw new IllegalArgumentException("attributes are null");
}
String[] mappedAttributes = new String[attributes.length];
for (int i = 0; i < attributes.length; i++)
{
String name = resolveAttributeStoreMapping(identity.getIdentityType(), attributes[i]);
mappedAttributes[i] = name;
Map<String, IdentityObjectAttributeMetaData> mdMap = attributesMetaData.get(identity.getIdentityType().getName());
if (mdMap != null)
{
IdentityObjectAttributeMetaData amd = mdMap.get(attributes[i]);
if (amd != null && amd.isRequired())
{
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]);
}
}
}
HibernateIdentityObject hibernateObject = safeGet(ctx, identity);
for (String attr : mappedAttributes)
{
hibernateObject.removeAttribute(attr);
}
}
public boolean validateCredential(IdentityStoreInvocationContext ctx, IdentityObject identityObject, IdentityObjectCredential credential) throws IdentityException
{
if (credential == null)
{
throw new IllegalArgumentException();
}
HibernateIdentityObject hibernateObject = safeGet(ctx, identityObject);
if (supportedFeatures.isCredentialSupported(hibernateObject.getIdentityType(),credential.getType()))
{
HibernateIdentityObjectCredential hibernateCredential = hibernateObject.getCredentials().get(credential.getType().getName());
if (hibernateCredential == null)
{
return false;
}
// Handle generic impl
Object value = null;
if (credential.getEncodedValue() != null)
{
value = credential.getEncodedValue();
}
else
{
//TODO: support for empty password should be configurable
value = credential.getValue();
}
if (value instanceof String && hibernateCredential.getTextValue() != null)
{
return value.toString().equals(hibernateCredential.getTextValue());
}
else if (value instanceof byte[] && hibernateCredential.getBinaryValue() != null)
{
return Arrays.equals((byte[])value, hibernateCredential.getBinaryValue());
}
else
{
throw new IdentityException("Not supported credential value: " + value.getClass());
}
}
else
{
throw new IdentityException("CredentialType not supported for a given IdentityObjectType");
}
}
public void updateCredential(IdentityStoreInvocationContext ctx, IdentityObject identityObject, IdentityObjectCredential credential) throws IdentityException
{
if (credential == null)
{
throw new IllegalArgumentException();
}
HibernateIdentityObject hibernateObject = safeGet(ctx, identityObject);
Session em = getHibernateSession(ctx);
if (supportedFeatures.isCredentialSupported(hibernateObject.getIdentityType(),credential.getType()))
{
HibernateIdentityObjectCredentialType hibernateCredentialType = getHibernateIdentityObjectCredentialType(ctx, credential.getType());
if (hibernateCredentialType == null)
{
throw new IllegalStateException("Credential type not present in this store: " + credential.getType().getName());
}
HibernateIdentityObjectCredential hibernateCredential = new HibernateIdentityObjectCredential();
hibernateCredential.setIdentityObject(hibernateObject);
hibernateCredential.setType(hibernateCredentialType);
Object value = null;
// Handle generic impl
if (credential.getEncodedValue() != null)
{
value = credential.getEncodedValue();
}
else
{
//TODO: support for empty password should be configurable
value = credential.getValue();
}
if (value instanceof String)
{
hibernateCredential.setTextValue(value.toString());
}
else if (value instanceof byte[])
{
hibernateCredential.setBinaryValue((byte[])value);
}
else
{
throw new IdentityException("Not supported credential value: " + value.getClass());
}
em.persist(hibernateCredential);
hibernateObject.addCredential(hibernateCredential);
}
else
{
throw new IdentityException("CredentialType not supported for a given IdentityObjectType");
}
}
// Internal
public void addIdentityObjectType(IdentityStoreInvocationContext ctx, IdentityObjectType type) throws IdentityException
{
HibernateIdentityObjectType hibernateType = new HibernateIdentityObjectType(type);
getHibernateSession(ctx).persist(hibernateType);
}
public void addIdentityObjectRelationshipType(IdentityStoreInvocationContext ctx, IdentityObjectRelationshipType type) throws IdentityException
{
HibernateIdentityObjectRelationshipType hibernateType = new HibernateIdentityObjectRelationshipType(type);
getHibernateSession(ctx).persist(hibernateType);
}
protected Session getHibernateSession(IdentityStoreInvocationContext ctx) throws IdentityException
{
try
{
return ((Session)ctx.getIdentityStoreSession().getSessionContext());
}
catch (Exception e)
{
throw new IdentityException("Cannot obtain HibernateEntityManager", e);
}
}
private void checkIOInstance(IdentityObject io)
{
if (io == null)
{
throw new IllegalArgumentException("IdentityObject is null");
}
}
private HibernateIdentityObject safeGet(IdentityStoreInvocationContext ctx, IdentityObject io) throws IdentityException
{
checkIOInstance(io);
if (io instanceof HibernateIdentityObject)
{
return (HibernateIdentityObject)io;
}
return getHibernateIdentityObject(ctx, io);
}
private void checkIOType(IdentityObjectType iot) throws IdentityException
{
if (iot == null)
{
throw new IllegalArgumentException("IdentityObjectType is null");
}
if (!getSupportedFeatures().isIdentityObjectTypeSupported(iot))
{
throw new IdentityException("IdentityType not supported by this IdentityStore implementation: " + iot);
}
}
private HibernateIdentityObjectType getHibernateIdentityObjectType(IdentityStoreInvocationContext ctx, IdentityObjectType type) throws IdentityException
{
HibernateIdentityObjectType hibernateType = null;
Session em = getHibernateSession(ctx);
try
{
hibernateType = (HibernateIdentityObjectType)em.
createQuery(HibernateIdentityObjectType.findIdentityObjectTypeByName)
.setParameter("name", type.getName())
.uniqueResult() ;
}
catch (HibernateException e)
{
throw new IdentityException("IdentityObjectType[" + type.getName() + "] not present in the store.", e);
}
return hibernateType;
}
private HibernateIdentityObject getHibernateIdentityObject(IdentityStoreInvocationContext ctx, IdentityObject io) throws IdentityException
{
HibernateIdentityObject hibernateObject = null;
Session em = getHibernateSession(ctx);
try
{
hibernateObject = (HibernateIdentityObject)em.createQuery(HibernateIdentityObject.findIdentityObjectByNameAndType)
.setParameter("name", io.getName())
.setParameter("typeName", io.getIdentityType().getName())
.setParameter("realm", getRealm(em, ctx))
.uniqueResult();
}
catch (Exception e)
{
throw new IdentityException("IdentityObject[ " + io.getName() + " | " + io.getIdentityType().getName() + "] not present in the store.", e);
}
return hibernateObject;
}
private HibernateIdentityObjectRelationshipType getHibernateIdentityObjectRelationshipType(IdentityStoreInvocationContext ctx, IdentityObjectRelationshipType iot) throws IdentityException
{
HibernateIdentityObjectRelationshipType relationshipType = null;
Session em = getHibernateSession(ctx);
try
{
relationshipType = (HibernateIdentityObjectRelationshipType)em.
createQuery(HibernateIdentityObjectRelationshipType.findIdentityObjectRelationshipTypeByName)
.setParameter("name", iot.getName())
.uniqueResult();
}
catch (Exception e)
{
throw new IdentityException("IdentityObjectRelationshipType[ " + iot.getName() + "] not present in the store.");
}
return relationshipType;
}
private HibernateIdentityObjectCredentialType getHibernateIdentityObjectCredentialType(IdentityStoreInvocationContext ctx, IdentityObjectCredentialType credentialType) throws IdentityException
{
Session em = getHibernateSession(ctx);
HibernateIdentityObjectCredentialType hibernateType = null;
try
{
hibernateType = (HibernateIdentityObjectCredentialType)em.
createCriteria(HibernateIdentityObjectCredentialType.class).add(Restrictions.eq("name", credentialType.getName())).uniqueResult();
}
catch (HibernateException e)
{
throw new IdentityException("IdentityObjectCredentialType[ " + credentialType.getName() + "] not present in the store.");
}
return hibernateType;
}
public void populateObjectTypes(Session hibernateSession, String[] typeNames) throws Exception
{
hibernateSession.getTransaction().begin();
for (String typeName : typeNames)
{
//Check if present
HibernateIdentityObjectType hibernateType = (HibernateIdentityObjectType)hibernateSession.
createCriteria(HibernateIdentityObjectType.class).add(Restrictions.eq("name", typeName)).uniqueResult();
if (hibernateType == null)
{
hibernateType = new HibernateIdentityObjectType(typeName);
hibernateSession.persist(hibernateType);
}
}
hibernateSession.getTransaction().commit();
}
public void populateRelationshipTypes(Session hibernateSession, String[] typeNames) throws Exception
{
hibernateSession.getTransaction().begin();
for (String typeName : typeNames)
{
HibernateIdentityObjectRelationshipType hibernateType = (HibernateIdentityObjectRelationshipType)hibernateSession.
createCriteria(HibernateIdentityObjectRelationshipType.class).add(Restrictions.eq("name", typeName)).uniqueResult();
if (hibernateType == null)
{
hibernateType = new HibernateIdentityObjectRelationshipType(typeName);
hibernateSession.persist(hibernateType);
}
}
hibernateSession.getTransaction().commit();
}
public void populateCredentialTypes(Session hibernateSession, String[] typeNames) throws Exception
{
hibernateSession.getTransaction().begin();
for (String typeName : typeNames)
{
HibernateIdentityObjectCredentialType hibernateType = (HibernateIdentityObjectCredentialType)hibernateSession.
createCriteria(HibernateIdentityObjectCredentialType.class).add(Restrictions.eq("name", typeName)).uniqueResult();
if (hibernateType == null)
{
hibernateType = new HibernateIdentityObjectCredentialType(typeName);
hibernateSession.persist(hibernateType);
}
}
hibernateSession.getTransaction().commit();
}
public void addRealm(Session hibernateSession, String realmName) throws IdentityException
{
try
{
hibernateSession.getTransaction().begin();
HibernateRealm realm = new HibernateRealm(realmName);
hibernateSession.persist(realm);
hibernateSession.getTransaction().commit();
}
catch (Exception e)
{
throw new IdentityException("Failed to create store realm", e);
}
}
public HibernateRealm getRealm(Session hibernateSession, IdentityStoreInvocationContext ctx) throws IdentityException
{
if (ctx.getRealmId() == null)
{
throw new IllegalStateException("Realm Id not present");
}
HibernateRealm realm = null;
// If store is not realm aware return null to create/get objects accessible from other realms
if (!isRealmAware())
{
realm = (HibernateRealm)hibernateSession.
createCriteria(HibernateRealm.class).add(Restrictions.eq("name", DEFAULT_REALM_NAME)).uniqueResult();
if (realm == null)
{
throw new IllegalStateException("Default store realm is not present: " + DEFAULT_REALM_NAME);
}
}
else
{
realm = (HibernateRealm)hibernateSession.
createCriteria(HibernateRealm.class).add(Restrictions.eq("name", ctx.getRealmId())).uniqueResult();
// TODO: other way to not lazy initialize realm? special method called on every new session creation
if (realm == null)
{
HibernateRealm newRealm = new HibernateRealm(ctx.getRealmId());
hibernateSession.persist(newRealm);
return newRealm;
}
}
return realm;
}
private boolean isRealmAware()
{
return isRealmAware;
}
private boolean isAllowNotDefinedAttributes()
{
return isAllowNotDefinedAttributes;
}
private void checkControls(IdentityObjectSearchControl[] controls) throws IdentityException
{
if (controls != null)
{
for (IdentityObjectSearchControl control : controls)
{
if (!supportedIdentityObjectSearchControls.contains(control.getClass()))
{
throw new IdentityException("IdentityObjectSearchControl not supported by this IdentityStore: " + control.getClass());
}
}
}
}
/**
* Resolve store mapping for attribute name. If attribute is not mapped and store doesn't allow not defined
* attributes throw exception
* @param type
* @param name
* @return
*/
private String resolveAttributeStoreMapping(IdentityObjectType type, String name) throws IdentityException
{
String mapping = null;
if (attributesMetaData.containsKey(type.getName()))
{
IdentityObjectAttributeMetaData amd = attributesMetaData.get(type.getName()).get(name);
if (amd != null)
{
mapping = amd.getStoreMapping() != null ? amd.getStoreMapping() : amd.getName();
return mapping;
}
}
if (isAllowNotDefinedAttributes())
{
mapping = name;
return mapping;
}
throw new IdentityException("Attribute name is not configured in this store");
}
private String resolveAttributeNameFromStoreMapping(IdentityObjectType type, String mapping)
{
if (reverseAttributeMappings.containsKey(type.getName()))
{
Map<String, String> map = reverseAttributeMappings.get(type.getName());
if (map != null)
{
String name = map.containsKey(mapping) ? map.get(mapping) : mapping;
return name;
}
}
if (isAllowNotDefinedAttributes())
{
return mapping;
}
return null;
}
//TODO: this kills performance and is present here only as "quick" hack to have the feature present and let to add test cases
//TODO: needs to be redone at the hibernate query level
private void filterByAttributesValues(Collection<IdentityObject> objects, Map<String, String[]> attrs)
{
Set<IdentityObject> toRemove = new HashSet<IdentityObject>();
for (IdentityObject object : objects)
{
Map<String, Collection> presentAttrs = ((HibernateIdentityObject)object).getAttributesAsMap();
for (Map.Entry<String, String[]> entry : attrs.entrySet())
{
if (presentAttrs.containsKey(entry.getKey()))
{
Set<String> given = new HashSet<String>(Arrays.asList(entry.getValue()));
Collection present = presentAttrs.get(entry.getKey());
for (String s : given)
{
if (!present.contains(s))
{
toRemove.add(object);
break;
}
}
}
else
{
toRemove.add(object);
break;
}
}
}
for (IdentityObject identityObject : toRemove)
{
objects.remove(identityObject);
}
}
}