| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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.apache.syncope.core.persistence.jpa.dao; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Optional; |
| import javax.persistence.NoResultException; |
| import javax.persistence.TypedQuery; |
| import org.apache.commons.lang3.StringUtils; |
| import org.apache.syncope.common.lib.SyncopeConstants; |
| import org.apache.syncope.core.persistence.api.dao.MalformedPathException; |
| import org.apache.syncope.core.persistence.api.dao.RealmDAO; |
| import org.apache.syncope.core.persistence.api.dao.RoleDAO; |
| import org.apache.syncope.core.persistence.api.entity.Implementation; |
| import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy; |
| import org.apache.syncope.core.persistence.api.entity.Realm; |
| import org.apache.syncope.core.persistence.api.entity.policy.AccessPolicy; |
| import org.apache.syncope.core.persistence.api.entity.policy.AttrReleasePolicy; |
| import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy; |
| import org.apache.syncope.core.persistence.api.entity.policy.Policy; |
| import org.apache.syncope.core.persistence.api.entity.policy.ProvisioningPolicy; |
| import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource; |
| import org.apache.syncope.core.persistence.jpa.entity.JPARealm; |
| import org.springframework.transaction.annotation.Transactional; |
| import org.apache.syncope.core.persistence.api.entity.policy.AuthPolicy; |
| |
| public class JPARealmDAO extends AbstractDAO<Realm> implements RealmDAO { |
| |
| protected final RoleDAO roleDAO; |
| |
| public JPARealmDAO(final RoleDAO roleDAO) { |
| this.roleDAO = roleDAO; |
| } |
| |
| @Override |
| public Realm getRoot() { |
| TypedQuery<Realm> query = entityManager().createQuery( |
| "SELECT e FROM " + JPARealm.class.getSimpleName() + " e WHERE e.parent IS NULL", Realm.class); |
| |
| Realm result = null; |
| try { |
| result = query.getSingleResult(); |
| } catch (NoResultException e) { |
| LOG.debug("Root realm not found", e); |
| } |
| |
| return result; |
| } |
| |
| @Transactional(readOnly = true) |
| @Override |
| public Realm find(final String key) { |
| return entityManager().find(JPARealm.class, key); |
| } |
| |
| @Transactional(readOnly = true) |
| @Override |
| public Realm findByFullPath(final String fullPath) { |
| if (SyncopeConstants.ROOT_REALM.equals(fullPath)) { |
| return getRoot(); |
| } |
| |
| if (StringUtils.isBlank(fullPath) || !PATH_PATTERN.matcher(fullPath).matches()) { |
| throw new MalformedPathException(fullPath); |
| } |
| |
| Realm root = getRoot(); |
| if (root == null) { |
| return null; |
| } |
| |
| Realm current = root; |
| for (final String pathElement : fullPath.substring(1).split("/")) { |
| Optional<Realm> first = findChildren(current).stream(). |
| filter(realm -> pathElement.equals(realm.getName())).findFirst(); |
| if (first.isPresent()) { |
| current = first.get(); |
| } else { |
| return null; |
| } |
| } |
| return current; |
| } |
| |
| private <T extends Policy> List<Realm> findSamePolicyChildren(final Realm realm, final T policy) { |
| List<Realm> result = new ArrayList<>(); |
| |
| findChildren(realm).stream(). |
| filter(child -> (policy instanceof AccountPolicy |
| && child.getAccountPolicy() == null || policy.equals(child.getAccountPolicy())) |
| || (policy instanceof PasswordPolicy |
| && child.getPasswordPolicy() == null || policy.equals(child.getPasswordPolicy()))). |
| forEach(child -> { |
| result.add(child); |
| result.addAll(findSamePolicyChildren(child, policy)); |
| }); |
| |
| return result; |
| } |
| |
| @Override |
| public List<Realm> findByName(final String name) { |
| TypedQuery<Realm> query = entityManager().createQuery("SELECT e FROM " + JPARealm.class.getSimpleName() + " e " |
| + "WHERE e.name=:name", Realm.class); |
| query.setParameter("name", name); |
| |
| return query.getResultList(); |
| } |
| |
| @Override |
| public List<Realm> findByResource(final ExternalResource resource) { |
| TypedQuery<Realm> query = entityManager().createQuery("SELECT e FROM " + JPARealm.class.getSimpleName() + " e " |
| + "WHERE :resource MEMBER OF e.resources", Realm.class); |
| query.setParameter("resource", resource); |
| |
| return query.getResultList(); |
| } |
| |
| @Override |
| public List<Realm> findMatching(final String keyword) { |
| TypedQuery<Realm> query = entityManager().createQuery("SELECT e FROM " + JPARealm.class.getSimpleName() + " e " |
| + "WHERE e.name LIKE :keyword", Realm.class); |
| query.setParameter("keyword", keyword); |
| |
| return query.getResultList(); |
| } |
| |
| @Override |
| public <T extends Policy> List<Realm> findByPolicy(final T policy) { |
| if (ProvisioningPolicy.class.isAssignableFrom(policy.getClass())) { |
| return Collections.<Realm>emptyList(); |
| } |
| String policyColumn = null; |
| if (policy instanceof AccountPolicy) { |
| policyColumn = "accountPolicy"; |
| } else if (policy instanceof PasswordPolicy) { |
| policyColumn = "passwordPolicy"; |
| } else if (policy instanceof AuthPolicy) { |
| policyColumn = "authPolicy"; |
| } else if (policy instanceof AccessPolicy) { |
| policyColumn = "accessPolicy"; |
| } else if (policy instanceof AttrReleasePolicy) { |
| policyColumn = "attrReleasePolicy"; |
| } |
| |
| TypedQuery<Realm> query = entityManager().createQuery( |
| "SELECT e FROM " + JPARealm.class.getSimpleName() + " e WHERE e." |
| + policyColumn + "=:policy", Realm.class); |
| query.setParameter("policy", policy); |
| |
| List<Realm> result = new ArrayList<>(); |
| query.getResultList().stream().map(realm -> { |
| result.add(realm); |
| return realm; |
| }).forEachOrdered(realm -> result.addAll(findSamePolicyChildren(realm, policy))); |
| |
| return result; |
| } |
| |
| @Override |
| public List<Realm> findByLogicActions(final Implementation logicActions) { |
| TypedQuery<Realm> query = entityManager().createQuery( |
| "SELECT e FROM " + JPARealm.class.getSimpleName() + " e " |
| + "WHERE :logicActions MEMBER OF e.actions", Realm.class); |
| query.setParameter("logicActions", logicActions); |
| |
| return query.getResultList(); |
| } |
| |
| private static void findAncestors(final List<Realm> result, final Realm realm) { |
| if (realm.getParent() != null && !result.contains(realm.getParent())) { |
| result.add(realm.getParent()); |
| findAncestors(result, realm.getParent()); |
| } |
| } |
| |
| @Override |
| public List<Realm> findAncestors(final Realm realm) { |
| List<Realm> result = new ArrayList<>(); |
| result.add(realm); |
| findAncestors(result, realm); |
| return result; |
| } |
| |
| @Override |
| public List<Realm> findChildren(final Realm realm) { |
| TypedQuery<Realm> query = entityManager().createQuery( |
| "SELECT e FROM " + JPARealm.class.getSimpleName() + " e WHERE e.parent=:realm", Realm.class); |
| query.setParameter("realm", realm); |
| |
| return query.getResultList(); |
| } |
| |
| private void findDescendants(final List<Realm> result, final Realm realm) { |
| result.add(realm); |
| List<Realm> children = findChildren(realm); |
| if (children != null) { |
| children.forEach(child -> findDescendants(result, child)); |
| } |
| } |
| |
| @Override |
| public List<Realm> findDescendants(final Realm realm) { |
| List<Realm> result = new ArrayList<>(); |
| findDescendants(result, realm); |
| return result; |
| } |
| |
| @Transactional(readOnly = true) |
| @Override |
| public List<Realm> findAll() { |
| return findDescendants(getRoot()); |
| } |
| |
| @Override |
| public Realm save(final Realm realm) { |
| return entityManager().merge(realm); |
| } |
| |
| @Override |
| public void delete(final Realm realm) { |
| findDescendants(realm).forEach(toBeDeleted -> { |
| roleDAO.findByRealm(toBeDeleted).forEach(role -> role.getRealms().remove(toBeDeleted)); |
| |
| toBeDeleted.setParent(null); |
| |
| entityManager().remove(toBeDeleted); |
| }); |
| } |
| |
| @Override |
| public void delete(final String key) { |
| Realm realm = find(key); |
| if (realm == null) { |
| return; |
| } |
| |
| delete(realm); |
| } |
| } |