| // 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 com.cloud.domain.dao; | |
| import java.sql.PreparedStatement; | |
| import java.sql.ResultSet; | |
| import java.sql.SQLException; | |
| import java.util.HashSet; | |
| import java.util.List; | |
| import java.util.Set; | |
| import javax.ejb.Local; | |
| import org.apache.log4j.Logger; | |
| import org.springframework.stereotype.Component; | |
| import com.cloud.domain.Domain; | |
| import com.cloud.domain.DomainVO; | |
| import com.cloud.utils.db.DB; | |
| import com.cloud.utils.db.GenericDaoBase; | |
| import com.cloud.utils.db.GenericSearchBuilder; | |
| import com.cloud.utils.db.SearchBuilder; | |
| import com.cloud.utils.db.SearchCriteria; | |
| import com.cloud.utils.db.TransactionLegacy; | |
| @Component | |
| @Local(value = {DomainDao.class}) | |
| public class DomainDaoImpl extends GenericDaoBase<DomainVO, Long> implements DomainDao { | |
| private static final Logger s_logger = Logger.getLogger(DomainDaoImpl.class); | |
| protected SearchBuilder<DomainVO> DomainNameLikeSearch; | |
| protected SearchBuilder<DomainVO> ParentDomainNameLikeSearch; | |
| protected SearchBuilder<DomainVO> DomainPairSearch; | |
| protected SearchBuilder<DomainVO> ImmediateChildDomainSearch; | |
| protected SearchBuilder<DomainVO> FindAllChildrenSearch; | |
| protected GenericSearchBuilder<DomainVO, Long> FindIdsOfAllChildrenSearch; | |
| protected SearchBuilder<DomainVO> AllFieldsSearch; | |
| public DomainDaoImpl() { | |
| DomainNameLikeSearch = createSearchBuilder(); | |
| DomainNameLikeSearch.and("name", DomainNameLikeSearch.entity().getName(), SearchCriteria.Op.LIKE); | |
| DomainNameLikeSearch.done(); | |
| ParentDomainNameLikeSearch = createSearchBuilder(); | |
| ParentDomainNameLikeSearch.and("name", ParentDomainNameLikeSearch.entity().getName(), SearchCriteria.Op.LIKE); | |
| ParentDomainNameLikeSearch.and("parent", ParentDomainNameLikeSearch.entity().getName(), SearchCriteria.Op.EQ); | |
| ParentDomainNameLikeSearch.done(); | |
| DomainPairSearch = createSearchBuilder(); | |
| DomainPairSearch.and("id", DomainPairSearch.entity().getId(), SearchCriteria.Op.IN); | |
| DomainPairSearch.done(); | |
| ImmediateChildDomainSearch = createSearchBuilder(); | |
| ImmediateChildDomainSearch.and("parent", ImmediateChildDomainSearch.entity().getParent(), SearchCriteria.Op.EQ); | |
| ImmediateChildDomainSearch.done(); | |
| FindAllChildrenSearch = createSearchBuilder(); | |
| FindAllChildrenSearch.and("path", FindAllChildrenSearch.entity().getPath(), SearchCriteria.Op.LIKE); | |
| FindAllChildrenSearch.and("id", FindAllChildrenSearch.entity().getId(), SearchCriteria.Op.NEQ); | |
| FindAllChildrenSearch.done(); | |
| FindIdsOfAllChildrenSearch = createSearchBuilder(Long.class); | |
| FindIdsOfAllChildrenSearch.selectFields(FindIdsOfAllChildrenSearch.entity().getId()); | |
| FindIdsOfAllChildrenSearch.and("path", FindIdsOfAllChildrenSearch.entity().getPath(), SearchCriteria.Op.LIKE); | |
| FindIdsOfAllChildrenSearch.done(); | |
| AllFieldsSearch = createSearchBuilder(); | |
| AllFieldsSearch.and("name", AllFieldsSearch.entity().getName(), SearchCriteria.Op.EQ); | |
| AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), SearchCriteria.Op.EQ); | |
| AllFieldsSearch.and("owner", AllFieldsSearch.entity().getAccountId(), SearchCriteria.Op.EQ); | |
| AllFieldsSearch.and("path", AllFieldsSearch.entity().getPath(), SearchCriteria.Op.EQ); | |
| AllFieldsSearch.and("parent", AllFieldsSearch.entity().getParent(), SearchCriteria.Op.EQ); | |
| AllFieldsSearch.done(); | |
| } | |
| private static String allocPath(DomainVO parentDomain, String name) { | |
| String parentPath = parentDomain.getPath(); | |
| return parentPath + name + "/"; | |
| } | |
| @Override | |
| public synchronized DomainVO create(DomainVO domain) { | |
| // make sure domain name is valid | |
| String domainName = domain.getName(); | |
| if (domainName != null) { | |
| if (domainName.contains("/")) { | |
| throw new IllegalArgumentException("Domain name contains one or more invalid characters. Please enter a name without '/' characters."); | |
| } | |
| } else { | |
| throw new IllegalArgumentException("Domain name is null. Please specify a valid domain name."); | |
| } | |
| long parent = Domain.ROOT_DOMAIN; | |
| if (domain.getParent() != null && domain.getParent().longValue() >= Domain.ROOT_DOMAIN) { | |
| parent = domain.getParent().longValue(); | |
| } | |
| DomainVO parentDomain = findById(parent); | |
| if (parentDomain == null) { | |
| s_logger.error("Unable to load parent domain: " + parent); | |
| return null; | |
| } | |
| TransactionLegacy txn = TransactionLegacy.currentTxn(); | |
| try { | |
| txn.start(); | |
| parentDomain = this.lockRow(parent, true); | |
| if (parentDomain == null) { | |
| s_logger.error("Unable to lock parent domain: " + parent); | |
| return null; | |
| } | |
| domain.setPath(allocPath(parentDomain, domain.getName())); | |
| domain.setLevel(parentDomain.getLevel() + 1); | |
| parentDomain.setNextChildSeq(parentDomain.getNextChildSeq() + 1); // FIXME: remove sequence number? | |
| parentDomain.setChildCount(parentDomain.getChildCount() + 1); | |
| persist(domain); | |
| update(parentDomain.getId(), parentDomain); | |
| txn.commit(); | |
| return domain; | |
| } catch (Exception e) { | |
| s_logger.error("Unable to create domain due to " + e.getMessage(), e); | |
| txn.rollback(); | |
| return null; | |
| } | |
| } | |
| @Override | |
| @DB | |
| public boolean remove(Long id) { | |
| // check for any active users / domains assigned to the given domain id and don't remove the domain if there are any | |
| if (id != null && id.longValue() == Domain.ROOT_DOMAIN) { | |
| s_logger.error("Can not remove domain " + id + " as it is ROOT domain"); | |
| return false; | |
| } | |
| DomainVO domain = findById(id); | |
| if (domain == null) { | |
| s_logger.error("Unable to remove domain as domain " + id + " no longer exists"); | |
| return false; | |
| } | |
| if (domain.getParent() == null) { | |
| s_logger.error("Invalid domain " + id + ", orphan?"); | |
| return false; | |
| } | |
| String sql = "SELECT * from account where domain_id = " + id + " and removed is null"; | |
| String sql1 = "SELECT * from domain where parent = " + id + " and removed is null"; | |
| boolean success = false; | |
| TransactionLegacy txn = TransactionLegacy.currentTxn(); | |
| try { | |
| txn.start(); | |
| DomainVO parentDomain = super.lockRow(domain.getParent(), true); | |
| if (parentDomain == null) { | |
| s_logger.error("Unable to load parent domain: " + domain.getParent()); | |
| return false; | |
| } | |
| PreparedStatement stmt = txn.prepareAutoCloseStatement(sql); | |
| ResultSet rs = stmt.executeQuery(); | |
| if (rs.next()) { | |
| return false; | |
| } | |
| stmt = txn.prepareAutoCloseStatement(sql1); | |
| rs = stmt.executeQuery(); | |
| if (rs.next()) { | |
| return false; | |
| } | |
| parentDomain.setChildCount(parentDomain.getChildCount() - 1); | |
| update(parentDomain.getId(), parentDomain); | |
| success = super.remove(id); | |
| txn.commit(); | |
| } catch (SQLException ex) { | |
| success = false; | |
| s_logger.error("error removing domain: " + id, ex); | |
| txn.rollback(); | |
| } | |
| return success; | |
| } | |
| @Override | |
| public DomainVO findDomainByPath(String domainPath) { | |
| SearchCriteria<DomainVO> sc = createSearchCriteria(); | |
| sc.addAnd("path", SearchCriteria.Op.EQ, domainPath); | |
| return findOneBy(sc); | |
| } | |
| @Override | |
| public DomainVO findImmediateChildForParent(Long parentId) { | |
| SearchCriteria<DomainVO> sc = ImmediateChildDomainSearch.create(); | |
| sc.setParameters("parent", parentId); | |
| return (listBy(sc).size() > 0 ? listBy(sc).get(0) : null);//may need to revisit for multiple children case | |
| } | |
| @Override | |
| public List<DomainVO> findImmediateChildrenForParent(Long parentId) { | |
| SearchCriteria<DomainVO> sc = ImmediateChildDomainSearch.create(); | |
| sc.setParameters("parent", parentId); | |
| return listBy(sc); | |
| } | |
| @Override | |
| public List<DomainVO> findAllChildren(String path, Long parentId) { | |
| SearchCriteria<DomainVO> sc = FindAllChildrenSearch.create(); | |
| sc.setParameters("path", path + "%"); | |
| sc.setParameters("id", parentId); | |
| return listBy(sc); | |
| } | |
| @Override | |
| public List<Long> getDomainChildrenIds(String path) { | |
| SearchCriteria<Long> sc = FindIdsOfAllChildrenSearch.create(); | |
| sc.setParameters("path", path + "%"); | |
| return customSearch(sc, null); | |
| } | |
| @Override | |
| public boolean isChildDomain(Long parentId, Long childId) { | |
| if ((parentId == null) || (childId == null)) { | |
| return false; | |
| } | |
| if (parentId.equals(childId)) { | |
| return true; | |
| } | |
| boolean result = false; | |
| SearchCriteria<DomainVO> sc = DomainPairSearch.create(); | |
| sc.setParameters("id", parentId, childId); | |
| List<DomainVO> domainPair = listBy(sc); | |
| if ((domainPair != null) && (domainPair.size() == 2)) { | |
| DomainVO d1 = domainPair.get(0); | |
| DomainVO d2 = domainPair.get(1); | |
| if (d1.getId() == parentId) { | |
| result = d2.getPath().startsWith(d1.getPath()); | |
| } else { | |
| result = d1.getPath().startsWith(d2.getPath()); | |
| } | |
| } | |
| return result; | |
| } | |
| @Override | |
| public List<DomainVO> findInactiveDomains() { | |
| SearchCriteria<DomainVO> sc = AllFieldsSearch.create(); | |
| sc.setParameters("state", Domain.State.Inactive); | |
| return listBy(sc); | |
| } | |
| @Override | |
| public Set<Long> getDomainParentIds(long domainId) { | |
| Set<Long> parentDomains = new HashSet<Long>(); | |
| Domain domain = findById(domainId); | |
| if (domain != null) { | |
| parentDomains.add(domain.getId()); | |
| while (domain.getParent() != null) { | |
| domain = findById(domain.getParent()); | |
| parentDomains.add(domain.getId()); | |
| } | |
| } | |
| return parentDomains; | |
| } | |
| } |