Java tutorial
/* * 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.picketlink.idm.impl.store.hibernate; import org.picketlink.idm.common.exception.IdentityException; import org.picketlink.idm.impl.helper.Tools; import org.picketlink.idm.impl.model.hibernate.*; import org.picketlink.idm.impl.store.FeaturesMetaDataImpl; import org.picketlink.idm.impl.types.SimpleIdentityObject; import org.picketlink.idm.spi.configuration.IdentityStoreConfigurationContext; import org.picketlink.idm.spi.configuration.metadata.IdentityObjectAttributeMetaData; import org.picketlink.idm.spi.configuration.metadata.IdentityObjectTypeMetaData; import org.picketlink.idm.spi.configuration.metadata.IdentityStoreConfigurationMetaData; import org.picketlink.idm.spi.configuration.metadata.RealmConfigurationMetaData; import org.picketlink.idm.spi.exception.OperationNotSupportedException; import org.picketlink.idm.spi.model.IdentityObject; import org.picketlink.idm.spi.model.IdentityObjectAttribute; import org.picketlink.idm.spi.model.IdentityObjectCredential; import org.picketlink.idm.spi.model.IdentityObjectCredentialType; import org.picketlink.idm.spi.model.IdentityObjectRelationship; import org.picketlink.idm.spi.model.IdentityObjectRelationshipType; import org.picketlink.idm.spi.model.IdentityObjectType; import org.picketlink.idm.spi.search.IdentityObjectSearchCriteria; import org.picketlink.idm.spi.store.FeaturesMetaData; import org.picketlink.idm.spi.store.IdentityObjectSearchCriteriaType; import org.picketlink.idm.spi.store.IdentityStore; import org.picketlink.idm.spi.store.IdentityStoreInvocationContext; import org.picketlink.idm.spi.store.IdentityStoreSession; import java.io.Serializable; 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 java.util.logging.Level; import java.util.logging.Logger; import javax.naming.InitialContext; import javax.naming.NamingException; import org.hibernate.*; import org.hibernate.cfg.Configuration; import org.hibernate.criterion.Restrictions; import org.hibernate.criterion.Order; import org.hibernate.criterion.Projections; /** * @author <a href="mailto:boleslaw.dawidowicz at redhat.com">Boleslaw Dawidowicz</a> * @version : 0.1 $ */ public class HibernateIdentityStoreImpl implements IdentityStore, Serializable { private static Logger log = Logger.getLogger(HibernateIdentityStoreImpl.class.getName()); public static final String HIBERNATE_SESSION_FACTORY_REGISTRY_NAME = "hibernateSessionFactoryRegistryName"; public static final String HIBERNATE_CONFIGURATION = "hibernateConfiguration"; public static final String ADD_HIBERNATE_MAPPINGS = "addHibernateMappings"; 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 MANAGE_TRANSACTION_DURING_BOOTSTRAP = "manageTransactionDuringBootstrap"; public static final String ALLOW_NOT_DEFINED_ATTRIBUTES = "allowNotDefinedAttributes"; public static final String ALLOW_NOT_DEFINED_IDENTITY_OBJECT_TYPES_OPTION = "allowNotDefinedIdentityObjectTypes"; public static final String ALLOW_NOT_CASE_SENSITIVE_SEARCH = "allowNotCaseSensitiveSearch"; public static final String LAZY_START_OF_HIBERNATE_TRANSACTION = "lazyStartOfHibernateTransaction"; 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; private boolean isAllowNotDefinedIdentityObjectTypes = false; private boolean isAllowNotCaseSensitiveSearch = false; private boolean lazyStartOfHibernateTransaction = false; private boolean isManageTransactionDuringBootstrap = true; // TODO: rewrite this into some more handy object private IdentityStoreConfigurationMetaData configurationMD; private static Set<IdentityObjectSearchCriteriaType> supportedIdentityObjectSearchCriteria = new HashSet<IdentityObjectSearchCriteriaType>(); 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>>(); private static final long serialVersionUID = -130355852189832805L; static { // List all supported criteria classes supportedIdentityObjectSearchCriteria.add(IdentityObjectSearchCriteriaType.ATTRIBUTE_FILTER); supportedIdentityObjectSearchCriteria.add(IdentityObjectSearchCriteriaType.NAME_FILTER); supportedIdentityObjectSearchCriteria.add(IdentityObjectSearchCriteriaType.PAGE); supportedIdentityObjectSearchCriteria.add(IdentityObjectSearchCriteriaType.SORT); // 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, supportedIdentityObjectSearchCriteria, true, true, new HashSet<String>()); String populateMembershipTypes = configurationMD.getOptionSingleValue(POPULATE_MEMBERSHIP_TYPES); String populateIdentityObjectTypes = configurationMD.getOptionSingleValue(POPULATE_IDENTITY_OBJECT_TYPES); String manageTransactionDuringBootstrap = configurationMD .getOptionSingleValue(MANAGE_TRANSACTION_DURING_BOOTSTRAP); if (manageTransactionDuringBootstrap != null && manageTransactionDuringBootstrap.equalsIgnoreCase("false")) { this.isAllowNotDefinedAttributes = false; } 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 (isManageTransactionDuringBootstrap()) { hibernateSession.getTransaction().begin(); } 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) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", 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) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", 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) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", 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; } String allowNotDefinedIOT = configurationMD .getOptionSingleValue(ALLOW_NOT_DEFINED_IDENTITY_OBJECT_TYPES_OPTION); if (allowNotDefinedIOT != null && allowNotDefinedIOT.equalsIgnoreCase("true")) { this.isAllowNotDefinedIdentityObjectTypes = true; } String allowNotCaseSensitiveSearch = configurationMD.getOptionSingleValue(ALLOW_NOT_CASE_SENSITIVE_SEARCH); if (allowNotCaseSensitiveSearch != null && allowNotCaseSensitiveSearch.equalsIgnoreCase("true")) { this.isAllowNotCaseSensitiveSearch = true; } String lazyStartOfHibernateTransaction = configurationMD .getOptionSingleValue(LAZY_START_OF_HIBERNATE_TRANSACTION); if (lazyStartOfHibernateTransaction != null && lazyStartOfHibernateTransaction.equalsIgnoreCase("true")) { this.lazyStartOfHibernateTransaction = true; } // Default realm HibernateRealm realm = null; try { realm = (HibernateRealm) hibernateSession.createCriteria(HibernateRealm.class) .add(Restrictions.eq("name", DEFAULT_REALM_NAME)).uniqueResult(); } catch (HibernateException e) { // Realm does not exist } if (realm == null) { addRealm(hibernateSession, DEFAULT_REALM_NAME); } // If store is realm aware than creat all configured realms if (isRealmAware()) { Set<String> realmNames = new HashSet<String>(); for (RealmConfigurationMetaData realmMD : configurationContext.getConfigurationMetaData().getRealms()) { realmNames.add(realmMD.getId()); } for (String rid : realmNames) { realm = (HibernateRealm) hibernateSession.createCriteria(HibernateRealm.class) .add(Restrictions.eq("name", rid)).setCacheable(true).uniqueResult(); if (realm == null) { addRealm(hibernateSession, rid); } } } if (isManageTransactionDuringBootstrap()) { hibernateSession.getTransaction().commit(); } 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_HIBERNATE_MAPPINGS); String hibernateConfiguration = configurationContext.getStoreConfigurationMetaData() .getOptionSingleValue(HIBERNATE_CONFIGURATION); if (sfJNDIName != null) { try { return (SessionFactory) new InitialContext().lookup(sfJNDIName); } catch (NamingException e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", 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 { Configuration config = new Configuration().configure(hibernateConfiguration); if (addMappedClasses != null && addMappedClasses.equals("false")) { return config.buildSessionFactory(); } else { return config.addResource("mappings/HibernateIdentityObject.hbm.xml") .addResource("mappings/HibernateIdentityObjectCredentialBinaryValue.hbm.xml") .addResource("mappings/HibernateIdentityObjectAttributeBinaryValue.hbm.xml") .addResource("mappings/HibernateIdentityObjectAttribute.hbm.xml") .addResource("mappings/HibernateIdentityObjectCredential.hbm.xml") .addResource("mappings/HibernateIdentityObjectCredentialType.hbm.xml") .addResource("mappings/HibernateIdentityObjectRelationship.hbm.xml") .addResource("mappings/HibernateIdentityObjectRelationshipName.hbm.xml") .addResource("mappings/HibernateIdentityObjectRelationshipType.hbm.xml") .addResource("mappings/HibernateIdentityObjectType.hbm.xml") .addResource("mappings/HibernateRealm.hbm.xml").buildSessionFactory(); } } catch (Exception e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", 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, lazyStartOfHibernateTransaction); } catch (Exception e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", e); } throw new IdentityException("Failed to obtain Hibernate SessionFactory", e); } } public IdentityStoreSession createIdentityStoreSession(Map<String, Object> sessionOptions) throws IdentityException { return createIdentityStoreSession(); } 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); Number boxedSize = (Number) session.createCriteria(HibernateIdentityObject.class) .createAlias("identityType", "type").createAlias("realm", "rm").add(Restrictions.eq("name", name)) .add(Restrictions.eq("rm.name", realm.getName())) .add(Restrictions.eq("type.name", identityObjectType.getName())) .setProjection(Projections.rowCount()).setCacheable(true).list().get(0); int size = boxedSize.intValue(); if (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) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", 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 HibernateIdentityObjectRelationship[] from = new HibernateIdentityObjectRelationship[hibernateObject .getFromRelationships().size()]; for (HibernateIdentityObjectRelationship relationship : hibernateObject.getFromRelationships() .toArray(from)) { relationship.getFromIdentityObject().getFromRelationships().remove(relationship); relationship.getToIdentityObject().getToRelationships().remove(relationship); hibernateSession.delete(relationship); hibernateSession.flush(); } HibernateIdentityObjectRelationship[] to = new HibernateIdentityObjectRelationship[hibernateObject .getToRelationships().size()]; for (HibernateIdentityObjectRelationship relationship : hibernateObject.getToRelationships() .toArray(to)) { relationship.getFromIdentityObject().getFromRelationships().remove(relationship); relationship.getToIdentityObject().getToRelationships().remove(relationship); hibernateSession.delete(relationship); hibernateSession.flush(); } hibernateSession.delete(hibernateObject); hibernateSession.flush(); } catch (Exception e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", 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("realmName", getRealmName(ctx)) .setCacheable(true).uniqueResult()).intValue(); } catch (Exception e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", 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); HibernateIdentityObject hibernateObject = safeGet(ctx, new SimpleIdentityObject(name, type)); // Check result with case sensitive compare: if (isAllowNotCaseSensitiveSearch()) { return hibernateObject; } else if (hibernateObject != null && hibernateObject.getName().equals(name)) { return hibernateObject; } return null; } 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) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", e); } throw new IdentityException("Cannot find IdentityObject with id: " + id, e); } return hibernateObject; } @SuppressWarnings("unchecked") public Collection<IdentityObject> findIdentityObject(IdentityStoreInvocationContext ctx, IdentityObjectType identityType, IdentityObjectSearchCriteria criteria) throws IdentityException { checkIOType(identityType); HibernateIdentityObjectType hibernateType = getHibernateIdentityObjectType(ctx, identityType); HibernateRealm realm = getRealm(getHibernateSession(ctx), ctx); List<IdentityObject> results; Session hibernateSession = getHibernateSession(ctx); try { Criteria hc = hibernateSession.createCriteria(HibernateIdentityObject.class).setCacheable(true) .add(Restrictions.eq("realm", realm)).add(Restrictions.eq("identityType", hibernateType)); if (criteria != null && criteria.isSorted()) { if (criteria.isAscending()) { hc.addOrder(Order.asc("name")); } else { hc.addOrder(Order.desc("name")); } } if (criteria != null && criteria.isPaged() && !criteria.isFiltered()) { if (criteria.getMaxResults() > 0) { hc.setMaxResults(criteria.getMaxResults()); } hc.setFirstResult(criteria.getFirstResult()); } if (criteria != null && criteria.getFilter() != null) { hc.add(Restrictions.like("name", criteria.getFilter().replaceAll("\\*", "%"))); } else { hc.add(Restrictions.like("name", "%")); } results = (List<IdentityObject>) hc.list(); Hibernate.initialize(results); } catch (Exception e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", e); } throw new IdentityException("Cannot find IdentityObjects with type '" + identityType.getName() + "'", e); } if (criteria != null && criteria.isFiltered()) { filterByAttributesValues(results, criteria.getValues()); if (criteria.isPaged()) { results = (LinkedList) cutPageFromResults(results, criteria); } } return results; } public Collection<IdentityObject> findIdentityObject(IdentityStoreInvocationContext ctx, IdentityObjectType identityType) throws IdentityException { return findIdentityObject(ctx, identityType, null); } public int getIdentityObjectCount(IdentityStoreInvocationContext invocationCxt, IdentityObject identity, IdentityObjectRelationshipType relationshipType, boolean parent, IdentityObjectSearchCriteria criteria) throws IdentityException { return getIdentityObjectCount(invocationCxt, identity, relationshipType, null, parent, criteria); } @SuppressWarnings("unchecked") public Collection<IdentityObject> findIdentityObject(IdentityStoreInvocationContext invocationCxt, IdentityObject identity, IdentityObjectRelationshipType relationshipType, boolean parent, IdentityObjectSearchCriteria criteria) throws IdentityException { return findIdentityObject(invocationCxt, identity, relationshipType, null, parent, criteria); } public int getIdentityObjectCount(IdentityStoreInvocationContext ctx, IdentityObject identity, IdentityObjectRelationshipType relationshipType, Collection<IdentityObjectType> excludes, boolean parent, IdentityObjectSearchCriteria criteria) throws IdentityException { int result; try { org.hibernate.Query q = prepareIdentityObjectQuery(ctx, identity, relationshipType, excludes, parent, criteria, false); result = ((Integer) q.iterate().next()).intValue(); } catch (Exception e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", e); } throw new IdentityException("Cannot get IdentityObject count", e); } return result; } @SuppressWarnings("unchecked") public Collection<IdentityObject> findIdentityObject(IdentityStoreInvocationContext ctx, IdentityObject identity, IdentityObjectRelationshipType relationshipType, Collection<IdentityObjectType> excludes, boolean parent, IdentityObjectSearchCriteria criteria) throws IdentityException { List<IdentityObject> results; try { org.hibernate.Query q = prepareIdentityObjectQuery(ctx, identity, relationshipType, excludes, parent, criteria, false); results = q.list(); Hibernate.initialize(results); } catch (Exception e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", e); } throw new IdentityException("Cannot find IdentityObjects", e); } if (criteria != null && criteria.isFiltered()) { filterByAttributesValues(results, criteria.getValues()); if (criteria.isPaged()) { results = (LinkedList) cutPageFromResults(results, criteria); } } return results; } @SuppressWarnings("unchecked") public org.hibernate.Query prepareIdentityObjectQuery(IdentityStoreInvocationContext ctx, IdentityObject identity, IdentityObjectRelationshipType relationshipType, Collection<IdentityObjectType> excludes, boolean parent, IdentityObjectSearchCriteria criteria, boolean count) throws IdentityException { //TODO:test HibernateIdentityObject hibernateObject = safeGet(ctx, identity); HibernateRealm realm = getRealm(getHibernateSession(ctx), ctx); boolean orderByName = false; boolean ascending = true; if (criteria != null && criteria.isSorted()) { orderByName = true; ascending = criteria.isAscending(); } org.hibernate.Query q = null; try { StringBuilder hqlString = new StringBuilder(""); if (parent) { if (count) { hqlString.append( "select count(distinct ior.toIdentityObject) from HibernateIdentityObjectRelationship ior where "); } else { hqlString.append( "select distinct ior.toIdentityObject from HibernateIdentityObjectRelationship ior where "); } hqlString.append( "ior.toIdentityObject.realm = :realm and ior.fromIdentityObject.realm = :realm and "); if (relationshipType != null) { hqlString.append( "ior.toIdentityObject.name like :nameFilter and ior.type.name = :relType and ior.fromIdentityObject = :identity"); } else { hqlString.append( "ior.toIdentityObject.name like :nameFilter and ior.fromIdentityObject = :identity"); } if (excludes != null && excludes.size() > 0) { int i = 0; for (IdentityObjectType exclude : excludes) { hqlString.append(" and ior.toIdentityObject.identityType.id <> ").append(":exclude" + i++); } } if (orderByName) { hqlString.append(" order by ior.toIdentityObject.name"); if (ascending) { hqlString.append(" asc"); } } } else { if (count) { hqlString.append( "select count(distinct ior.fromIdentityObject) from HibernateIdentityObjectRelationship ior where "); } else { hqlString.append( "select distinct ior.fromIdentityObject from HibernateIdentityObjectRelationship ior where "); } hqlString.append( "ior.toIdentityObject.realm = :realm and ior.fromIdentityObject.realm = :realm and "); if (relationshipType != null) { hqlString.append( "ior.fromIdentityObject.name like :nameFilter and ior.type.name = :relType and ior.toIdentityObject = :identity"); } else { hqlString.append( "ior.fromIdentityObject.name like :nameFilter and ior.toIdentityObject = :identity"); } if (excludes != null && excludes.size() > 0) { int i = 0; for (IdentityObjectType exclude : excludes) { hqlString.append(" and ior.fromIdentityObject.identityType.id <> ") .append(":exclude" + i++); } } if (orderByName) { hqlString.append(" order by ior.fromIdentityObject.name"); if (ascending) { hqlString.append(" asc"); } } } q = getHibernateSession(ctx).createQuery(hqlString.toString()).setParameter("identity", hibernateObject) .setParameter("realm", realm).setCacheable(true); if (relationshipType != null) { q.setParameter("relType", relationshipType.getName()); } if (criteria != null && criteria.getFilter() != null) { q.setParameter("nameFilter", criteria.getFilter().replaceAll("\\*", "%")); } else { q.setParameter("nameFilter", "%"); } if (excludes != null && excludes.size() > 0) { int i = 0; for (IdentityObjectType exclude : excludes) { HibernateIdentityObjectType exType = getHibernateIdentityObjectType(ctx, exclude); q.setParameter("exclude" + i++, exType.getId()); } } if (criteria != null && criteria.isPaged() && !criteria.isFiltered()) { q.setFirstResult(criteria.getFirstResult()); if (criteria.getMaxResults() > 0) { q.setMaxResults(criteria.getMaxResults()); } } q.setCacheable(true); } catch (Exception e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", e); } throw new IdentityException("Cannot prepare hibernate query", e); } return q; } 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); HibernateRealm realm = getRealm(getHibernateSession(ctx), ctx); if (!getSupportedFeatures().isRelationshipTypeSupported(fromIO.getIdentityType(), toIO.getIdentityType(), relationshipType)) { if (!isAllowNotDefinedIdentityObjectTypes()) { throw new IdentityException("Relationship not supported. RelationshipType[ " + relationshipType.getName() + " ] " + "beetween: [ " + fromIO.getIdentityType().getName() + " ] and [ " + toIO.getIdentityType().getName() + " ]"); } } HibernateIdentityObjectRelationship relationship = null; HibernateRealm hibernateRealm = getRealm(getHibernateSession(ctx), ctx); if (name != null) { HibernateIdentityObjectRelationshipName relationshipName = (HibernateIdentityObjectRelationshipName) getHibernateSession( ctx).createCriteria(HibernateIdentityObjectRelationshipName.class).setCacheable(true) .add(Restrictions.eq("name", name)).add(Restrictions.eq("realm", hibernateRealm)) .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); } try { Session session = getHibernateSession(ctx); session.persist(relationship); session.flush(); } catch (HibernateException e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", e); } throw new IdentityException("Cannot create relationship: ", e); } 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); HibernateRealm realm = getRealm(getHibernateSession(ctx), ctx); org.hibernate.Query query = null; Criteria crit = null; if (name == null) { crit = getHibernateSession(ctx).createCriteria(HibernateIdentityObjectRelationship.class) .createAlias("type", "t").add(Restrictions.eq("fromIdentityObject", fromIO)) .add(Restrictions.eq("toIdentityObject", toIO)).add(Restrictions.eq("t.name", type.getName())) .setCacheable(true); } else { HibernateIdentityObjectRelationshipName relationshipName = (HibernateIdentityObjectRelationshipName) getHibernateSession( ctx).createCriteria(HibernateIdentityObjectRelationshipName.class) .add(Restrictions.eq("name", name)).createAlias("realm", "rm") .add(Restrictions.eq("rm.name", getRealmName(ctx))).uniqueResult(); if (relationshipName == null) { throw new IdentityException("Relationship name not present in the store"); } crit = getHibernateSession(ctx).createCriteria(HibernateIdentityObjectRelationship.class) .createAlias("type", "t").createAlias("name", "n") .add(Restrictions.eq("fromIdentityObject", fromIO)) .add(Restrictions.eq("toIdentityObject", toIO)).add(Restrictions.eq("t.name", type.getName())) .add(Restrictions.eq("n.name", name)).setCacheable(true); } HibernateIdentityObjectRelationship relationship = (HibernateIdentityObjectRelationship) crit .uniqueResult(); if (relationship == null) { throw new IdentityException("Relationship not present in the store"); } try { fromIO.getFromRelationships().remove(relationship); toIO.getToRelationships().remove(relationship); getHibernateSession(ctx).delete(relationship); getHibernateSession(ctx).flush(); } catch (HibernateException e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", e); } throw new IdentityException("Cannot remove relationship"); } } public void removeRelationships(IdentityStoreInvocationContext ctx, IdentityObject identity1, IdentityObject identity2, boolean named) throws IdentityException { HibernateIdentityObject hio1 = safeGet(ctx, identity1); HibernateIdentityObject hio2 = safeGet(ctx, identity2); Criteria criteria = getHibernateSession(ctx).createCriteria(HibernateIdentityObjectRelationship.class) .setCacheable(true) .add(Restrictions.or( Restrictions.and(Restrictions.eq("fromIdentityObject", hio1), Restrictions.eq("toIdentityObject", hio2)), Restrictions.and(Restrictions.eq("fromIdentityObject", hio2), Restrictions.eq("toIdentityObject", hio1)))); List results = criteria.list(); Hibernate.initialize(results); for (Iterator iterator = results.iterator(); iterator.hasNext();) { HibernateIdentityObjectRelationship relationship = (HibernateIdentityObjectRelationship) iterator .next(); if ((named && relationship.getName() != null) || (!named && relationship.getName() == null)) { try { relationship.getFromIdentityObject().getFromRelationships().remove(relationship); relationship.getToIdentityObject().getToRelationships().remove(relationship); getHibernateSession(ctx).delete(relationship); getHibernateSession(ctx).flush(); } catch (HibernateException e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", e); } throw new IdentityException("Cannot remove 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); Criteria criteria = getHibernateSession(ctx).createCriteria(HibernateIdentityObjectRelationship.class) .setCacheable(true); if (relationshipType != null) { criteria.createAlias("type", "t").add(Restrictions.eq("t.name", relationshipType.getName())); } criteria.add(Restrictions.eq("fromIdentityObject", hio1)).add(Restrictions.eq("toIdentityObject", hio2)); List<HibernateIdentityObjectRelationship> results = criteria.list(); Hibernate.initialize(results); return new HashSet<IdentityObjectRelationship>(results); } public int getRelationshipsCount(IdentityStoreInvocationContext ctx, IdentityObject identity, IdentityObjectRelationshipType type, boolean parent, boolean named, String name, IdentityObjectSearchCriteria searchCriteria) throws IdentityException { Criteria criteria = prepareResolveRelationshipsCriteria(ctx, identity, type, parent, named, name, searchCriteria); criteria.setProjection(Projections.rowCount()); Iterator result = criteria.list().iterator(); if (!result.hasNext()) { return 0; } return (Integer) result.next(); } public Set<IdentityObjectRelationship> resolveRelationships(IdentityStoreInvocationContext ctx, IdentityObject identity, IdentityObjectRelationshipType type, boolean parent, boolean named, String name, IdentityObjectSearchCriteria searchCriteria) throws IdentityException { HibernateIdentityObject hio = safeGet(ctx, identity); Criteria criteria = prepareResolveRelationshipsCriteria(ctx, identity, type, parent, named, name, searchCriteria); List<HibernateIdentityObjectRelationship> results = criteria.list(); Hibernate.initialize(results); return new HashSet<IdentityObjectRelationship>(results); } public Criteria prepareResolveRelationshipsCriteria(IdentityStoreInvocationContext ctx, IdentityObject identity, IdentityObjectRelationshipType type, boolean parent, boolean named, String name, IdentityObjectSearchCriteria searchCriteria) throws IdentityException { HibernateIdentityObject hio = safeGet(ctx, identity); Criteria criteria = getHibernateSession(ctx).createCriteria(HibernateIdentityObjectRelationship.class); criteria.setCacheable(true); 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)); } criteria.setFetchMode("fromIdentityObject", FetchMode.JOIN); criteria.setFetchMode("toIdentityObject", FetchMode.JOIN); if (searchCriteria != null && searchCriteria.isPaged() && !searchCriteria.isFiltered()) { if (searchCriteria.getMaxResults() > 0) { criteria.setMaxResults(searchCriteria.getMaxResults()); } criteria.setFirstResult(searchCriteria.getFirstResult()); } if (searchCriteria != null && searchCriteria.isSorted()) { if (parent) { criteria.createAlias("toIdentityObject", "io"); if (searchCriteria.isAscending()) { criteria.addOrder(Order.asc("io.name")); } else { criteria.addOrder(Order.desc("io.name")); } } else { criteria.createAlias("fromIdentityObject", "io"); if (searchCriteria.isAscending()) { criteria.addOrder(Order.asc("io.name")); } else { criteria.addOrder(Order.desc("io.name")); } } } return criteria; } public String createRelationshipName(IdentityStoreInvocationContext ctx, String name) throws IdentityException, OperationNotSupportedException { if (name == null) { throw new IllegalArgumentException("name is null"); } Session hibernateSession = getHibernateSession(ctx); HibernateRealm realm = getRealm(hibernateSession, ctx); try { HibernateIdentityObjectRelationshipName hiorn = (HibernateIdentityObjectRelationshipName) hibernateSession .createQuery(HibernateIdentityObjectRelationshipName.findIdentityObjectRelationshipNameByName) .setParameter("name", name).setParameter("realmName", realm.getName()).uniqueResult(); if (hiorn != null) { throw new IdentityException("Relationship name already exists"); } hiorn = new HibernateIdentityObjectRelationshipName(name, realm); getHibernateSession(ctx).persist(hiorn); getHibernateSession(ctx).flush(); } catch (Exception e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", 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 hibernateSession = getHibernateSession(ctx); try { HibernateIdentityObjectRelationshipName hiorn = (HibernateIdentityObjectRelationshipName) hibernateSession .createCriteria(HibernateIdentityObjectRelationshipName.class).createAlias("realm", "rm") .add(Restrictions.eq("name", name)).add(Restrictions.eq("rm.name", getRealmName(ctx))) .setCacheable(true).uniqueResult(); if (hiorn == null) { throw new IdentityException("Relationship name doesn't exist"); } List<HibernateIdentityObjectRelationship> rels = (List<HibernateIdentityObjectRelationship>) hibernateSession .createCriteria(HibernateIdentityObjectRelationship.class).add(Restrictions.eq("name", hiorn)) .setCacheable(true).list(); Hibernate.initialize(rels); //Remove all present usages for (HibernateIdentityObjectRelationship rel : rels) { getHibernateSession(ctx).delete(rel); } getHibernateSession(ctx).delete(hiorn); getHibernateSession(ctx).flush(); } catch (Exception e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", e); } throw new IdentityException("Cannot remove new relationship name: " + name, e); } return name; } public Set<String> getRelationshipNames(IdentityStoreInvocationContext ctx, IdentityObjectSearchCriteria criteria) throws IdentityException, OperationNotSupportedException { Set<String> names = null; Session hibernateSession = getHibernateSession(ctx); try { //Query q = null; Criteria c = hibernateSession.createCriteria(HibernateIdentityObjectRelationshipName.class) .setCacheable(true).createAlias("realm", "r").setProjection(Projections.property("name")); if (criteria != null && criteria.isSorted()) { if (criteria.isAscending()) { c.addOrder(Order.asc("name")); } else { c.addOrder(Order.desc("name")); } } c.add(Restrictions.eq("r.name", getRealmName(ctx))); if (criteria != null && criteria.getFilter() != null) { c.add(Restrictions.like("name", criteria.getFilter().replaceAll("\\*", "%"))); } else { c.add(Restrictions.like("name", "%")); } if (criteria != null && criteria.isPaged()) { c.setFirstResult(criteria.getFirstResult()); if (criteria.getMaxResults() > 0) { c.setMaxResults(criteria.getMaxResults()); } } List<String> results = (List<String>) c.list(); Hibernate.initialize(results); names = new HashSet<String>(results); } catch (Exception e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", e); } throw new IdentityException("Cannot get relationship names. ", e); } return names; } public Set<String> getRelationshipNames(IdentityStoreInvocationContext ctx) throws IdentityException, OperationNotSupportedException { return getRelationshipNames(ctx, (IdentityObjectSearchCriteria) null); } public Set<String> getRelationshipNames(IdentityStoreInvocationContext ctx, IdentityObject identity, IdentityObjectSearchCriteria criteria) throws IdentityException, OperationNotSupportedException { Set<String> names; HibernateIdentityObject hibernateObject = safeGet(ctx, identity); Session hibernateSession = getHibernateSession(ctx); try { Criteria c = hibernateSession.createCriteria(HibernateIdentityObjectRelationship.class) .setCacheable(true).createAlias("name", "n").setProjection(Projections.property("n.name")); if (criteria != null) { if (criteria.isAscending()) { c.addOrder(Order.asc("n.name")); } else { c.addOrder(Order.desc("n.name")); } } c.add(Restrictions.or(Restrictions.eq("fromIdentityObject", hibernateObject), Restrictions.eq("toIdentityObject", hibernateObject))); if (criteria != null && criteria.isPaged()) { c.setFirstResult(criteria.getFirstResult()); if (criteria.getMaxResults() > 0) { c.setMaxResults(criteria.getMaxResults()); } } List<String> results = (List<String>) c.list(); Hibernate.initialize(results); names = new HashSet<String>(results); } catch (Exception e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", 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); } public Map<String, String> getRelationshipNameProperties(IdentityStoreInvocationContext ctx, String name) throws IdentityException, OperationNotSupportedException { if (name == null) { throw new IllegalArgumentException("name is null"); } Session hibernateSession = getHibernateSession(ctx); try { HibernateIdentityObjectRelationshipName hiorn = (HibernateIdentityObjectRelationshipName) hibernateSession .createCriteria(HibernateIdentityObjectRelationshipName.class).setCacheable(true) .createAlias("realm", "r").add(Restrictions.eq("name", name)) .add(Restrictions.eq("r.name", getRealmName(ctx))).uniqueResult(); if (hiorn == null) { throw new IdentityException("Relationship name doesn't exist"); } Hibernate.initialize(hiorn.getProperties()); return new HashMap<String, String>(hiorn.getProperties()); } catch (Exception e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", e); } throw new IdentityException("Cannot get relationship name properties: " + name, e); } } public void setRelationshipNameProperties(IdentityStoreInvocationContext ctx, String name, Map<String, String> properties) throws IdentityException, OperationNotSupportedException { if (name == null) { throw new IllegalArgumentException("name is null"); } Session hibernateSession = getHibernateSession(ctx); try { HibernateIdentityObjectRelationshipName hiorn = (HibernateIdentityObjectRelationshipName) hibernateSession .createCriteria(HibernateIdentityObjectRelationshipName.class).setCacheable(true) .createAlias("realm", "r").add(Restrictions.eq("name", name)) .add(Restrictions.eq("r.name", getRealmName(ctx))).uniqueResult(); if (hiorn == null) { throw new IdentityException("Relationship name doesn't exist"); } hiorn.getProperties().putAll(properties); } catch (Exception e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", e); } throw new IdentityException("Cannot set relationship name properties: " + name, e); } } public void removeRelationshipNameProperties(IdentityStoreInvocationContext ctx, String name, Set<String> properties) throws IdentityException, OperationNotSupportedException { if (name == null) { throw new IllegalArgumentException("name is null"); } Session hibernateSession = getHibernateSession(ctx); try { HibernateIdentityObjectRelationshipName hiorn = (HibernateIdentityObjectRelationshipName) hibernateSession .createCriteria(HibernateIdentityObjectRelationshipName.class).setCacheable(true) .createAlias("realm", "r").add(Restrictions.eq("name", name)) .add(Restrictions.eq("r.name", getRealmName(ctx))).uniqueResult(); if (hiorn == null) { throw new IdentityException("Relationship name doesn't exist"); } Hibernate.initialize(hiorn.getProperties()); for (String property : properties) { hiorn.getProperties().remove(property); } } catch (Exception e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", e); } throw new IdentityException("Cannot remove relationship name properties: " + name, e); } } public Map<String, String> getRelationshipProperties(IdentityStoreInvocationContext ctx, IdentityObjectRelationship relationship) throws IdentityException, OperationNotSupportedException { HibernateIdentityObject fromIO = safeGet(ctx, relationship.getFromIdentityObject()); HibernateIdentityObject toIO = safeGet(ctx, relationship.getToIdentityObject()); HibernateIdentityObjectRelationshipType type = getHibernateIdentityObjectRelationshipType(ctx, relationship.getType()); Criteria criteria = getHibernateSession(ctx).createCriteria(HibernateIdentityObjectRelationship.class) .setCacheable(true).createAlias("type", "t").add(Restrictions.eq("t.name", type.getName())) .add(Restrictions.eq("fromIdentityObject", fromIO)).add(Restrictions.eq("toIdentityObject", toIO)); if (relationship.getName() != null) { HibernateIdentityObjectRelationshipName relationshipName = (HibernateIdentityObjectRelationshipName) getHibernateSession( ctx).createCriteria(HibernateIdentityObjectRelationshipName.class) .add(Restrictions.eq("name", relationship.getName())).setCacheable(true).uniqueResult(); if (relationshipName == null) { throw new IdentityException("Relationship name not present in the store"); } criteria.createAlias("name", "n").add(Restrictions.eq("n.name", relationship.getName())); } try { HibernateIdentityObjectRelationship hibernateRelationship = (HibernateIdentityObjectRelationship) criteria .uniqueResult(); Hibernate.initialize(hibernateRelationship.getProperties()); return new HashMap<String, String>(hibernateRelationship.getProperties()); } catch (HibernateException e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", e); } throw new IdentityException("Cannot obtain relationship properties: ", e); } } public void setRelationshipProperties(IdentityStoreInvocationContext ctx, IdentityObjectRelationship relationship, Map<String, String> properties) throws IdentityException, OperationNotSupportedException { HibernateIdentityObject fromIO = safeGet(ctx, relationship.getFromIdentityObject()); HibernateIdentityObject toIO = safeGet(ctx, relationship.getToIdentityObject()); HibernateIdentityObjectRelationshipType type = getHibernateIdentityObjectRelationshipType(ctx, relationship.getType()); Criteria criteria = getHibernateSession(ctx).createCriteria(HibernateIdentityObjectRelationship.class) .setCacheable(true).createAlias("type", "t").add(Restrictions.eq("t.name", type.getName())) .add(Restrictions.eq("fromIdentityObject", fromIO)).add(Restrictions.eq("toIdentityObject", toIO)); if (relationship.getName() != null) { HibernateIdentityObjectRelationshipName relationshipName = (HibernateIdentityObjectRelationshipName) getHibernateSession( ctx).createCriteria(HibernateIdentityObjectRelationshipName.class) .add(Restrictions.eq("name", relationship.getName())).setCacheable(true).uniqueResult(); if (relationshipName == null) { throw new IdentityException("Relationship name not present in the store"); } criteria.createAlias("name", "n").add(Restrictions.eq("n.name", relationship.getName())); } try { HibernateIdentityObjectRelationship hibernateRelationship = (HibernateIdentityObjectRelationship) criteria .uniqueResult(); hibernateRelationship.getProperties().putAll(properties); } catch (HibernateException e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", e); } throw new IdentityException("Cannot update relationship properties: ", e); } } public void removeRelationshipProperties(IdentityStoreInvocationContext ctx, IdentityObjectRelationship relationship, Set<String> properties) throws IdentityException, OperationNotSupportedException { HibernateIdentityObject fromIO = safeGet(ctx, relationship.getFromIdentityObject()); HibernateIdentityObject toIO = safeGet(ctx, relationship.getToIdentityObject()); HibernateIdentityObjectRelationshipType type = getHibernateIdentityObjectRelationshipType(ctx, relationship.getType()); Criteria criteria = getHibernateSession(ctx).createCriteria(HibernateIdentityObjectRelationship.class) .setCacheable(true).createAlias("type", "t").add(Restrictions.eq("t.name", type.getName())) .add(Restrictions.eq("fromIdentityObject", fromIO)).add(Restrictions.eq("toIdentityObject", toIO)); if (relationship.getName() == null) { HibernateIdentityObjectRelationshipName relationshipName = (HibernateIdentityObjectRelationshipName) getHibernateSession( ctx).createCriteria(HibernateIdentityObjectRelationshipName.class) .add(Restrictions.eq("name", relationship.getName())).setCacheable(true).uniqueResult(); if (relationshipName == null) { throw new IdentityException("Relationship name not present in the store"); } criteria.createAlias("name", "n").add(Restrictions.eq("n.name", relationship.getName())); } try { HibernateIdentityObjectRelationship hibernateRelationship = (HibernateIdentityObjectRelationship) criteria .uniqueResult(); Hibernate.initialize(hibernateRelationship.getProperties()); for (String property : properties) { hibernateRelationship.getProperties().remove(property); } } catch (HibernateException e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", e); } throw new IdentityException("Cannot update relationship properties: ", e); } } // 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(); Hibernate.initialize(storeAttributes); // 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 { HibernateRealm realm = getRealm(getHibernateSession(ctx), ctx); HibernateIdentityObjectType hibernateType = getHibernateIdentityObjectType(ctx, identity.getIdentityType()); Map<String, IdentityObjectAttribute> result = new HashMap<String, IdentityObjectAttribute>(); Criteria criteria = getHibernateSession(ctx).createCriteria(HibernateIdentityObjectAttribute.class) .setCacheable(true).setFetchMode("textValues", FetchMode.JOIN).setFetchSize(20) .createAlias("identityObject", "io").add(Restrictions.eq("io.name", identity.getName())) .add(Restrictions.eq("io.realm", realm)).add(Restrictions.eq("io.identityType", hibernateType)); Collection<HibernateIdentityObjectAttribute> storeAttributes = (Collection<HibernateIdentityObjectAttribute>) criteria .list(); // 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"); } 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()); } } if (mdMap != null && mdMap.containsKey(attribute.getName())) { IdentityObjectAttributeMetaData amd = mdMap.get(attribute.getName()); if (!amd.isMultivalued() && attribute.getSize() > 1) { throw new IdentityException( "Cannot assigned multiply values to single valued attribute: " + attribute.getName()); } if (amd.isReadonly()) { // Just silently fail and go on mappedAttributes.remove(name); continue; //throw new IdentityException("Cannot update readonly attribute: " + attribute.getName()); } if (amd.isUnique()) { IdentityObject checkIdentity = findIdentityObjectByUniqueAttribute(ctx, identity.getIdentityType(), attribute); if (checkIdentity != null && !checkIdentity.getName().equals(identity.getName())) { throw new IdentityException("Unique attribute '" + attribute.getName() + " value already set for identityObject: " + checkIdentity); } } 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); } } if (type.equals(IdentityObjectAttributeMetaData.BINARY_TYPE) && attribute.getValues().size() > 1) { throw new IdentityException( "Cannot add binary type attribute with more than one value - this implementation" + "support only single value binary attributes: " + attribute.getName()); } } } HibernateIdentityObject hibernateObject = safeGet(ctx, identity); Hibernate.initialize(hibernateObject.getAttributes()); for (String name : mappedAttributes.keySet()) { IdentityObjectAttribute attribute = mappedAttributes.get(name); IdentityObjectAttributeMetaData amd = null; if (mdMap != null) { amd = mdMap.get(attribute.getName()); } // Default to text String type = amd != null ? amd.getType() : IdentityObjectAttributeMetaData.TEXT_TYPE; boolean present = false; for (HibernateIdentityObjectAttribute storeAttribute : hibernateObject.getAttributes()) { if (storeAttribute.getName().equals(name)) { present = true; if (storeAttribute.getType().equals(HibernateIdentityObjectAttribute.TYPE_TEXT)) { 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()); } storeAttribute.setTextValues(v); } else if (storeAttribute.getType().equals(HibernateIdentityObjectAttribute.TYPE_BINARY)) { if (!type.equals(IdentityObjectAttributeMetaData.BINARY_TYPE)) { throw new IdentityException( "Wrong attribute mapping. Attribute persisted as binary is mapped with: " + type + ". Attribute name: " + name); } HibernateIdentityObjectAttributeBinaryValue bv = new HibernateIdentityObjectAttributeBinaryValue( (byte[]) attribute.getValue()); getHibernateSession(ctx).persist(bv); storeAttribute.setBinaryValue(bv); } else { throw new IdentityException("Internal identity store error"); } break; } } if (!present && attribute.getValues() != null && attribute.getValues().size() > 0) { HibernateIdentityObjectAttribute newAttribute = new HibernateIdentityObjectAttribute( hibernateObject, name, type); if (type.equals(HibernateIdentityObjectAttribute.TYPE_TEXT)) { newAttribute.setTextValues(attribute.getValues()); } else if (type.equals(HibernateIdentityObjectAttribute.TYPE_BINARY)) { HibernateIdentityObjectAttributeBinaryValue bv = new HibernateIdentityObjectAttributeBinaryValue( (byte[]) attribute.getValue()); getHibernateSession(ctx).persist(bv); newAttribute.setBinaryValue(bv); } hibernateObject.addAttribute(newAttribute); } } } 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 = null; if (mdMap != null) { 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()) { // Just silently fail and go on mappedAttributes.remove(name); continue; //throw new IdentityException("Cannot add readonly attribute: " + attribute.getName()); } if (amd.isUnique()) { IdentityObject checkIdentity = findIdentityObjectByUniqueAttribute(ctx, identity.getIdentityType(), attribute); if (checkIdentity != null && !checkIdentity.getName().equals(identity.getName())) { throw new IdentityException("Unique attribute '" + attribute.getName() + " value already set for identityObject: " + checkIdentity); } } 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); } } if (type.equals(IdentityObjectAttributeMetaData.BINARY_TYPE) && attribute.getValues().size() > 1) { throw new IdentityException( "Cannot add binary type attribute with more than one value - this implementation" + "support only single value binary attributes: " + attribute.getName()); } } } HibernateIdentityObject hibernateObject = safeGet(ctx, identity); Hibernate.initialize(hibernateObject.getAttributes()); for (String name : mappedAttributes.keySet()) { IdentityObjectAttribute attribute = mappedAttributes.get(name); IdentityObjectAttributeMetaData amd = mdMap != null ? mdMap.get(attribute.getName()) : null; // 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.getType().equals(HibernateIdentityObjectAttribute.TYPE_TEXT)) { 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()); } hibernateAttribute.setTextValues(mergedValues); } else if (hibernateAttribute.getType().equals(HibernateIdentityObjectAttribute.TYPE_BINARY)) { if (!type.equals(IdentityObjectAttributeMetaData.BINARY_TYPE)) { throw new IdentityException( "Wrong attribute mapping. Attribute persisted as binary is mapped with: " + type + ". Attribute name: " + name); } HibernateIdentityObjectAttributeBinaryValue bv = new HibernateIdentityObjectAttributeBinaryValue( (byte[]) attribute.getValue()); getHibernateSession(ctx).persist(bv); hibernateAttribute.setBinaryValue(bv); } 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 HibernateIdentityObjectAttribute(hibernateObject, name, HibernateIdentityObjectAttribute.TYPE_TEXT); hibernateAttribute.setTextValues(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 HibernateIdentityObjectAttribute(hibernateObject, name, HibernateIdentityObjectAttribute.TYPE_BINARY); HibernateIdentityObjectAttributeBinaryValue bv = new HibernateIdentityObjectAttributeBinaryValue( (byte[]) attribute.getValue()); getHibernateSession(ctx).persist(bv); hibernateAttribute.setBinaryValue(bv); } 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); Hibernate.initialize(hibernateObject.getAttributes()); for (String attr : mappedAttributes) { hibernateObject.removeAttribute(attr); } } public IdentityObject findIdentityObjectByUniqueAttribute(IdentityStoreInvocationContext invocationCtx, IdentityObjectType identityObjectType, IdentityObjectAttribute attribute) throws IdentityException { if (attribute == null) { throw new IllegalArgumentException("attribute is null"); } checkIOType(identityObjectType); //TODO: check both binary and text with multivalue String attrMappedName = resolveAttributeStoreMapping(identityObjectType, attribute.getName()); HibernateIdentityObjectType hiot = getHibernateIdentityObjectType(invocationCtx, identityObjectType); Session session = getHibernateSession(invocationCtx); HibernateRealm realm = getRealm(session, invocationCtx); if (attribute.getValues() == null || attribute.getValues().size() == 0) { return null; } boolean attrDuctTypeText = true; if (attribute.getValue() instanceof byte[]) { attrDuctTypeText = false; } StringBuffer queryString = new StringBuffer( "select a from HibernateIdentityObjectAttribute a where a.identityObject.identityType = :identityType " + "and a.name = :attributeName and a.identityObject.realm = :realm"); if (attrDuctTypeText) { for (int i = 0; i < attribute.getValues().size(); i++) { String paramName = " :value" + i; queryString.append(" and").append(paramName).append(" = any elements(a.textValues)"); } } else { queryString.append(" and :value = a.binaryValue"); } Query q = session.createQuery(queryString.toString()); q.setParameter("identityType", hiot).setParameter("attributeName", attrMappedName).setParameter("realm", realm); if (attrDuctTypeText) { int i = 0; for (Object o : attribute.getValues()) { String value = o.toString(); String paramName = "value" + i; q.setParameter(paramName, value); i++; } } else { q.setParameter("value", attribute.getValue()); } List<HibernateIdentityObjectAttribute> attrs = (List<HibernateIdentityObjectAttribute>) q.list(); if (attrs.size() == 0) { return null; } if (attrs.size() > 1) { throw new IdentityException( "Illegal state - more than one IdentityObject with the same unique attribute value: " + attribute); } return attrs.get(0).getIdentityObject(); } 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 = null; hibernateCredential = (HibernateIdentityObjectCredential) getHibernateSession(ctx) .createCriteria(HibernateIdentityObjectCredential.class).createAlias("type", "t") .add(Restrictions.eq("t.name", credential.getType().getName())) .add(Restrictions.eq("identityObject", hibernateObject)).setCacheable(true).uniqueResult(); 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().getValue()); } 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 hibernateSession = 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 = hibernateObject .getCredential(credential.getType()); if (hibernateCredential == null) { hibernateCredential = new HibernateIdentityObjectCredential(); hibernateCredential.setType(hibernateCredentialType); hibernateObject.addCredential(hibernateCredential); } 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[]) { HibernateIdentityObjectCredentialBinaryValue bv = new HibernateIdentityObjectCredentialBinaryValue( (byte[]) value); getHibernateSession(ctx).persist(bv); hibernateCredential.setBinaryValue(bv); } else { throw new IdentityException("Not supported credential value: " + value.getClass()); } hibernateSession.persist(hibernateCredential); hibernateObject.addCredential(hibernateCredential); hibernateSession.flush(); } 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); getHibernateSession(ctx).flush(); } public void addIdentityObjectRelationshipType(IdentityStoreInvocationContext ctx, IdentityObjectRelationshipType type) throws IdentityException { HibernateIdentityObjectRelationshipType hibernateType = new HibernateIdentityObjectRelationshipType(type); getHibernateSession(ctx).persist(hibernateType); getHibernateSession(ctx).flush(); } protected Session getHibernateSession(IdentityStoreInvocationContext ctx) throws IdentityException { try { HibernateIdentityStoreSessionImpl hbIdentityStoreSession = (HibernateIdentityStoreSessionImpl) ctx .getIdentityStoreSession(); if (lazyStartOfHibernateTransaction) { hbIdentityStoreSession.startHibernateTransactionIfNotStartedYet(); } return ((Session) hbIdentityStoreSession.getSessionContext()); } catch (Exception e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", e); } throw new IdentityException("Cannot obtain Hibernate Session", 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)) { if (!isAllowNotDefinedIdentityObjectTypes()) { throw new IdentityException( "IdentityType not supported by this IdentityStore implementation: " + iot); } } } private HibernateIdentityObjectType getHibernateIdentityObjectType(IdentityStoreInvocationContext ctx, IdentityObjectType type) throws IdentityException { checkIOType(type); HibernateIdentityObjectType hibernateType = null; Session hibernateSession = getHibernateSession(ctx); try { Criteria crit = hibernateSession.createCriteria(HibernateIdentityObjectType.class) .add(Restrictions.eq("name", type.getName())).setCacheable(true); hibernateType = (HibernateIdentityObjectType) crit.uniqueResult(); if (hibernateType == null) { if (isAllowNotDefinedIdentityObjectTypes()) { populateObjectTypes(hibernateSession, new String[] { type.getName() }); } hibernateType = (HibernateIdentityObjectType) crit.uniqueResult(); } } catch (Exception e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", e); } throw new IdentityException("IdentityObjectType[" + type.getName() + "] not present in the store.", e); } if (hibernateType == null) { throw new IdentityException("IdentityObjectType[" + type.getName() + "] not present in the store."); } return hibernateType; } private HibernateIdentityObject getHibernateIdentityObject(IdentityStoreInvocationContext ctx, IdentityObject io) throws IdentityException { HibernateIdentityObject hibernateObject = null; HibernateIdentityObjectType hibernateType = getHibernateIdentityObjectType(ctx, io.getIdentityType()); HibernateRealm realm = getRealm(getHibernateSession(ctx), ctx); Session hibernateSession = getHibernateSession(ctx); try { hibernateObject = (HibernateIdentityObject) hibernateSession .createCriteria(HibernateIdentityObject.class).add(Restrictions.eq("name", io.getName())) .add(Restrictions.eq("identityType", hibernateType)).add(Restrictions.eq("realm", realm)) .setCacheable(true).uniqueResult(); } catch (Exception e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", 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 hibernateSession = getHibernateSession(ctx); try { relationshipType = (HibernateIdentityObjectRelationshipType) hibernateSession .createCriteria(HibernateIdentityObjectRelationshipType.class) .add(Restrictions.eq("name", iot.getName())).setCacheable(true).uniqueResult(); } catch (Exception e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", e); } throw new IdentityException( "IdentityObjectRelationshipType[ " + iot.getName() + "] not present in the store."); } return relationshipType; } private HibernateIdentityObjectCredentialType getHibernateIdentityObjectCredentialType( IdentityStoreInvocationContext ctx, IdentityObjectCredentialType credentialType) throws IdentityException { Session session = getHibernateSession(ctx); HibernateIdentityObjectCredentialType hibernateType = null; try { hibernateType = (HibernateIdentityObjectCredentialType) session .createCriteria(HibernateIdentityObjectCredentialType.class) .add(Restrictions.eq("name", credentialType.getName())).setCacheable(true).uniqueResult(); } catch (HibernateException e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", e); } throw new IdentityException( "IdentityObjectCredentialType[ " + credentialType.getName() + "] not present in the store."); } return hibernateType; } public void populateObjectTypes(Session hibernateSession, String[] typeNames) throws Exception { 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); } } } public void populateRelationshipTypes(Session hibernateSession, String[] typeNames) throws Exception { 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); } } } public void populateCredentialTypes(Session hibernateSession, String[] typeNames) throws Exception { 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); } } } public void addRealm(Session hibernateSession, String realmName) throws IdentityException { try { HibernateRealm realm = new HibernateRealm(realmName); hibernateSession.persist(realm); } catch (Exception e) { if (log.isLoggable(Level.FINER)) { log.log(Level.FINER, "Exception occurred: ", e); } throw new IdentityException("Failed to create store realm", e); } } private HibernateRealm getRealm(Session hibernateSession, IdentityStoreInvocationContext ctx) throws IdentityException { if (getRealmName(ctx) == 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)).setCacheable(true).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", getRealmName(ctx))).setCacheable(true).uniqueResult(); // TODO: other way to not lazy initialize realm? special method called on every new session creation if (realm == null) { HibernateRealm newRealm = new HibernateRealm(getRealmName(ctx)); hibernateSession.persist(newRealm); return newRealm; } } return realm; } private String getRealmName(IdentityStoreInvocationContext ctx) { if (isRealmAware()) { return ctx.getRealmId(); } else { return DEFAULT_REALM_NAME; } } private boolean isRealmAware() { return isRealmAware; } private boolean isAllowNotDefinedAttributes() { return isAllowNotDefinedAttributes; } /** * 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()) { // Resolve attribute name from the store attribute mapping String mappedAttributeName = null; try { mappedAttributeName = resolveAttributeStoreMapping(object.getIdentityType(), entry.getKey()); } catch (IdentityException e) { //Nothing } if (mappedAttributeName == null) { toRemove.add(object); break; } if (presentAttrs.containsKey(mappedAttributeName)) { Set<String> given = new HashSet<String>(Arrays.asList(entry.getValue())); Collection present = presentAttrs.get(mappedAttributeName); for (String s : given) { String regex = Tools.wildcardToRegex(s); boolean matches = false; for (Object o : present) { if (o.toString().matches(regex)) { matches = true; } } if (!matches) { toRemove.add(object); break; } } } else { toRemove.add(object); break; } } } for (IdentityObject identityObject : toRemove) { objects.remove(identityObject); } } //TODO: need to be implemented at HQL level private <T> List<T> cutPageFromResults(List<T> objects, IdentityObjectSearchCriteria criteria) { List<T> results = new LinkedList<T>(); if (criteria.getMaxResults() == 0) { for (int i = criteria.getFirstResult(); i < objects.size(); i++) { if (i < objects.size()) { results.add(objects.get(i)); } } } else { for (int i = criteria.getFirstResult(); i < criteria.getFirstResult() + criteria.getMaxResults(); i++) { if (i < objects.size()) { results.add(objects.get(i)); } } } return results; } protected boolean isAllowNotDefinedIdentityObjectTypes() { return isAllowNotDefinedIdentityObjectTypes; } public boolean isManageTransactionDuringBootstrap() { return isManageTransactionDuringBootstrap; } public boolean isAllowNotCaseSensitiveSearch() { return isAllowNotCaseSensitiveSearch; } }