/* * JBoss, Home of Professional Open Source * * Copyright 2013 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.picketlink.idm.jpa.internal; import org.picketlink.common.properties.Property; import org.picketlink.common.properties.query.NamedPropertyCriteria; import org.picketlink.common.properties.query.PropertyQueries; import org.picketlink.common.properties.query.TypedPropertyCriteria; import org.picketlink.common.properties.query.TypedPropertyCriteria.MatchOption; import org.picketlink.common.util.Base64; import org.picketlink.idm.IdentityManagementException; import org.picketlink.idm.config.IdentityStoreConfiguration.IdentityOperation; import org.picketlink.idm.config.JPAIdentityStoreConfiguration; import org.picketlink.idm.config.SecurityConfigurationException; import org.picketlink.idm.credential.handler.DigestCredentialHandler; import org.picketlink.idm.credential.handler.PasswordCredentialHandler; import org.picketlink.idm.credential.handler.TOTPCredentialHandler; import org.picketlink.idm.credential.handler.TokenCredentialHandler; import org.picketlink.idm.credential.handler.X509CertificateCredentialHandler; import org.picketlink.idm.credential.handler.annotations.CredentialHandlers; import org.picketlink.idm.credential.storage.CredentialStorage; import org.picketlink.idm.internal.AbstractAttributeStore; import org.picketlink.idm.internal.IdentityTypeReference; import org.picketlink.idm.internal.RelationshipReference; import org.picketlink.idm.internal.util.IdentityTypeUtil; import org.picketlink.idm.internal.util.PermissionUtil; import org.picketlink.idm.jpa.annotations.AttributeClass; import org.picketlink.idm.jpa.annotations.AttributeName; import org.picketlink.idm.jpa.annotations.AttributeValue; import org.picketlink.idm.jpa.annotations.CredentialClass; import org.picketlink.idm.jpa.annotations.EffectiveDate; import org.picketlink.idm.jpa.annotations.ExpiryDate; import org.picketlink.idm.jpa.annotations.Identifier; import org.picketlink.idm.jpa.annotations.IdentityClass; import org.picketlink.idm.jpa.annotations.OwnerReference; import org.picketlink.idm.jpa.annotations.PartitionClass; import org.picketlink.idm.jpa.annotations.PermissionOperation; import org.picketlink.idm.jpa.annotations.PermissionResourceClass; import org.picketlink.idm.jpa.annotations.PermissionResourceIdentifier; import org.picketlink.idm.jpa.annotations.RelationshipClass; import org.picketlink.idm.jpa.annotations.RelationshipDescriptor; import org.picketlink.idm.jpa.annotations.RelationshipMember; import org.picketlink.idm.jpa.annotations.entity.ConfigurationName; import org.picketlink.idm.jpa.annotations.entity.IdentityManaged; import org.picketlink.idm.jpa.annotations.entity.ManagedCredential; import org.picketlink.idm.jpa.annotations.entity.PermissionManaged; import org.picketlink.idm.jpa.internal.mappers.EntityMapper; import org.picketlink.idm.jpa.internal.mappers.EntityMapping; import org.picketlink.idm.model.Account; import org.picketlink.idm.model.Attribute; import org.picketlink.idm.model.AttributedType; import org.picketlink.idm.model.IdentityType; import org.picketlink.idm.model.Partition; import org.picketlink.idm.model.Relationship; import org.picketlink.idm.permission.IdentityPermission; import org.picketlink.idm.permission.Permission; import org.picketlink.idm.permission.acl.spi.PermissionStore; import org.picketlink.idm.permission.annotations.AllowedOperation; import org.picketlink.idm.permission.annotations.AllowedOperations; import org.picketlink.idm.query.AttributeParameter; import org.picketlink.idm.query.Condition; import org.picketlink.idm.query.IdentityQuery; import org.picketlink.idm.query.QueryParameter; import org.picketlink.idm.query.RelationshipQuery; import org.picketlink.idm.query.RelationshipQueryParameter; import org.picketlink.idm.query.Sort; import org.picketlink.idm.query.internal.BetweenCondition; import org.picketlink.idm.query.internal.EqualCondition; import org.picketlink.idm.query.internal.GreaterThanCondition; import org.picketlink.idm.query.internal.InCondition; import org.picketlink.idm.query.internal.LessThanCondition; import org.picketlink.idm.query.internal.LikeCondition; import org.picketlink.idm.spi.AttributeStore; import org.picketlink.idm.spi.CredentialStore; import org.picketlink.idm.spi.IdentityContext; import org.picketlink.idm.spi.PartitionStore; import javax.persistence.EntityManager; import javax.persistence.NoResultException; import javax.persistence.Query; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Join; import javax.persistence.criteria.Order; import javax.persistence.criteria.Path; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import javax.persistence.criteria.Subquery; import java.io.Serializable; import java.lang.annotation.Annotation; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import static org.picketlink.common.reflection.Reflections.classForName; import static org.picketlink.common.reflection.Reflections.newInstance; import static org.picketlink.common.util.StringUtil.isNullOrEmpty; import static org.picketlink.idm.IDMInternalLog.JPA_STORE_LOGGER; import static org.picketlink.idm.IDMInternalMessages.MESSAGES; import static org.picketlink.idm.internal.util.PermissionUtil.asOperationList; /** * Implementation of IdentityStore that stores its state in a relational database. * * @author Shane Bryzak * @author Pedro Silva */ @CredentialHandlers({ PasswordCredentialHandler.class, X509CertificateCredentialHandler.class, DigestCredentialHandler.class, TOTPCredentialHandler.class, TokenCredentialHandler.class}) public class JPAIdentityStore extends AbstractAttributeStore<JPAIdentityStoreConfiguration> implements CredentialStore<JPAIdentityStoreConfiguration>, PartitionStore<JPAIdentityStoreConfiguration>, AttributeStore<JPAIdentityStoreConfiguration>, PermissionStore { // Invocation context parameters public static final String INVOCATION_CTX_ENTITY_MANAGER = "CTX_ENTITY_MANAGER"; private final List<EntityMapper> entityMappers = new ArrayList<EntityMapper>(); @Override public void setup(JPAIdentityStoreConfiguration config) { super.setup(config); if (config.getContextInitializers().isEmpty()) { JPA_STORE_LOGGER.jpaContextInitializerNotProvided(); } for (Class<?> entityType : config.getEntityTypes()) { configureEntityMapper(entityType); } logEntityMappers(); validateConfiguration(); } @Override public void addAttributedType(IdentityContext context, AttributedType attributedType) { EntityManager entityManager = getEntityManager(context); for (EntityMapper entityMapper : getMapperFor(attributedType.getClass())) { entityMapper.persist(attributedType, entityManager); if (Relationship.class.isInstance(attributedType)) { if (entityMapper.isRoot()) { storeRelationshipMembers((Relationship) attributedType, entityManager); } } } } @Override public void updateAttributedType(IdentityContext context, AttributedType attributedType) { EntityManager entityManager = getEntityManager(context); for (EntityMapper entityMapper : getMapperFor(attributedType.getClass())) { entityMapper.updateEntity(attributedType, entityManager); } } @Override public void removeAttributedType(IdentityContext context, AttributedType attributedType) { EntityManager entityManager = getEntityManager(context); EntityMapper rootMapper = getRootMapper(attributedType.getClass()); if (Relationship.class.isAssignableFrom(attributedType.getClass())) { removeChildRelationships(context, (Relationship) attributedType, entityManager); } removeAssociatedEntities(attributedType, entityManager, rootMapper); entityManager.remove(getRootEntity(attributedType, entityManager)); } @Override protected void removeFromRelationships(IdentityContext context, IdentityType identityType) { // First we build a list of all the relationships that the specified identity // is participating in List<?> relationshipsToRemove = findIdentityTypeRelationships(context, Relationship.class, identityType); // Now that we have the list, we can iterate through and remove the records for (Object relationship : relationshipsToRemove) { remove(context, convertToRelationshipType(context, relationship)); } } @Override protected void removeCredentials(IdentityContext context, Account account) { EntityManager entityManager = getEntityManager(context); List entities = new ArrayList(); for (EntityMapper attributeMapper : getEntityMappers()) { if (attributeMapper.getEntityType().isAnnotationPresent(ManagedCredential.class)) { CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery<?> criteria = builder.createQuery(attributeMapper.getEntityType()); Root<?> root = criteria.from(attributeMapper.getEntityType()); Object agentInstance = getRootEntity(account, entityManager); Property identityTypeProperty = attributeMapper.getProperty(OwnerReference.class).getValue(); criteria.where(builder.equal(root.get(identityTypeProperty.getName()), agentInstance)); Property effectiveProperty = attributeMapper.getProperty(EffectiveDate.class).getValue(); criteria.orderBy(builder.desc(root.get(effectiveProperty.getName()))); List result = entityManager.createQuery(criteria).getResultList(); for (Object storageEntity : result) { entities.add(storageEntity); } } } for (Object credentialEntity : entities) { entityManager.remove(credentialEntity); } } @Override public void add(IdentityContext identityContext, Partition partition, String configurationName) { add(identityContext, partition); // now that the partition entity is created, let`s populate the configuration name. // the configuration name is not part of the Model API, so we need to do this manually. EntityMapper entityMapper = getRootMapper(partition.getClass()); EntityManager entityManager = getEntityManager(identityContext); Object partitionEntity = getRootEntity(partition, entityManager); Property configurationNameProperty = entityMapper.getProperty(partition.getClass(), ConfigurationName.class).getValue(); configurationNameProperty.setValue(partitionEntity, configurationName); entityManager.merge(partitionEntity); } @Override public String getConfigurationName(IdentityContext identityContext, Partition partition) { EntityMapper entityMapper = getRootMapper(partition.getClass()); EntityManager entityManager = getEntityManager(identityContext); Object partitionEntity = entityManager.find(entityMapper.getEntityType(), partition.getId()); Property configurationNameProperty = entityMapper.getProperty(partition.getClass(), ConfigurationName.class).getValue(); String configurationName = configurationNameProperty.getValue(partitionEntity).toString(); if (isNullOrEmpty(configurationName)) { throw MESSAGES.partitionWithNoConfigurationName(partition); } return configurationName; } @Override public <P extends Partition> P get(IdentityContext identityContext, Class<P> partitionClass, String name) { List<P> result = getPartitions(identityContext, partitionClass, name); if (!result.isEmpty()) { if (result.size() > 1) { throw MESSAGES.partitionFoundWithSameNameAndType(name, partitionClass); } return result.get(0); } return null; } @Override public <P extends Partition> List<P> get(IdentityContext identityContext, Class<P> partitionClass) { return getPartitions(identityContext, partitionClass, null); } public <P extends Partition> List<P> getPartitions(IdentityContext identityContext, Class<P> partitionClass, String name) { EntityManager entityManager = getEntityManager(identityContext); String PARTITION_NAME_PROPERTY_NAME = "name"; EntityMapper entityMapper = getEntityMapperForProperty(partitionClass, PARTITION_NAME_PROPERTY_NAME); CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery cq = cb.createQuery(entityMapper.getEntityType()); Root from = cq.from(entityMapper.getEntityType()); List<Predicate> predicates = new ArrayList<Predicate>(); if (!isNullOrEmpty(name)) { Property nameProperty = entityMapper.getProperty(partitionClass, PARTITION_NAME_PROPERTY_NAME).getValue(); predicates.add(cb.equal(from.get(nameProperty.getName()), name)); } if (!Partition.class.equals(partitionClass)) { Property typeProperty = entityMapper.getProperty(partitionClass, PartitionClass.class).getValue(); predicates.add(cb.equal(from.get(typeProperty.getName()), partitionClass.getName())); } cq.where(predicates.toArray(new Predicate[predicates.size()])); Query query = entityManager.createQuery(cq); List<P> result = new ArrayList<P>(); for (Object entity : query.getResultList()) { result.add(entityMapper.<P>createType(entity, entityManager)); } return result; } @Override public <P extends Partition> P lookupById(final IdentityContext context, final Class<P> partitionClass, final String id) { EntityManager entityManager = getEntityManager(context); EntityMapper entityMapper = getRootMapper(Partition.class); CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery cq = cb.createQuery(entityMapper.getEntityType()); Root from = cq.from(entityMapper.getEntityType()); List<Predicate> predicates = new ArrayList<Predicate>(); Property idProperty = entityMapper.getProperty(Partition.class, Identifier.class).getValue(); predicates.add(cb.equal(from.get(idProperty.getName()), id)); if (!Partition.class.equals(partitionClass)) { Property typeProperty = entityMapper.getProperty(partitionClass, PartitionClass.class).getValue(); predicates.add(cb.equal(from.get(typeProperty.getName()), partitionClass.getName())); } cq.where(predicates.toArray(new Predicate[predicates.size()])); Query query = entityManager.createQuery(cq); query.setMaxResults(1); List result = query.getResultList(); if (!result.isEmpty()) { return entityMapper.createType(result.get(0), entityManager); } return null; } @Override public void update(IdentityContext identityContext, Partition partition) { update(identityContext, (AttributedType) partition); } @Override public void remove(IdentityContext identityContext, Partition partition) { remove(identityContext, (AttributedType) partition); } @Override protected Collection<Attribute<? extends Serializable>> getAttributes(IdentityContext identityContext, AttributedType attributedType) { EntityMapper attributeMapper = getAttributeMapper(attributedType.getClass()); Class<?> attributeEntityClass = attributeMapper.getEntityType(); EntityManager entityManager = getEntityManager(identityContext); CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<?> cq = cb.createQuery(attributeEntityClass); Root<?> from = cq.from(attributeEntityClass); List<Predicate> predicates = new ArrayList<Predicate>(); Property attributeNameProperty = attributeMapper.getProperty(Attribute.class, AttributeName.class).getValue(); // if (attributeName != null) { // predicates.add(cb.equal(from.get(attributeNameProperty.getName()), // attributeName)); // } Property ownerProperty = attributeMapper.getProperty(Attribute.class, OwnerReference.class).getValue(); if (getConfig().supportsType(attributedType.getClass(), IdentityOperation.create) && !String.class.equals(ownerProperty.getJavaClass())) { predicates.add(cb.equal(from.get(ownerProperty.getName()), getOwnerEntity(attributedType, ownerProperty, entityManager))); } else { predicates.add(cb.equal(from.get(ownerProperty.getName()), attributedType.getId())); } cq.where(predicates.toArray(new Predicate[predicates.size()])); Property attributeValueProperty = attributeMapper.getProperty(Attribute.class, AttributeValue.class).getValue(); Map<String, Attribute<? extends Serializable>> attributes = new HashMap<String, Attribute<? extends Serializable>>(); for (Object attributeEntity : entityManager.createQuery(cq).getResultList()) { String storedName = attributeNameProperty.getValue(attributeEntity).toString(); Serializable storedValue = (Serializable) Base64.decodeToObject(attributeValueProperty.getValue(attributeEntity).toString()); Attribute attribute = attributes.get(storedName); if (attribute == null) { attribute = new Attribute<Serializable>(storedName, storedValue); } else { // if it is a multi-valued attribute if (attribute != null) { Serializable[] values = null; if (attribute.getValue().getClass().isArray()) { values = (Serializable[]) attribute.getValue(); } else { values = (Serializable[]) Array.newInstance(attribute.getValue().getClass(), 1); values[0] = attribute.getValue(); } Serializable[] newValues = Arrays.copyOf(values, values.length + 1); newValues[newValues.length - 1] = storedValue; attribute.setValue(newValues); } } attributes.put(attribute.getName(), attribute); } return attributes.values(); } @Override public void removeAttribute(IdentityContext context, AttributedType attributedType, String attributeName) { EntityMapper attributeMapper = getAttributeMapper(attributedType.getClass()); EntityManager entityManager = getEntityManager(context); CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<?> cq = cb.createQuery(attributeMapper.getEntityType()); Root<?> from = cq.from(attributeMapper.getEntityType()); List<Predicate> predicates = new ArrayList<Predicate>(); Property attributeNameProperty = attributeMapper.getProperty(Attribute.class, AttributeName.class).getValue(); predicates.add(cb.equal(from.get(attributeNameProperty.getName()), attributeName)); Property ownerProperty = attributeMapper.getProperty(Attribute.class, OwnerReference.class).getValue(); if (getConfig().supportsType(attributedType.getClass(), IdentityOperation.create) && !String.class.equals(ownerProperty.getJavaClass())) { predicates.add(cb.equal(from.get(ownerProperty.getName()), getOwnerEntity(attributedType, ownerProperty, entityManager))); } else { predicates.add(cb.equal(from.get(ownerProperty.getName()), attributedType.getId())); } cq.where(predicates.toArray(new Predicate[predicates.size()])); for (Object entity : entityManager.createQuery(cq).getResultList()) { entityManager.remove(entity); } } @Override public <V extends IdentityType> List<V> fetchQueryResults(IdentityContext context, IdentityQuery<V> identityQuery) { List<V> result = new ArrayList<V>(); Class<V> type = identityQuery.getIdentityType(); for (Condition condition : identityQuery.getConditions()) { if (IdentityType.ID.equals(condition.getParameter())) { if (!EqualCondition.class.isInstance(condition)) { throw new IdentityManagementException("Only equality conditions are allowed when queryng based on the identifier."); } EqualCondition equalCondition = (EqualCondition) condition; Object value = equalCondition.getValue(); if (value != null) { V identityType = (V) lookupIdentityTypeById(context, type, value.toString()); if (identityType != null) { result.add(identityType); } } return result; } } EntityMapper rootMapper = getRootMapper(type); EntityManager entityManager = getEntityManager(context); CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery cq = cb.createQuery(rootMapper.getEntityType()); List<Predicate> predicates = new ArrayList<Predicate>(); Root<?> rootEntity = cq.from(rootMapper.getEntityType()); Partition partition = context.getPartition(); for (Condition condition : identityQuery.getConditions()) { if (IdentityType.PARTITION.equals(condition.getParameter())) { if (!EqualCondition.class.isInstance(condition)) { throw new IdentityManagementException("Only equality conditions are allowed when queryng based on a partition."); } EqualCondition equalCondition = (EqualCondition) condition; Object value = equalCondition.getValue(); if (value != null) { partition = (Partition) value; } } } Entry<Property, Property> partitionProperty = rootMapper.getProperty(OwnerReference.class); if (partitionProperty != null && getConfig().supportsPartition()) { Join<Object, Object> join = rootEntity.join(partitionProperty.getValue().getName()); predicates.add(cb.equal(join, entityManager.find(partitionProperty.getValue().getJavaClass(), partition.getId()))); } if (!IdentityType.class.equals(type)) { Property typeProperty = rootMapper.getProperty(type, IdentityClass.class).getValue(); predicates.add(cb.equal(rootEntity.get(typeProperty.getName()), type.getName())); } for (Condition condition : identityQuery.getConditions()) { QueryParameter queryParameter = condition.getParameter(); if (IdentityType.PARTITION.equals(queryParameter)) { continue; } if (AttributeParameter.class.isInstance(queryParameter)) { AttributeParameter attributeParameter = (AttributeParameter) queryParameter; EntityMapper parameterEntityMapper = getEntityMapperForProperty(type, attributeParameter.getName()); if (parameterEntityMapper != null) { Property attributeProperty = (Property) parameterEntityMapper.getProperty(type, attributeParameter.getName()).getValue(); Root<?> attributeOwnerEntity = rootEntity; if (!parameterEntityMapper.getEntityType().equals(rootMapper.getEntityType())) { attributeOwnerEntity = cq.from(parameterEntityMapper.getEntityType()); Property ownerProperty = parameterEntityMapper.getProperty(OwnerReference.class).getValue(); if (ownerProperty != null) { if (ownerProperty.getAnnotatedElement().isAnnotationPresent(Identifier.class)) { predicates.add(cb.and(cb.equal(attributeOwnerEntity, rootEntity))); } else { predicates.add(cb.and(cb.equal(attributeOwnerEntity.get(ownerProperty.getName()), rootEntity))); } } } addCondition(entityManager, cb, predicates, condition, attributeProperty, attributeOwnerEntity, false); } else if (getConfig().supportsAttribute()) { addAttributeQueryPredicates(type, entityManager, cb, cq, rootEntity, predicates, attributeParameter, condition, null); } } } Property idProperty = rootMapper.getProperty(Identifier.class).getValue(); cq.select(rootEntity.get(idProperty.getName())); cq.where(predicates.toArray(new Predicate[predicates.size()])); if (!identityQuery.getSorting().isEmpty()) { List<Order> orders = new ArrayList<Order>(); for (Sort sort : identityQuery.getSorting()) { QueryParameter queryParameter = sort.getParameter(); if (!AttributeParameter.class.isInstance(queryParameter)) { throw new IdentityManagementException("Sorting parameter is not a [" + AttributeParameter.class + "]."); } AttributeParameter attributeParameter = (AttributeParameter) queryParameter; if (sort.isAscending()) { orders.add(cb.asc(rootEntity.get(attributeParameter.getName()))); } else { orders.add(cb.desc(rootEntity.get(attributeParameter.getName()))); } } cq.orderBy(orders); } Query query = entityManager.createQuery(cq); if (identityQuery.getLimit() > 0) { query.setMaxResults(identityQuery.getLimit()); if (identityQuery.getOffset() > 0) { query.setFirstResult(identityQuery.getOffset()); } } for (Object entity : query.getResultList()) { result.add(rootMapper.<V>createType(entityManager.find(rootMapper.getEntityType(), entity), entityManager)); } return result; } private void addCondition(EntityManager entityManager, CriteriaBuilder cb, List<Predicate> predicates, Condition condition, Property attributeProperty, Root<?> attributeOwnerEntity, boolean convertValueToBase64) { if (EqualCondition.class.isInstance(condition)) { EqualCondition equalCondition = (EqualCondition) condition; Object parameterValue = equalCondition.getValue(); if (convertValueToBase64) { parameterValue = Base64.encodeObject((Serializable) parameterValue); } if (isMappedType(attributeProperty.getJavaClass())) { AttributedType ownerType = (AttributedType) parameterValue; if (ownerType != null) { parameterValue = entityManager.find(attributeProperty.getJavaClass(), ownerType.getId()); } } predicates.add(cb.equal(attributeOwnerEntity.get(attributeProperty.getName()), parameterValue)); } else if (LikeCondition.class.isInstance(condition)) { LikeCondition likeCondition = (LikeCondition) condition; String parameterValue = (String) likeCondition.getValue(); if (convertValueToBase64) { parameterValue = Base64.encodeObject((Serializable) parameterValue); } predicates.add(cb.like(attributeOwnerEntity.<String>get(attributeProperty.getName()), parameterValue)); } else if (GreaterThanCondition.class.isInstance(condition)) { GreaterThanCondition greaterThanCondition = (GreaterThanCondition) condition; Comparable parameterValue = (Comparable) greaterThanCondition.getValue(); if (convertValueToBase64) { parameterValue = Base64.encodeObject((Serializable) parameterValue); } if (greaterThanCondition.isOrEqual()) { predicates.add(cb .greaterThanOrEqualTo(attributeOwnerEntity.<Comparable>get(attributeProperty.getName()), parameterValue)); } else { predicates.add(cb .greaterThan(attributeOwnerEntity.<Comparable>get(attributeProperty.getName()), parameterValue)); } } else if (LessThanCondition.class.isInstance(condition)) { LessThanCondition lessThanCondition = (LessThanCondition) condition; Comparable parameterValue = (Comparable) lessThanCondition.getValue(); if (convertValueToBase64) { parameterValue = Base64.encodeObject((Serializable) parameterValue); } if (lessThanCondition.isOrEqual()) { predicates.add(cb .lessThanOrEqualTo(attributeOwnerEntity .<Comparable>get(attributeProperty.getName()), parameterValue)); } else { predicates.add(cb .lessThan(attributeOwnerEntity.<Comparable>get(attributeProperty.getName()), parameterValue)); } } else if (BetweenCondition.class.isInstance(condition)) { BetweenCondition betweenCondition = (BetweenCondition) condition; Comparable x = betweenCondition.getX(); Comparable y = betweenCondition.getY(); if (convertValueToBase64) { x = Base64.encodeObject((Serializable) x); y = Base64.encodeObject((Serializable) y); } predicates.add(cb.between(attributeOwnerEntity.<Comparable>get(attributeProperty.getName()), x, y)); } else if (InCondition.class.isInstance(condition)) { InCondition inCondition = (InCondition) condition; Object[] valuesToSearch = new String[inCondition.getValue().length]; for (int i = 0; i < inCondition.getValue().length; i++) { if (convertValueToBase64) { valuesToSearch[i] = Base64.encodeObject((Serializable) inCondition.getValue()[i]); } else { valuesToSearch[i] = inCondition.getValue()[i]; } } predicates.add(attributeOwnerEntity.get(attributeProperty.getName()).in(valuesToSearch)); } else { throw new IdentityManagementException("Unsupported query condition [" + condition + "]."); } } @Override public <V extends Relationship> List<V> fetchQueryResults(IdentityContext context, RelationshipQuery<V> query) { EntityManager entityManager = getEntityManager(context); List entities = new ArrayList(); Object[] identityParameterValues = query.getParameter(Relationship.IDENTITY); if (identityParameterValues != null) { for (Object parameterValue : identityParameterValues) { if (IdentityType.class.isInstance(parameterValue)) { entities = findIdentityTypeRelationships(context, query.getRelationshipClass(), (IdentityType) parameterValue); } else { throw MESSAGES.queryUnsupportedParameterValue("Relationship.IDENTITY", parameterValue); } } } else { Class<V> relationshipType = query.getRelationshipClass(); EntityMapper entityMapper = getRootMapper(relationshipType); CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<?> cq = cb.createQuery(entityMapper.getEntityType()); Root root = cq.from(entityMapper.getEntityType()); List<Predicate> predicates = new ArrayList<Predicate>(); Property typeProperty = entityMapper.getProperty(RelationshipClass.class).getValue(); if (!Relationship.class.equals(relationshipType)) { predicates.add(cb.equal(root.get(typeProperty.getName()), relationshipType.getName())); } Object[] idParameterValues = query.getParameter(Relationship.ID); Property idProperty = entityMapper.getProperty(Identifier.class).getValue(); if (idParameterValues != null && idParameterValues.length > 0) { predicates.add(cb.equal(root.get(idProperty.getName()), idParameterValues[0])); } else { for (Entry<QueryParameter, Object[]> entry : query.getParameters().entrySet()) { QueryParameter queryParameter = entry.getKey(); Object[] values = entry.getValue(); if (queryParameter instanceof RelationshipQueryParameter) { RelationshipQueryParameter identityTypeParameter = (RelationshipQueryParameter) entry.getKey(); List<String> identityTypeIdentifiers = new ArrayList<String>(); EntityMapper relationshipMemberMapper = getEntityMapperForProperty(relationshipType, RelationshipMember.class); for (Object object : values) { IdentityType identityType = (IdentityType) object; if (identityType == null) { return Collections.emptyList(); } Property<Object> identityTypeProperty = relationshipMemberMapper.getProperty(RelationshipMember.class).getValue(); if (identityTypeProperty.getJavaClass().equals(String.class)) { identityTypeIdentifiers.add(IdentityTypeUtil.formatId(identityType)); } else { identityTypeIdentifiers.add(identityType.getId()); } } Property<Object> relationshipProperty = relationshipMemberMapper.getProperty(OwnerReference.class).getValue(); Subquery<?> subQuery = cq.subquery(relationshipMemberMapper.getEntityType()); Root fromRelationshipIdentityType = subQuery.from(relationshipMemberMapper.getEntityType()); subQuery.select(fromRelationshipIdentityType.get(relationshipProperty.getName()).get(idProperty.getName())); List<Predicate> subQueryPredicates = new ArrayList<Predicate>(); Property<String> descriptorProperty = relationshipMemberMapper.getProperty(RelationshipDescriptor.class).getValue(); subQueryPredicates.add( cb.equal(fromRelationshipIdentityType.get(descriptorProperty.getName()), identityTypeParameter.getName())); Property<Object> identityProperty = relationshipMemberMapper.getProperty(RelationshipMember.class).getValue(); if (identityProperty.getJavaClass().equals(String.class)) { subQueryPredicates.add(fromRelationshipIdentityType.get(identityProperty.getName()).in(identityTypeIdentifiers)); } else { Join join = fromRelationshipIdentityType.join(identityProperty.getName()); EntityMapper identityTypeMapper = getMapperForEntity(identityProperty.getJavaClass()); Property identifierProperty = identityTypeMapper.getProperty(Identifier.class).getValue(); subQueryPredicates.add(join.get(identifierProperty.getName()).in(identityTypeIdentifiers)); } subQuery.where(subQueryPredicates.toArray(new Predicate[subQueryPredicates.size()])); predicates.add(cb.in(root.get(idProperty.getName())).value(subQuery)); } else if (AttributeParameter.class.equals(entry.getKey().getClass())) { AttributeParameter attributeParameter = (AttributeParameter) entry.getKey(); Object[] parameterValues = entry.getValue(); EntityMapper parameterEntityMapper = getEntityMapperForProperty(relationshipType, attributeParameter.getName()); if (parameterEntityMapper != null) { Root<?> propertyEntityJoin = root; Property ownerProperty = parameterEntityMapper.getProperty(relationshipType, OwnerReference.class).getValue(); if (ownerProperty.getJavaClass().equals(entityMapper.getEntityType())) { propertyEntityJoin = cq.from(parameterEntityMapper.getEntityType()); predicates.add(cb.and(cb.equal(propertyEntityJoin.get(ownerProperty.getName()), root))); } Object parameterValue = parameterValues[0]; Property mappedProperty = parameterEntityMapper.getProperty(relationshipType, attributeParameter.getName()).getValue(); if (isMappedType(mappedProperty.getJavaClass())) { AttributedType ownerType = (AttributedType) parameterValue; if (ownerType != null) { parameterValue = entityManager.find(mappedProperty.getJavaClass(), ownerType.getId()); } } predicates.add(cb.equal(propertyEntityJoin.get(mappedProperty.getName()), parameterValue)); } else { addAttributeQueryPredicates(relationshipType, entityManager, cb, cq, root, predicates, attributeParameter, null, parameterValues); } } } } cq.select(root); cq.where(predicates.toArray(new Predicate[predicates.size()])); entities = entityManager.createQuery(cq).getResultList(); } List<V> result = new ArrayList<V>(); for (Object relationshipObject : entities) { result.add(this.<V>convertToRelationshipType(context, relationshipObject)); } return result; } @Override public void doSetAttribute(IdentityContext context, AttributedType attributedType, Attribute<? extends Serializable> attribute) { removeAttribute(context, attributedType, attribute.getName()); Serializable values = attribute.getValue(); if (!values.getClass().isArray()) { values = new Serializable[]{values}; } if (values instanceof byte[]) { values = new Serializable[]{values}; } EntityMapper attributeMapper = getAttributeMapper(attributedType.getClass()); Property attributeNameProperty = attributeMapper.getProperty(Attribute.class, AttributeName.class).getValue(); Property attributeValueProperty = attributeMapper.getProperty(Attribute.class, AttributeValue.class).getValue(); Property ownerProperty = attributeMapper.getProperty(Attribute.class, OwnerReference.class).getValue(); EntityManager entityManager = getEntityManager(context); for (Serializable attributeValue : (Serializable[]) values) { Object attributeEntity = attributeMapper.createEntity(); attributeNameProperty.setValue(attributeEntity, attribute.getName()); attributeValueProperty.setValue(attributeEntity, Base64.encodeObject(attributeValue)); if (getConfig().supportsType(attributedType.getClass(), IdentityOperation.create) && !String.class.equals(ownerProperty.getJavaClass())) { ownerProperty.setValue(attributeEntity, getOwnerEntity(attributedType, ownerProperty, entityManager)); } else { ownerProperty.setValue(attributeEntity, attributedType.getId()); } entityManager.persist(attributeEntity); entityManager.flush(); } } @Override public void storeCredential(IdentityContext context, Account account, CredentialStorage storage) { EntityMapper credentialMapper = getCredentialAttributeMapper(storage.getClass()); Object newCredential = credentialMapper.createEntity(); EntityManager entityManager = getEntityManager(context); for (EntityMapping entityMapping : credentialMapper.getEntityMappings()) { for (Property property : entityMapping.getProperties().keySet()) { Property mappedProperty = entityMapping.getProperties().get(property); if (mappedProperty.getAnnotatedElement().isAnnotationPresent(OwnerReference.class)) { mappedProperty.setValue(newCredential, getOwnerEntity(account, mappedProperty, entityManager)); } else { mappedProperty.setValue(newCredential, property.getValue(storage)); } } } entityManager.persist(newCredential); entityManager.flush(); } @Override public <T extends CredentialStorage> T retrieveCurrentCredential(IdentityContext context, Account account, Class<T> storageClass) { List<T> credentials = retrieveCredentials(context, account, storageClass); if (!credentials.isEmpty()) { return credentials.get(0); } return null; } @Override public <T extends CredentialStorage> List<T> retrieveCredentials(IdentityContext context, Account account, Class<T> storageClass) { List<T> storages = new ArrayList<T>(); for (Object object : findCredentials(context, account, storageClass)) { storages.add(convertToCredentialStorage(object, storageClass)); } return storages; } @Override public void removeCredential(IdentityContext context, Account account, Class<? extends CredentialStorage> storageClass) { List<?> credentials = findCredentials(context, account, storageClass); EntityManager entityManager = getEntityManager(context); for (Object credential : credentials) { entityManager.remove(credential); } entityManager.flush(); } public Object getOwnerEntity(final AttributedType attributedType, final Property ownerProperty, final EntityManager entityManager) { EntityMapper attributedTypeMapper = getRootMapper(attributedType.getClass()); Object entity = null; if (ownerProperty.getJavaClass().isAssignableFrom(attributedTypeMapper.getEntityType())) { entity = getRootEntity(attributedType, entityManager); } else { EntityMapper ownerMapper = getMapperForEntity(ownerProperty.getJavaClass()); List associatedEntities = attributedTypeMapper.getAssociatedEntities(attributedType, ownerMapper, entityManager); if (!associatedEntities.isEmpty()) { entity = associatedEntities.get(0); } } return entity; } /** * <p>Returns all {@link EntityMapper} instances used to map the given {@link AttributedType}. Only mappers for * {@link IdentityManaged} annotated entity classes are considered, what means that this method can only be * used * when * trying to persist or populate @{link AttributedType} instances.</p> * * @param attributedType * * @return */ public List<EntityMapper> getMapperFor(Class<? extends AttributedType> attributedType) { List<EntityMapper> mappers = new ArrayList<EntityMapper>(); for (EntityMapper entityMapper : this.entityMappers) { if (entityMapper.getEntityType().isAnnotationPresent(IdentityManaged.class)) { for (EntityMapping entityMapping : entityMapper.getEntityMappings()) { if ((entityMapping.getSupportedType().equals(attributedType) || entityMapping.getSupportedType().isAssignableFrom(attributedType)) && entityMapper.isRoot()) { mappers.add(0, entityMapper); } else if (entityMapping.getSupportedType().isAssignableFrom(attributedType)) { mappers.add(entityMapper); } else { if (Partition.class.equals(attributedType) || IdentityType.class.equals(attributedType) || Relationship.class.equals(attributedType)) { if (attributedType.isAssignableFrom(entityMapping.getSupportedType())) { mappers.add(entityMapper); } } } } } } if (mappers.isEmpty()) { throw new IdentityManagementException("No entity mapper found for type [" + attributedType + "]."); } return mappers; } public EntityMapper getRootMapperForEntity(Class<?> entityClass) { for (EntityMapper entityMapper : this.entityMappers) { if (entityMapper.isRoot() && entityMapper.getEntityType().equals(entityClass)) { return entityMapper; } } throw new IdentityManagementException("No mapper for entity type [" + entityClass + "]."); } public EntityMapper getMapperForEntity(Class<?> entityClass) { for (EntityMapper entityMapper : this.entityMappers) { if (entityMapper.getEntityType().equals(entityClass)) { return entityMapper; } } throw new IdentityManagementException("No mapper for entity type [" + entityClass + "]."); } public List<EntityMapper> getEntityMappers() { return this.entityMappers; } public boolean isMappedType(Class mappedClass) { for (EntityMapper entityMapper : getEntityMappers()) { if (entityMapper.getEntityType().equals(mappedClass)) { return true; } } return false; } public Object getRootEntity(AttributedType attributedType, EntityManager entityManager) { return entityManager.find(getRootMapper(attributedType.getClass()).getEntityType(), attributedType.getId()); } private <V extends IdentityType> IdentityType lookupIdentityTypeById(IdentityContext context, Class<V> type, String identifier) { EntityManager entityManager = getEntityManager(context); if (IdentityType.class.equals(type)) { // when querying based on the IdentityType base type, we try to load the instance from all available mappers. for (EntityMapper entityMapper : getEntityMappers()) { if (entityMapper.getMappingsFor(type) != null && entityMapper.isRoot()) { Object entity = entityManager.find(entityMapper.getEntityType(), identifier); V identityType = entityMapper.<V>createType(entity, entityManager); if (identityType != null) { return identityType; } } } } else { // we know the right type, we just lookup based on its root mapper Object entity = entityManager.find(getRootMapper(type).getEntityType(), identifier); if (entity != null) { return getRootMapperForEntity(entity.getClass()).<V>createType(entity, entityManager); } } return null; } private EntityMapper getEntityMapperForProperty(Class<? extends AttributedType> attributedType, String propertyName) { for (EntityMapper entityMapper : getMapperFor(attributedType)) { Entry<Property, Property> property = entityMapper.getProperty(attributedType, propertyName); if (property != null) { return entityMapper; } } return null; } private EntityMapper getEntityMapperForProperty(Class<? extends AttributedType> attributedType, Class<? extends Annotation> annotation) { for (EntityMapper entityMapper : this.entityMappers) { Entry<Property, Property> property = entityMapper.getProperty(attributedType, annotation); if (property != null) { return entityMapper; } } return null; } private List<?> findIdentityTypeRelationships(IdentityContext context, Class<? extends Relationship> relationshipType, IdentityType identityType) { List<Object> relationships = new ArrayList<Object>(); for (EntityMapper relationshipMemberMapper : getEntityMappers()) { Entry<Property, Property> property = relationshipMemberMapper.getProperty(RelationshipMember.class); if (property != null) { EntityManager em = getEntityManager(context); CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaQuery<?> criteria = builder.createQuery(relationshipMemberMapper.getEntityType()); Root<?> root = criteria.from(relationshipMemberMapper.getEntityType()); Property<Object> identityTypeProperty = relationshipMemberMapper.getProperty(RelationshipMember.class).getValue(); if (identityTypeProperty.getJavaClass().equals(String.class)) { criteria.where(builder.equal(root.get(identityTypeProperty.getName()), IdentityTypeUtil.formatId(identityType))); } else { criteria.where(builder.equal(root.get(identityTypeProperty.getName()), em.find(identityTypeProperty.getJavaClass(), identityType.getId()))); } List<?> result = em.createQuery(criteria).getResultList(); Property<Object> ownerProperty = relationshipMemberMapper.getProperty(OwnerReference.class).getValue(); for (Object object : result) { relationships.add(ownerProperty.getValue(object)); } } } return relationships; } private <T extends Relationship> T convertToRelationshipType(IdentityContext context, Object relationshipObject) { EntityMapper relationshipTypeMapper = getMapperForEntity(relationshipObject.getClass()); Property typeProperty = relationshipTypeMapper.getTypeProperty(); Object relationshipTypeName = typeProperty.getValue(relationshipObject); Class<? extends AttributedType> relationshipType; try { relationshipType = classForName(relationshipTypeName.toString()); } catch (ClassNotFoundException e) { throw new IdentityManagementException("Could not get type name from entity [" + relationshipObject + "].", e); } EntityMapper relationshipMemberMapper = getEntityMapperForProperty(relationshipType, RelationshipMember.class); Property<Object> identityProperty = relationshipMemberMapper.getProperty(relationshipType, RelationshipMember.class).getValue(); Property<String> descriptorProperty = relationshipMemberMapper.getProperty(relationshipType, RelationshipDescriptor.class).getValue(); EntityManager entityManager = getEntityManager(context); EntityMapper relMapper = getRootMapper(relationshipType); T relationshipInstance = relMapper.createType(relationshipObject, entityManager); boolean isReference = !identityProperty.getJavaClass().equals(String.class); RelationshipReference reference = null; if (!isReference) { reference = new RelationshipReference(relationshipInstance); } for (Object object : findChildRelationships(context, relationshipInstance)) { String descriptor = descriptorProperty.getValue(object).toString(); Property<Object> identityTypeProperty = PropertyQueries.createQuery(relationshipInstance.getClass()) .addCriteria(new NamedPropertyCriteria(descriptor)).getSingleResult(); IdentityType identityType = null; Object identityTypeEntity = identityProperty.getValue(object); if (!isReference) { reference.addIdentityTypeReference(descriptor, identityTypeEntity.toString()); } else { EntityMapper entityMapper = getRootMapperForEntity(identityTypeEntity.getClass()); identityType = entityMapper.createType(identityTypeEntity, entityManager); } identityTypeProperty.setValue(relationshipInstance, identityType); } if (reference != null) { return (T) reference; } else { return relationshipInstance; } } private List<?> findChildRelationships(IdentityContext context, Relationship relationship) { EntityManager em = getEntityManager(context); EntityMapper relationshipMemberMapper = getEntityMapperForProperty(relationship.getClass(), RelationshipMember.class); CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaQuery<?> criteria = builder.createQuery(relationshipMemberMapper.getEntityType()); Root<?> root = criteria.from(relationshipMemberMapper.getEntityType()); List<Predicate> predicates = new ArrayList<Predicate>(); Property ownerProperty = relationshipMemberMapper.getProperty(OwnerReference.class).getValue(); Join<?, ?> join = root.join(ownerProperty.getName()); EntityMapper relationshipMapper = getRootMapper(relationship.getClass()); Property identifierProperty = relationshipMapper.getProperty(Identifier.class).getValue(); predicates.add(builder.equal(join.get(identifierProperty.getName()), relationship.getId())); criteria.where(predicates.toArray(new Predicate[predicates.size()])); return em.createQuery(criteria).getResultList(); } private <T extends CredentialStorage> List<?> findCredentials(IdentityContext context, Account account, Class<T> storageClass) { EntityMapper attributeMapper = getCredentialAttributeMapper(storageClass); EntityManager entityManager = getEntityManager(context); CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery<?> criteria = builder.createQuery(attributeMapper.getEntityType()); Root<?> root = criteria.from(attributeMapper.getEntityType()); List<Predicate> predicates = new ArrayList<Predicate>(); Object agentInstance = getRootEntity(account, entityManager); Property identityTypeProperty = attributeMapper.getProperty(storageClass, OwnerReference.class).getValue(); predicates.add(builder.equal(root.get(identityTypeProperty.getName()), agentInstance)); Property typeProperty = attributeMapper.getProperty(storageClass, CredentialClass.class).getValue(); Property effectiveProperty = attributeMapper.getProperty(storageClass, EffectiveDate.class).getValue(); predicates.add(builder.equal(root.get(typeProperty.getName()), storageClass.getName())); predicates.add(builder.lessThanOrEqualTo(root.<Date>get(effectiveProperty.getName()), new Date())); criteria.where(predicates.toArray(new Predicate[predicates.size()])); criteria.orderBy(builder.desc(root.get(effectiveProperty.getName()))); return entityManager.createQuery(criteria).getResultList(); } private <T extends CredentialStorage> T convertToCredentialStorage(Object entity, Class<T> storageType) { T storage = null; if (entity != null) { EntityMapper credentialMapper = getCredentialAttributeMapper(storageType); try { storage = newInstance(storageType); } catch (Exception e) { throw MESSAGES.instantiationError(storageType, e); } for (EntityMapping entityMapping : credentialMapper.getEntityMappings()) { for (Property property : entityMapping.getProperties().keySet()) { Property mappedProperty = entityMapping.getProperties().get(property); if (!mappedProperty.getAnnotatedElement().isAnnotationPresent(OwnerReference.class)) { property.setValue(storage, mappedProperty.getValue(entity)); } } } } return storage; } private EntityMapper getCredentialAttributeMapper(Class<? extends CredentialStorage> credentialStorageClass) { for (EntityMapper entityMapper : this.entityMappers) { ManagedCredential managedCredential = entityMapper.getEntityType().getAnnotation(ManagedCredential.class); if (managedCredential != null) { if (managedCredential.value().length > 0) { for (Class<?> supportedType : managedCredential.value()) { if (supportedType.equals(credentialStorageClass)) { return entityMapper; } } for (Class<?> supportedType : managedCredential.value()) { if (supportedType.isAssignableFrom(credentialStorageClass)) { return entityMapper; } } } else { return entityMapper; } } } throw new IdentityManagementException("No mapper for for credential storage type [" + credentialStorageClass + "]."); } private void removeChildRelationships(final IdentityContext context, final Relationship attributedType, final EntityManager entityManager) { for (Object child : findChildRelationships(context, (Relationship) attributedType)) { entityManager.remove(child); } } private void removeAssociatedEntities(final AttributedType attributedType, final EntityManager entityManager, final EntityMapper rootMapper) { for (EntityMapper childMapper : getMapperFor(attributedType.getClass())) { if (!childMapper.isRoot()) { for (Object child : rootMapper.getAssociatedEntities(attributedType, childMapper, entityManager)) { entityManager.remove(child); } } } } private EntityMapper getRootMapper(Class<? extends AttributedType> aClass) { return getMapperFor(aClass).get(0); } private void addAttributeQueryPredicates(Class<? extends AttributedType> attributedType, EntityManager entityManager, final CriteriaBuilder cb, final CriteriaQuery<?> cq, final Root from, final List<Predicate> predicates, final AttributeParameter attributeParameter, final Condition condition, final Object[] parameterValues) { int valuesLength = 1; if (condition != null) { if (InCondition.class.isInstance(condition)) { InCondition inCondition = (InCondition) condition; valuesLength = inCondition.getValue().length; } } else { valuesLength = parameterValues.length; } EntityMapper attributeMapper = getAttributeMapper(attributedType); Subquery<?> subQueryOwnerAttributesByValue = cq.subquery(attributeMapper.getEntityType()); Root fromAttributeType = subQueryOwnerAttributesByValue.from(attributeMapper.getEntityType()); Property ownerProperty = attributeMapper.getProperty(Attribute.class, OwnerReference.class).getValue(); String ownerIdentifierPropertyName = getRootMapper(attributedType).getProperty(Identifier.class).getValue().getName(); Path selection; if (String.class.equals(ownerProperty.getJavaClass())) { selection = fromAttributeType.get(ownerProperty.getName()); } else { selection = fromAttributeType.get(ownerProperty.getName()).get(ownerIdentifierPropertyName); } subQueryOwnerAttributesByValue.select(selection); List<Predicate> conjunction = new ArrayList<Predicate>(); Property attributeNameProperty = attributeMapper.getProperty(Attribute.class, AttributeName.class).getValue(); conjunction.add(cb.equal(fromAttributeType.get(attributeNameProperty.getName()), attributeParameter.getName())); Property attributeValueProperty = attributeMapper.getProperty(Attribute.class, AttributeValue.class).getValue(); if (condition == null) { Object[] valuesToSearch = new String[parameterValues.length]; for (int i = 0; i < parameterValues.length; i++) { valuesToSearch[i] = Base64.encodeObject((Serializable) parameterValues[i]); } conjunction.add(fromAttributeType.get(attributeValueProperty.getName()).in((Object[]) valuesToSearch)); } else { addCondition(entityManager, cb, conjunction, condition, attributeValueProperty, fromAttributeType, true); } subQueryOwnerAttributesByValue.where(conjunction.toArray(new Predicate[conjunction.size()])); subQueryOwnerAttributesByValue.groupBy(selection).having(cb.equal(cb.count(selection), valuesLength)); predicates.add(cb.in(from.get(ownerIdentifierPropertyName)).value(subQueryOwnerAttributesByValue)); } private EntityMapper getAttributeMapper(Class<? extends AttributedType> attributedType) { List<EntityMapper> attributeMappers = getAttributeMappers(); if (!attributeMappers.isEmpty()) { boolean supportsType = getConfig().supportsType(attributedType, IdentityOperation.create); // if the store supports the type, we try to find the most specific mapper for its corresponding entity. if (supportsType) { EntityMapper secondaryMapper = null; for (EntityMapper entityMapper : getMapperFor(attributedType)) { for (EntityMapper mapper : attributeMappers) { Class<?> entityType = entityMapper.getEntityType(); EntityMapping mappings = mapper.getMappingsFor(Attribute.class); if (mappings.getOwnerType().equals(entityType)) { return mapper; } else if (mappings.getOwnerType().isAssignableFrom(entityType)) { secondaryMapper = mapper; } } } if (secondaryMapper != null) { return secondaryMapper; } } // as a fallback, we check if the attribute mappers support id-based references for the type. this is specially useful when using a single // attribute entity to store attributes for all types based on their ids. for (EntityMapper mapper : attributeMappers) { EntityMapping mappings = mapper.getMappingsFor(Attribute.class); if (String.class.equals(mappings.getOwnerType())) { return mapper; } } // in this case, the store does not support the type. So the attribute mapping must provide a String-based field to store only references to the type based on the id. if (!supportsType) { throw new IdentityManagementException("The store does not support type [" + attributedType + "]. The attribute mapping must provide a String-based field to reference instances of this type."); } } throw new IdentityManagementException("Could not find attribute mapper for type [" + attributedType + "]."); } private List<EntityMapper> getAttributeMappers() { List<EntityMapper> attributeMappers = new ArrayList<EntityMapper>(); for (EntityMapper entityMapper : this.entityMappers) { if (entityMapper.getProperty(AttributeClass.class) != null) { attributeMappers.add(entityMapper); } } return attributeMappers; } private void storeRelationshipMembers(Relationship relationship, EntityManager entityManager) { Object ownerEntity = getRootEntity(relationship, entityManager); List<Property<IdentityType>> props = PropertyQueries.<IdentityType>createQuery(relationship.getClass()) .addCriteria(new TypedPropertyCriteria(IdentityType.class, MatchOption.SUB_TYPE)).getResultList(); EntityMapper relationshipMemberMapper = getEntityMapperForProperty(relationship.getClass(), RelationshipMember.class); for (Property<IdentityType> prop : props) { Object relationshipIdentity = relationshipMemberMapper.createEntity(); IdentityType identityType = prop.getValue(relationship); if (identityType != null) { Property<Object> identityTypeProperty = relationshipMemberMapper.getProperty(RelationshipMember.class).getValue(); // in this case we hold only the reference to the identity type identifier if (identityTypeProperty.getJavaClass().equals(String.class)) { identityTypeProperty.setValue(relationshipIdentity, IdentityTypeUtil.formatId(identityType)); } else { identityTypeProperty.setValue(relationshipIdentity, getRootEntity(identityType, entityManager)); } Property<Object> descriptorProperty = relationshipMemberMapper.getProperty(RelationshipDescriptor.class).getValue(); Property<Object> ownerProperty = relationshipMemberMapper.getProperty(OwnerReference.class).getValue(); descriptorProperty.setValue(relationshipIdentity, prop.getName()); ownerProperty.setValue(relationshipIdentity, ownerEntity); } entityManager.persist(relationshipIdentity); } } /** * <p> Creates an {@link EntityMapper} for the given mapped entity. This method looks first for the owner * references * in order to have them configured first. The order is important to make sure the entities are created or * updated * in the correct order of dependency. * <p/> * * @param entityType */ private void configureEntityMapper(Class<?> entityType) { EntityMapper entityMapper = new EntityMapper(entityType, this); Entry<Property, Property> ownerProperty = entityMapper.getProperty(OwnerReference.class); if (ownerProperty != null) { Class<?> ownerClass = ownerProperty.getValue().getJavaClass(); // When working with multiple partitions supporting different types, some owner references point to a // String valued mapped property that holds only a reference to the corresponding type. This reference is // usually the id. if (!String.class.equals(ownerClass)) { if (getConfig().getEntityTypes().contains(ownerClass)) { configureEntityMapper(ownerClass); } } } if (entityType.getSuperclass().isAnnotationPresent(IdentityManaged.class)) { configureEntityMapper(entityType.getSuperclass()); } if (!this.entityMappers.contains(entityMapper)) { this.entityMappers.add(entityMapper); } } private EntityManager getEntityManager(IdentityContext context) { EntityManager entityManager = (EntityManager) context.getParameter(INVOCATION_CTX_ENTITY_MANAGER); if (entityManager == null) { throw MESSAGES.storeJpaCouldNotGetEntityManagerFromStoreContext(); } return entityManager; } private void logEntityMappers() { if (JPA_STORE_LOGGER.isDebugEnabled()) { JPA_STORE_LOGGER.debug("Supported EntityMappers: ["); for (EntityMapper entityMapper : this.entityMappers) { JPA_STORE_LOGGER.debugf(" %s: [", entityMapper.getEntityType()); JPA_STORE_LOGGER.debugf(" Is root: %s", entityMapper.isRoot()); JPA_STORE_LOGGER.debugf(" Mappings: ["); for (EntityMapping entityMapping : entityMapper.getEntityMappings()) { JPA_STORE_LOGGER.debugf(" %s: ", entityMapping.getSupportedType()); JPA_STORE_LOGGER.debugf(" Owner Type: %s", entityMapping.getOwnerType()); if (entityMapping.getTypeProperty() != null) { JPA_STORE_LOGGER.debugf(" Has type property: %s", entityMapping.getTypeProperty().getName()); } for (Property property : entityMapping.getProperties().keySet()) { JPA_STORE_LOGGER.debugf(" Property: %s, %s", property.getName(), property.getJavaClass()); Property mappedProperty = entityMapping.getProperties().get(property); if (mappedProperty != null) { StringBuffer propertyAnnotations = new StringBuffer(); for (Annotation annotation : mappedProperty.getAnnotatedElement().getAnnotations()) { if (propertyAnnotations.length() != 0) { propertyAnnotations.append(","); } propertyAnnotations.append(annotation.annotationType()); } JPA_STORE_LOGGER.debugf(" Mapped Property: %s, %s, annotations [%s]", mappedProperty.getName(), mappedProperty.getJavaClass(), propertyAnnotations); } } } JPA_STORE_LOGGER.debugf(" ]"); JPA_STORE_LOGGER.debugf(" ]"); JPA_STORE_LOGGER.debug(" ]"); } JPA_STORE_LOGGER.debug("]"); } } private EntityMapper getPermissionMapperForResource(Class resourceClass) { int score = -1; EntityMapper mapper = null; for (EntityMapper entityMapper: getEntityMappers()) { if (entityMapper.getEntityType().isAnnotationPresent(PermissionManaged.class)) { EntityMapping mapping = entityMapper.getMappingsFor(resourceClass); if (mapping != null) { Class<?> supportedType = mapping.getSupportedType(); if (supportedType.isAssignableFrom(resourceClass)) { int currentScore = 0; Class<?> currentClass = resourceClass; while (!currentClass.equals(supportedType) && !Object.class.equals(currentClass)) { currentScore++; currentClass = currentClass.getSuperclass(); } if (mapper == null || score == -1 || currentScore < score) { score = currentScore; mapper = entityMapper; } } } } } if (mapper == null) { throw MESSAGES.configJpaStoreNoPermissionEntityClassProvided(); } return mapper; } private List<EntityMapper> getPermissionMappers() { List<EntityMapper> mappers = new ArrayList<EntityMapper>(); for (EntityMapper entityMapper: getEntityMappers()) { if (entityMapper.getEntityType().isAnnotationPresent(PermissionManaged.class)) { mappers.add(entityMapper); } } if (mappers == null) { throw MESSAGES.configJpaStoreNoPermissionEntityClassProvided(); } return mappers; } @Override public List<Permission> listPermissions(IdentityContext ctx, Object resource) { return listPermissions(ctx, resource, null); } @Override public List<Permission> listPermissions(IdentityContext ctx, IdentityType identityType) { return listPermissions(ctx, new IdentityPermission(null, identityType, null)); } @Override public List<Permission> listPermissions(IdentityContext ctx, Object resource, String operation) { return listPermissions(ctx, new IdentityPermission(resource, null, operation)); } @Override public List<Permission> listPermissions(IdentityContext ctx, Set<Object> resources, String operation) { List<Permission> perms = new ArrayList<Permission>(); for (Object resource : resources) { perms.addAll(listPermissions(ctx, resource, operation)); } return perms; } @Override public List<Permission> listPermissions(IdentityContext ctx, Class<?> resourceClass, Serializable identifier) { return listPermissions(ctx, resourceClass, identifier, null); } @Override public List<Permission> listPermissions(IdentityContext ctx, Class<?> resourceClass, Serializable identifier, String operation) { return listPermissions(ctx, new IdentityPermission(resourceClass, identifier, null, operation)); } public List<Permission> listPermissions(IdentityContext ctx, IdentityPermission query) { EntityManager em = getEntityManager(ctx); List<EntityMapper> mappers = new ArrayList<EntityMapper>(); Object resource = query.getResource(); Class<?> resourceClass = query.getResourceClass(); Serializable resourceIdentifier = query.getResourceIdentifier(); if (resource != null) { resourceClass = ctx.getPermissionHandlerPolicy().getResourceClass(resource); resourceIdentifier = ctx.getPermissionHandlerPolicy().getIdentifier(resource); } if (resourceClass != null) { mappers.add(getPermissionMapperForResource(resourceClass)); } else { mappers.addAll(getPermissionMappers()); } List<Permission> perms = new ArrayList<Permission>(); for (EntityMapper mapper : mappers) { CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery cq = cb.createQuery(mapper.getEntityType()); Root from = cq.from(mapper.getEntityType()); List<Predicate> predicates = new ArrayList<Predicate>(); // Set the resource class and resource resourceIdentifier predicates Property resourceClassProperty = mapper.getProperty(PermissionResourceClass.class).getValue(); Property resourceIdentifierProperty = mapper.getProperty(PermissionResourceIdentifier.class).getValue(); Property ownerProperty = mapper.getProperty(OwnerReference.class).getValue(); if (resourceClass != null) { predicates.add(cb.equal(from.get(resourceClassProperty.getName()), resourceClass.getName())); } if (resourceIdentifier != null) { predicates.add(cb.equal(from.get(resourceIdentifierProperty.getName()), resourceIdentifier.toString())); } if (query.getAssignee() != null) { IdentityType assignee = query.getAssignee(); // Set the assignee, resource class and resource resourceIdentifier predicates if (String.class.equals(ownerProperty.getBaseType())) { predicates.add(from.get(ownerProperty.getName()).in(assignee.getId(), IdentityTypeUtil.formatId(assignee))); } else { predicates.add(cb.equal(from.get(ownerProperty.getName()), getOwnerEntity(assignee, ownerProperty, em))); } } cq.where(predicates.toArray(new Predicate[predicates.size()])); List results = em.createQuery(cq).getResultList(); for (Object result : results) { Object owner = ownerProperty.getValue(result); IdentityType ownerIdentityType = null; // If the owner value is a String, then it must be an resourceIdentifier value if (String.class.equals(owner.getClass())) { ownerIdentityType = lookupIdentityTypeById(ctx, IdentityType.class, (String) owner); if (ownerIdentityType == null) { // we assume that it is a cross-partition reference ownerIdentityType = new IdentityTypeReference((String) owner); } } else { for (EntityMapper entityMapper : getEntityMappers()) { if (entityMapper.getMappingsFor(IdentityType.class) != null && entityMapper.isRoot()) { IdentityType identityType = entityMapper.<IdentityType>createType(owner, em); if (identityType != null) { ownerIdentityType = identityType; break; } } } } if (ownerIdentityType == null) { throw new IdentityManagementException(String.format( "Could not determine permission assignee [%s] for resource class [%s] with resourceIdentifier [%s]", owner, resourceClass, resourceIdentifier)); } Class<?> actualResourceClass = resourceClass; if (actualResourceClass == null) { try { actualResourceClass = classForName((String) resourceClassProperty.getValue(result)); } catch (ClassNotFoundException e) { throw new IdentityManagementException("Could not load type.", e); } } PermissionOperationSet opSet = new PermissionOperationSet(result, actualResourceClass, mapper); String operation = query.getOperation(); Set<String> operationsToreturn; if (operation != null) { operationsToreturn = asOperationList(operation); } else { operationsToreturn = opSet.getOperations(); } for (String op : operationsToreturn) { for (String operationPermission : opSet.getOperations()) { if (op.equals(operationPermission)) { if (resource != null) { perms.add(new IdentityPermission(resource, ownerIdentityType, op)); } else { perms.add(new IdentityPermission(actualResourceClass, (Serializable) resourceIdentifierProperty .getValue(result), ownerIdentityType, op)); } } } } } } return perms; } private Object lookupPermissionEntity(IdentityContext ctx, EntityMapper mapper, IdentityType assignee, Class<?> resourceClass, Serializable identifier) { EntityManager em = getEntityManager(ctx); CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery cq = cb.createQuery(mapper.getEntityType()); Root from = cq.from(mapper.getEntityType()); List<Predicate> predicates = new ArrayList<Predicate>(); Property resourceClassProperty = mapper.getProperty(PermissionResourceClass.class).getValue(); Property resourceIdentifierProperty = mapper.getProperty(PermissionResourceIdentifier.class).getValue(); Property ownerProperty = mapper.getProperty(OwnerReference.class).getValue(); // Set the assignee, resource class and resource identifier predicates if (String.class.equals(ownerProperty.getBaseType())) { predicates.add(from.get(ownerProperty.getName()).in(assignee.getId(), IdentityTypeUtil.formatId(assignee))); } else { predicates.add(cb.equal(from.get(ownerProperty.getName()), getOwnerEntity(assignee, ownerProperty, em))); } predicates.add(cb.equal(from.get(resourceClassProperty.getName()), resourceClass.getName())); if (identifier != null && !identifier.equals(resourceClass.getName())) { // TODO we need some conversion API to convert identifiers to the correct type predicates.add(cb.equal(from.get(resourceIdentifierProperty.getName()), identifier.toString())); } cq.where(predicates.toArray(new Predicate[predicates.size()])); Query query = em.createQuery(cq); query.setMaxResults(1); try { return query.getSingleResult(); } catch (NoResultException ex) { return null; } } @Override public boolean grantPermission(IdentityContext context, IdentityType assignee, Object resource, String operation) { EntityManager em = getEntityManager(context); Class<?> resourceClass = context.getPermissionHandlerPolicy().getResourceClass(resource); Serializable resourceIdentifier = context.getPermissionHandlerPolicy().getIdentifier(resource); if (resourceIdentifier == null) { throw new IdentityManagementException(String.format( "No identifier value could be generated for resource [%s]", resource)); } EntityMapper mapper = getPermissionMapperForResource(resourceClass); // We first attempt to lookup an existing entity Object entity = lookupPermissionEntity(context, mapper, assignee, resourceClass, resourceIdentifier); // If there is no existing entity we create a new one if (entity == null) { Property resourceClassProperty = mapper.getProperty(PermissionResourceClass.class).getValue(); Property resourceIdentifierProperty = mapper.getProperty(PermissionResourceIdentifier.class).getValue(); Property ownerProperty = mapper.getProperty(OwnerReference.class).getValue(); try { entity = mapper.getEntityType().newInstance(); // Set the assignee property - this will either be a String, or a reference to an // identity entity if (String.class.equals(ownerProperty.getBaseType())) { ownerProperty.setValue(entity, IdentityTypeUtil.formatId(assignee)); } else { Object identityEntity = getOwnerEntity(assignee, ownerProperty, em); ownerProperty.setValue(entity, identityEntity); } // Set the resource class resourceClassProperty.setValue(entity, context.getPermissionHandlerPolicy().getResourceClass(resource).getName()); // TODO this is a nasty hack, we still need to support type conversion between a multitude of types resourceIdentifierProperty.setValue(entity, resourceIdentifier.toString()); PermissionOperationSet operationSet = new PermissionOperationSet(entity, resourceClass, mapper); operationSet.appendOperation(operation); em.persist(entity); return true; } catch (Exception ex) { throw new IdentityManagementException("Error persisting permission", ex); } } else { PermissionOperationSet operationSet = new PermissionOperationSet(entity, resourceClass, mapper); operationSet.appendOperation(operation); em.merge(entity); return true; } } protected class PermissionOperationSet { private EntityMapper mapper; private AllowedOperations perms; private Object entity; private Class resourceClass; public PermissionOperationSet(Object entity, Class resourceClass, EntityMapper mapper) { this.entity = entity; this.mapper = mapper; this.resourceClass = resourceClass; this.perms = (AllowedOperations) resourceClass.getAnnotation(AllowedOperations.class); } public void appendOperation(String operation) { adjustOperation(operation, true); } public void removeOperation(String operation) { adjustOperation(operation, false); } private String adjustCSVOperation(String operations, String operation, boolean mode) { String operationsCSV; if (mode) { operationsCSV = PermissionUtil.addOperation(operations, operation); } else { operationsCSV = PermissionUtil.removeOperation(operations, operation); } return operationsCSV; } public Set<String> getOperations() { Object opValue = mapper.getProperty(PermissionOperation.class).getValue().getValue(entity); Set<String> operations = new HashSet<String>(); // Determine how the permission operations are stored - first check if bitmasks are used if (perms != null) { try { // Convert the operations value to a long for convenience long ops = opValue != null ? Long.valueOf(opValue.toString()) : 0; for (AllowedOperation o : perms.value()) { if (o.mask() > 0) { if ((o.mask() & ops) != 0) { operations.add(o.value()); } } } return operations; } catch (NumberFormatException ex) { // Do nothing, revert to default behaviour below } } // Operations are stored as a comma separated value for (String op : ((String) opValue).split(",")) { if (!isNullOrEmpty(op)) { operations.add(op); } } return operations; } private void adjustOperation(String operation, boolean mode) { Object operations = mapper.getProperty(PermissionOperation.class).getValue().getValue(entity); if (operations == null) { operations = ""; } Object newOperations = operation; // Determine how the permission operations are stored - first check if bitmasks are used if (perms != null && perms.value().length > 0) { AllowedOperation perm = null; long ops = operations == null || isNullOrEmpty(operations.toString()) ? 0 : Long.valueOf(operations.toString()); for (String op : asOperationList(operation)) { for (AllowedOperation o : perms.value()) { if (o.value().equals(op)) { perm = o; break; } } if (perm == null) { // Trying to set an operation value that isn't defined - throw an exception throw new IllegalArgumentException(String.format( "Attempted to set illegal permission operation [%s] for resource [%s]", op, resourceClass)); } // Check if there is a bitmask value for the operation if (perm != null && perm.mask() > 0) { // Convert the operations value to a long for convenience if (mode) { ops |= perm.mask(); } else { ops ^= perm.mask(); } } newOperations = ops; } } else { newOperations = adjustCSVOperation(operations.toString(), newOperations.toString(), mode); } mapper.getProperty(PermissionOperation.class).getValue().setValue(entity, newOperations.toString()); } } @Override public boolean revokePermission(IdentityContext context, IdentityType assignee, Object resource, String operation) { EntityManager em = getEntityManager(context); List<EntityMapper> mappers = new ArrayList<EntityMapper>(); Class<?> resourceClass = context.getPermissionHandlerPolicy().getResourceClass(resource); Serializable resourceIdentifier = context.getPermissionHandlerPolicy().getIdentifier(resource); if (resourceClass != null) { mappers.add(getPermissionMapperForResource(resourceClass)); } else { mappers.addAll(getPermissionMappers()); } for (EntityMapper mapper : mappers) { // We first attempt to lookup an existing entity Object entity = lookupPermissionEntity(context, mapper, assignee, resourceClass, resourceIdentifier); // If there's no entity found then there's nothing to do if (entity != null) { PermissionOperationSet operationSet = new PermissionOperationSet(entity, resourceClass, mapper); operationSet.removeOperation(operation); Set<String> operations = operationSet.getOperations(); if (operations.isEmpty()) { em.remove(entity); } else { em.merge(entity); } return true; } } return false; } @Override public void revokeAllPermissions(IdentityContext ctx, Object resource) { EntityManager em = getEntityManager(ctx); EntityMapper mapper = getPermissionMapperForResource(resource.getClass()); Property resourceClassProperty = mapper.getProperty(PermissionResourceClass.class).getValue(); Property resourceIdentifierProperty = mapper.getProperty(PermissionResourceIdentifier.class).getValue(); CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery cq = cb.createQuery(mapper.getEntityType()); Root from = cq.from(mapper.getEntityType()); List<Predicate> predicates = new ArrayList<Predicate>(); // Set the resource class and resource identifier predicates predicates.add(cb.equal(from.get(resourceClassProperty.getName()), ctx.getPermissionHandlerPolicy().getResourceClass(resource).getName())); predicates.add(cb.equal(from.get(resourceIdentifierProperty.getName()), ctx.getPermissionHandlerPolicy().getIdentifier(resource).toString())); cq.where(predicates.toArray(new Predicate[predicates.size()])); List results = em.createQuery(cq).getResultList(); for (Object result : results) { em.remove(result); } } private void validateConfiguration() { Set<Class<? extends AttributedType>> supportedTypes = getConfig().getSupportedTypes().keySet(); validateTypeMapping(supportedTypes); validateAttributeMapping(); validateCredentialMapping(); } private void validateCredentialMapping() { if (getConfig().supportsCredential()) { for (EntityMapper entityMapper : getEntityMappers()) { ManagedCredential managedCredential = entityMapper.getEntityType().getAnnotation(ManagedCredential.class); if (managedCredential != null) { checkIfAnnotationIsDefinedForCredential(entityMapper, CredentialClass.class); checkIfAnnotationIsDefinedForCredential(entityMapper, EffectiveDate.class); checkIfAnnotationIsDefinedForCredential(entityMapper, ExpiryDate.class); return; } } throw MESSAGES.configJpaStoreMappedNoCredentialStorageMappingFound(); } } private void validateAttributeMapping() { if (getConfig().supportsAttribute()) { for (EntityMapper entityMapper : getEntityMappers()) { if (entityMapper.getProperty(AttributeClass.class) != null) { checkIfAnnotationIsDefinedForAttribute(entityMapper, AttributeName.class); checkIfAnnotationIsDefinedForAttribute(entityMapper, AttributeValue.class); checkIfAnnotationIsDefinedForAttribute(entityMapper, OwnerReference.class); return; } } throw MESSAGES.configJpaStoreMappedNoAttributeMappingFound(); } } private void validateTypeMapping(Set<Class<? extends AttributedType>> supportedTypes) { for (Class<? extends AttributedType> supportedType : supportedTypes) { // we only validate user-defined types if (Relationship.class.equals(supportedType) || Partition.class.equals(supportedType) || IdentityType.class.equals(supportedType) || Account.class.equals(supportedType)) { continue; } checkIfAnnotationIsDefined(supportedType, Identifier.class); if (Partition.class.isAssignableFrom(supportedType)) { checkIfAnnotationIsDefined(supportedType, PartitionClass.class); } if (IdentityType.class.isAssignableFrom(supportedType)) { checkIfAnnotationIsDefined(supportedType, IdentityClass.class); if (getConfig().supportsPartition()) { checkIfAnnotationIsDefined(supportedType, OwnerReference.class); } } if (Relationship.class.isAssignableFrom(supportedType)) { checkIfAnnotationIsDefined(supportedType, RelationshipClass.class); checkIfAnnotationIsDefined(supportedType, RelationshipDescriptor.class); checkIfAnnotationIsDefined(supportedType, RelationshipMember.class); checkIfAnnotationIsDefined(supportedType, OwnerReference.class); } } } /** * <p>Checks if the given {@link java.lang.annotation.Annotation} was define during the mapping of a specific * {@link org.picketlink.idm.model.AttributedType}.</p> * * @param attributedType * @param annotation * * @throws org.picketlink.idm.config.SecurityConfigurationException If not annotation was defined to map the type. */ private void checkIfAnnotationIsDefined(Class<? extends AttributedType> attributedType, Class<? extends Annotation> annotation) throws SecurityConfigurationException { if (getEntityMapperForProperty(attributedType, annotation) == null) { throw MESSAGES.configJpaStoreRequiredMappingAnnotationForAttributedType(attributedType, annotation); } } /** * <p>Checks if the given {@link java.lang.annotation.Annotation} was define during the mapping of a specific * {@link org.picketlink.idm.model.Attribute} mapping.</p> * * @param mapper * @param annotation * * @throws org.picketlink.idm.config.SecurityConfigurationException If not annotation was defined to map the type. */ private void checkIfAnnotationIsDefinedForAttribute(EntityMapper mapper, Class<? extends Annotation> annotation) throws SecurityConfigurationException { if (mapper.getProperty(annotation) == null) { throw MESSAGES.configJpaStoreRequiredMappingAnnotation(mapper.getEntityType(), annotation); } } /** * <p>Checks if the given {@link java.lang.annotation.Annotation} was define during the mapping of a specific * {@link org.picketlink.idm.credential.storage.CredentialStorage} mapping.</p> * * @param mapper * @param annotation * * @throws org.picketlink.idm.config.SecurityConfigurationException If not annotation was defined to map the type. */ private void checkIfAnnotationIsDefinedForCredential(EntityMapper mapper, Class<? extends Annotation> annotation) throws SecurityConfigurationException { if (mapper.getProperty(annotation) == null) { throw MESSAGES.configJpaStoreRequiredMappingAnnotation(mapper.getEntityType(), annotation); } } }