org.hyperic.hq.authz.server.session.ResourceDAO.java Source code

Java tutorial

Introduction

Here is the source code for org.hyperic.hq.authz.server.session.ResourceDAO.java

Source

/*
 * NOTE: This copyright does *not* cover user programs that use HQ
 * program services by normal system calls through the application
 * program interfaces provided as part of the Hyperic Plug-in Development
 * Kit or the Hyperic Client Development Kit - this is merely considered
 * normal use of the program, and does *not* fall under the heading of
 * "derived work".
 *
 * Copyright (C) [2004-2008], Hyperic, Inc.
 * This file is part of HQ.
 *
 * HQ is free software; you can redistribute it and/or modify
 * it under the terms version 2 of the GNU General Public License as
 * published by the Free Software Foundation. This program is distributed
 * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA.
 */

package org.hyperic.hq.authz.server.session;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.FlushMode;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hyperic.hibernate.PageInfo;
import org.hyperic.hibernate.dialect.HQDialect;
import org.hyperic.hq.appdef.server.session.Server;
import org.hyperic.hq.appdef.shared.ServerManager;
import org.hyperic.hq.appdef.shared.ServerNotFoundException;
import org.hyperic.hq.authz.shared.AuthzConstants;
import org.hyperic.hq.authz.shared.EdgePermCheck;
import org.hyperic.hq.authz.shared.PermissionManager;
import org.hyperic.hq.context.Bootstrap;
import org.hyperic.hq.dao.HibernateDAO;
import org.hyperic.hq.measurement.server.session.MonitorableType;
import org.hyperic.util.pager.PageControl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository
public class ResourceDAO extends HibernateDAO<Resource> {
    private Log _log = LogFactory.getLog(ResourceDAO.class);

    private PermissionManager permissionManager;

    @Autowired
    public ResourceDAO(SessionFactory f, PermissionManager permissionManager) {
        super(Resource.class, f);
        this.permissionManager = permissionManager;
    }

    Resource create(ResourceType type, Resource prototype, String name, AuthzSubject creator, Integer instanceId,
            boolean system) {
        Resource resource = createPrivate(type, prototype, name, creator, instanceId, system);

        /* add it to the root resource group */
        // TODO resolve circular dependencies to remove Bootstrap
        ResourceGroupDAO resourceGroupDAO = Bootstrap.getBean(ResourceGroupDAO.class);
        ResourceGroup authzGroup = resourceGroupDAO.findRootGroup();
        resourceGroupDAO.addMembers(authzGroup, Collections.singleton(resource));

        return resource;
    }

    Resource createPrivate(ResourceType type, Resource prototype, String name, AuthzSubject creator,
            Integer instanceId, boolean system) {
        if (type == null) {
            throw new IllegalArgumentException("ResourceType not set");
        }
        Resource resource = new Resource(type, prototype, name, creator, instanceId, system);

        save(resource);

        // Need to flush so that later permission checking can succeed
        getSession().flush();

        return resource;
    }

    public Resource findRootResource() {
        return findById(AuthzConstants.rootResourceId);
    }

    public void remove(Resource entity) {
        // need this to ensure that the optimistic locking doesn't fail
        entity.markDirty();
        super.remove(entity);
    }

    public boolean isOwner(Resource entity, Integer possibleOwner) {
        boolean is = false;

        if (possibleOwner == null) {
            _log.error("possible Owner is NULL. " + "This is probably not what you want.");
            /* XXX throw exception instead */
        } else {
            /* overlord owns every thing */
            if (is = possibleOwner.equals(AuthzConstants.overlordId) == false) {
                if (_log.isDebugEnabled() && possibleOwner != null) {
                    _log.debug("User is " + possibleOwner + " owner is " + entity.getOwner().getId());
                }
                is = (possibleOwner.equals(entity.getOwner().getId()));
            }
        }
        return is;
    }

    public Resource findByInstanceId(ResourceType type, Integer id) {
        return findByInstanceId(type.getId(), id);
    }

    @SuppressWarnings("unchecked")
    List<Resource> findResourcesOfType(int typeId, PageInfo pInfo) {
        String sql = "from Resource r where resourceType.id = :typeId ";
        ResourceSortField sort = (ResourceSortField) pInfo.getSort();

        sql += " order by " + sort.getSortString("r") + (pInfo.isAscending() ? "" : " DESC");

        return pInfo.pageResults(getSession().createQuery(sql).setInteger("typeId", typeId)).list();
    }

    public Resource findByInstanceId(Integer typeId, Integer id) {
        // Resource table is often updated. Manage the instance id and type
        // to resource mapping manually to avoid the query cache getting
        // invalidated on updates to the resource table.
        Cache ridCache = CacheManager.getInstance().getCache("ResourceByInstanceId");
        String key = typeId.toString() + id;

        Element e = ridCache.get(key);
        if (e != null) {
            Integer rid = (Integer) e.getObjectValue();
            return get(rid);
        } else {
            String sql = "from Resource where instanceId = ? and " + "resourceType.id = ?";
            Resource r = (Resource) getSession().createQuery(sql).setInteger(0, id.intValue())
                    .setInteger(1, typeId.intValue()).uniqueResult();

            if (r != null) {
                ridCache.put(new Element(key, r.getId()));
            }

            return r;
        }
    }

    /**
     * Find a Resource by type Id and instance Id, allowing for the query to
     * return a stale copy of the resource (for efficiency reasons).
     * 
     * @param typeId The type Id.
     * @param id The instance Id.
     * @param allowStale <code>true</code> to allow stale copies of an alert
     *        definition in the query results; <code>false</code> to never allow
     *        stale copies, potentially always forcing a sync with the database.
     * @return The Resource.
     */
    public Resource findByInstanceId(Integer typeId, Integer id, boolean allowStale) {
        FlushMode oldFlushMode = this.getSession().getFlushMode();

        try {
            if (allowStale) {
                this.getSession().setFlushMode(FlushMode.MANUAL);
            }

            return findByInstanceId(typeId, id);
        } finally {
            this.getSession().setFlushMode(oldFlushMode);
        }
    }

    @SuppressWarnings("unchecked")
    public List<Resource> findByResource(AuthzSubject subject, Resource r) {
        final String[] VIEW_APPDEFS = new String[] { AuthzConstants.platformOpViewPlatform,
                AuthzConstants.serverOpViewServer, AuthzConstants.serviceOpViewService, };

        EdgePermCheck wherePermCheck = permissionManager.makePermCheckHql("rez", true);
        String hql = "select rez from Resource rez " + wherePermCheck;

        Query q = createQuery(hql);
        return wherePermCheck.addQueryParameters(q, subject, r, 0, Arrays.asList(VIEW_APPDEFS)).list();
    }

    public List<Resource> findChildren(AuthzSubject subject, Resource r) {
        final String[] VIEW_APPDEFS = new String[] { AuthzConstants.platformOpViewPlatform,
                AuthzConstants.serverOpViewServer, AuthzConstants.serviceOpViewService, };

        EdgePermCheck wherePermCheck = permissionManager.makePermCheckHql("rez", false);
        String hql = "select rez from Resource rez " + wherePermCheck;

        Query q = createQuery(hql);
        return wherePermCheck.addQueryParameters(q, subject, r, 1, Arrays.asList(VIEW_APPDEFS)).list();
    }

    @SuppressWarnings("unchecked")
    public Collection<Resource> findByOwner(AuthzSubject owner, int sortName) {
        String sql = "from Resource where owner.id = ?";
        switch (sortName) {
        case PageControl.SORT_ASC:
            sql = sql + " order by name asc";
            break;
        case PageControl.SORT_DESC:
            sql = sql + " order by name desc";
            break;
        case PageControl.SORT_UNSORTED:
            break;
        default:
        }
        return getSession().createQuery(sql).setInteger(0, owner.getId().intValue()).list();
    }

    @SuppressWarnings("unchecked")
    public Collection<Resource> findByOwnerAndType(AuthzSubject owner, ResourceType type) {
        String sql = "from Resource where owner.id = ? and resourceType.id = ?";
        return getSession().createQuery(sql).setInteger(0, owner.getId().intValue())
                .setInteger(1, type.getId().intValue()).list();
    }

    @SuppressWarnings("unchecked")
    public Collection<Resource> findViewableSvcRes_orderName(Integer user, Boolean fSystem) {
        ResourceType serviceType = Bootstrap.getBean(ResourceTypeDAO.class)
                .findByName(AuthzConstants.serviceResType);
        Operation op = Bootstrap.getBean(OperationDAO.class).findByTypeAndName(serviceType,
                AuthzConstants.serviceOpViewService);
        final String sql = new StringBuilder(1024).append("SELECT {res.*} ").append("FROM EAM_SUBJECT subject ")
                .append("JOIN EAM_SUBJECT_ROLE_MAP subjrolemap on subject.ID = subjrolemap.SUBJECT_ID ")
                .append("JOIN EAM_ROLE role on role.ID = subjrolemap.ROLE_ID ")
                .append("JOIN EAM_ROLE_RESOURCE_GROUP_MAP rolegrpmap on rolegrpmap.ROLE_ID = role.ID ")
                .append("JOIN EAM_RESOURCE res on res.RESOURCE_TYPE_ID = :resourceTypeId ")
                .append("AND res.FSYSTEM = :system ")
                .append("JOIN EAM_RES_GRP_RES_MAP grpmap on grpmap.RESOURCE_ID = res.ID ")
                .append("JOIN EAM_RESOURCE_GROUP resgrp on resgrp.ID = grpmap.RESOURCE_GROUP_ID ")
                .append("AND rolegrpmap.RESOURCE_GROUP_ID = resgrp.ID ")
                .append("JOIN EAM_ROLE_OPERATION_MAP opmap on role.id = opmap.ROLE_ID ")
                .append("AND opmap.OPERATION_ID = :opId ").append("WHERE subject.ID = :subjectId ")
                .append("UNION ALL ").append("SELECT {res.*} ").append("FROM EAM_RESOURCE res ")
                .append("WHERE res.SUBJECT_ID = :subjectId AND res.RESOURCE_TYPE_ID = :resourceTypeId ")
                .append("AND res.FSYSTEM = :system ").toString();

        List<Resource> resources = getSession().createSQLQuery(sql).addEntity("res", Resource.class)
                .setBoolean("system", fSystem.booleanValue()).setInteger("opId", op.getId().intValue())
                .setInteger("subjectId", user.intValue())
                .setInteger("resourceTypeId", serviceType.getId().intValue()).list();

        // use TreeSet to eliminate dups and sort by Resource
        return new TreeSet<Resource>(resources);

    }

    @SuppressWarnings("unchecked")
    public Collection<Resource> findSvcRes_orderName(Boolean fSystem) {
        String sql = "select r from Resource r join r.resourceType rt " + "where r.system = :system and "
                + "(rt.name = :resSvcType or " + "exists (select rg from ResourceGroup rg " + "join rg.resource r2 "
                + "where r = r2 and rg.groupType = 15)) " + "order by r.sortName ";

        return getSession().createQuery(sql).setBoolean("system", fSystem.booleanValue())
                .setString("resSvcType", AuthzConstants.serviceResType).list();
    }

    @SuppressWarnings("unchecked")
    public Collection<Resource> findInGroupAuthz_orderName(Integer userId, Integer groupId, Boolean fSystem) {
        String sql = "select distinct r from Resource r " + " join r.resourceGroups rgg"
                + " join r.resourceGroups rg " + " join rg.roles role " + " join role.subjects subj "
                + " join role.operations op " + "where " + " r.system = :system and " + " rgg.id = :groupId and "
                + " (subj.id = :subjectId or " + "  r.owner.id = :subjectId or "
                + "  subj.authDsn = 'covalentAuthzInternalDsn') and "
                + " op.resourceType.id = r.resourceType.id and " + " (" + "  op.name = 'viewPlatform' or "
                + "  op.name = 'viewServer' or " + "  op.name = 'viewService' or "
                + "  op.name = 'viewApplication' or " + "  op.name = 'viewResourceGroup' )"
                + " order by r.sortName ";
        return getSession().createQuery(sql).setBoolean("system", fSystem.booleanValue())
                .setInteger("groupId", groupId.intValue()).setInteger("subjectId", userId.intValue()).list();
    }

    @SuppressWarnings("unchecked")
    public Collection<Resource> findInGroup_orderName(Integer groupId, Boolean fSystem) {
        String sql = "select distinct r from Resource r " + " join r.resourceGroups rgg"
                + " join r.resourceGroups rg " + " join rg.roles role " + " join role.subjects subj "
                + " join role.operations op " + "where " + " r.system = :system and " + " rgg.id = :groupId and "
                + " (subj.id=1 or r.owner.id=1 or " + "  subj.authDsn = 'covalentAuthzInternalDsn') and "
                + " op.resourceType.id = r.resourceType.id and " + " (op.name = 'viewPlatform' or "
                + "  op.name = 'viewServer' or " + "  op.name = 'viewService' or "
                + "  op.name = 'viewApplication' or " + "  op.name='viewResourceGroup' )" + " order by r.sortName ";

        return getSession().createQuery(sql).setBoolean("system", fSystem.booleanValue())
                .setInteger("groupId", groupId.intValue()).list();
    }

    @SuppressWarnings("unchecked")
    public Collection<Resource> findScopeByOperationBatch(AuthzSubject subjLoc, Resource[] resLocArr,
            Operation[] opLocArr) {
        StringBuffer sb = new StringBuffer();

        sb.append("SELECT DISTINCT r ").append("FROM Resource r ").append(" join r.resourceGroups g ")
                .append(" join g.roles e ").append(" join e.operations o ").append(" join e.subjects s ")
                .append(" WHERE s.id = ? ").append(" AND ( ");

        for (int x = 0; x < resLocArr.length; x++) {
            if (x > 0)
                sb.append(" OR ");
            sb.append(" (o.id=").append(opLocArr[x].getId()).append(" AND r.id=").append(resLocArr[x].getId())
                    .append(") ");
        }
        sb.append(")");
        return getSession().createQuery(sb.toString()).setInteger(0, subjLoc.getId().intValue()).list();
    }

    /**
     * Returns an ordered list of instance IDs for a given operation.
     */
    @SuppressWarnings("unchecked")
    public List<Integer> findAllResourcesInstancesForOperation(int opId) {
        final String sql = "SELECT r.instanceId FROM Resource r, Operation o "
                + "WHERE     o.resourceType = r.resourceType" + "      AND o.id = :opId";

        return getSession().createQuery(sql).setInteger("opId", opId).list();
    }

    int reassignResources(int oldOwner, int newOwner) {
        return getSession()
                .createQuery("UPDATE Resource " + "SET owner.id = :newOwner " + "WHERE owner.id = :oldOwner")
                .setInteger("oldOwner", oldOwner).setInteger("newOwner", newOwner).executeUpdate();
    }

    boolean resourcesExistOfType(String typeName) {
        String sql = "select r from Resource r " + "join r.prototype p " + "where p.name = :protoName";

        return getSession().createQuery(sql).setParameter("protoName", typeName).setMaxResults(1).list()
                .isEmpty() == false;
    }

    @SuppressWarnings("unchecked")
    List<Resource> getResourcesByPrototype(Resource proto, String regex) {
        String hql = "from Resource r where r.prototype = :proto";
        if (regex != null) {
            hql += " AND " + getHQDialect().getRegExSQL("r.name", regex, true, false);
        }
        return getSession().createQuery(hql).setParameter("proto", proto).list();
    }

    @SuppressWarnings("unchecked")
    List<Resource> findResourcesOfPrototype(Resource proto, PageInfo pInfo) {
        String sql = "select r from Resource r where r.prototype = :proto";
        return pInfo.pageResults(getSession().createQuery(sql).setParameter("proto", proto)).list();
    }

    Resource findResourcePrototypeByName(String name) {
        String sql = "select r from Resource r " + "where r.name = :name "
                + " AND r.resourceType.id in (:platProto, :svrProto, :svcProto)";

        return (Resource) getSession().createQuery(sql).setParameter("name", name)
                .setParameter("platProto", AuthzConstants.authzPlatformProto)
                .setParameter("svrProto", AuthzConstants.authzServerProto)
                .setParameter("svcProto", AuthzConstants.authzServiceProto).uniqueResult();
    }

    @SuppressWarnings("unchecked")
    List<Resource> findAllAppdefPrototypes() {
        String sql = "select r from Resource r " + "where r.resourceType.id in (:platProto, :svrProto, :svcProto)";

        return getSession().createQuery(sql).setParameter("platProto", AuthzConstants.authzPlatformProto)
                .setParameter("svrProto", AuthzConstants.authzServerProto)
                .setParameter("svcProto", AuthzConstants.authzServiceProto).list();
    }

    @SuppressWarnings("unchecked")
    List<Resource> findAppdefPrototypes() {
        String sql = "select distinct r.prototype from Resource r "
                + "where r.resourceType.id in (:platProto, :svrProto, :svcProto) ";

        return getSession().createQuery(sql).setParameter("platProto", AuthzConstants.authzPlatform)
                .setParameter("svrProto", AuthzConstants.authzServer)
                .setParameter("svcProto", AuthzConstants.authzService).list();
    }

    @SuppressWarnings("unchecked")
    List<Resource> findByPlugin(String pluginName) {
        String sql = "select s.resource from Server s " + "where s.serverType.plugin = :pluginName";

        return getSession().createQuery(sql).setParameter("pluginName", pluginName).list();
    }

    public int getPlatformCountMinusVsphereVmPlatforms() {
        String sql = "select count(*) from Resource r " + "where r.resourceType.id = :platProto "
                + "and r.prototype.name != :vspherevm";
        return ((Number) getSession().createQuery(sql)
                .setInteger("platProto", AuthzConstants.authzPlatform.intValue())
                .setString("vspherevm", AuthzConstants.platformPrototypeVmwareVsphereVm).uniqueResult()).intValue();
    }

    @SuppressWarnings("unchecked")
    public Collection<Resource> getUnconfiguredResources() {
        String hql = new StringBuilder(256).append("from Resource r ")
                .append("where resourceType.id in (:platformType, :serverType, :serviceType) ")
                .append("and not exists (select 1 from Measurement m where r.id = m.resource.id)").toString();
        Collection<Resource> rtn = getSession().createQuery(hql)
                .setParameter("platformType", AuthzConstants.authzPlatform)
                .setParameter("serverType", AuthzConstants.authzServer)
                .setParameter("serviceType", AuthzConstants.authzService).list();
        final ServerManager sMan = Bootstrap.getBean(ServerManager.class);
        for (final Iterator<Resource> it = rtn.iterator(); it.hasNext();) {
            final Resource r = it.next();
            if (r == null || r.isInAsyncDeleteState()) {
                it.remove();
                continue;
            }
            if (r.getResourceType().getId().equals(AuthzConstants.authzServer)) {
                try {
                    final Server server = sMan.findServerById(r.getInstanceId());
                    if (server.getServerType().isVirtual()) {
                        it.remove();
                    }
                } catch (ServerNotFoundException e) {
                    _log.debug(e, e);
                    continue;
                }
            }
        }
        return rtn;
    }

    @SuppressWarnings("unchecked")
    Collection<Integer> getParentResourceIds(Collection<Resource> resources, ResourceRelation relation,
            int startdistance, int maxdistance) {
        final List<Resource> resourceList = new ArrayList<Resource>(resources);
        final String hql = new StringBuilder(64).append("select distinct re.to.id FROM ResourceEdge re ")
                .append("WHERE re.distance between :start and :end and re.relation=:relation ")
                .append("AND re.from in (:from)").toString();
        final Query query = getSession().createQuery(hql);
        final HQDialect dialect = getHQDialect();
        final int batchSize = (dialect.getMaxExpressions() < 0) ? Integer.MAX_VALUE : dialect.getMaxExpressions();
        final Collection<Integer> rtn = new ArrayList<Integer>(resources.size());
        for (int ii = 0; ii < resources.size(); ii += batchSize) {
            final int last = Math.min(resources.size(), batchSize + ii);
            rtn.addAll(query.setParameterList("from", resourceList.subList(ii, last))
                    .setParameter("relation", relation).setParameter("start", Math.min(startdistance, maxdistance))
                    .setParameter("end", Math.max(startdistance, maxdistance)).list());
        }
        return rtn;
    }

    @SuppressWarnings("unchecked")
    Map<String, Long> getResourceCountByProtoTypeName(Collection<MonitorableType> types) {
        if (types == null || types.isEmpty()) {
            ;
            return Collections.emptyMap();
        }
        final Map<String, String> map = new HashMap<String, String>();
        for (final MonitorableType mt : types) {
            map.put(mt.getName(), mt.getPlugin());
        }
        final String hql = new StringBuilder().append("select count(*), prototype.name from Resource ")
                .append("where prototype.name in (:typeNames) group by prototype.name").toString();
        final Collection<Object[]> list = getSession().createQuery(hql).setParameterList("typeNames", map.keySet())
                .list();
        final Map<String, Long> rtn = new HashMap<String, Long>();
        for (final Object[] objs : list) {
            final String pluginName = map.get(objs[1]);
            if (pluginName == null) {
                continue;
            }
            Long count = rtn.get(pluginName);
            if (count == null) {
                rtn.put(pluginName, ((Number) objs[0]).longValue());
            } else {
                rtn.put(pluginName, count + ((Number) objs[0]).longValue());
            }
        }
        return rtn;
    }

    @SuppressWarnings("unchecked")
    Collection<Resource> getResourcesByProtoTypeName(Collection<String> typeNames) {
        if (typeNames == null || typeNames.isEmpty()) {
            return Collections.emptyList();
        }
        final String hql = "from Resource where prototype.name in (:typeNames)";
        return getSession().createQuery(hql).setParameterList("typeNames", typeNames).list();
    }

    @SuppressWarnings("unchecked")
    Collection<Resource> getOrphanedResources() {
        final List<Resource> rtn = new ArrayList<Resource>();
        // normally i would use a union all in sql instead of three different queries,
        // but hibernate keeps giving an NPE when I try that
        final String platformHql = new StringBuilder(128)
                .append("from Resource r where r.resourceType.id = :platformType and not exists (")
                .append("select 1 from Platform p where p.id = r.instanceId").append(")").toString();
        rtn.addAll(createQuery(platformHql).setInteger("platformType", AuthzConstants.authzPlatform).list());
        final String serverHql = new StringBuilder(128)
                .append("from Resource r where r.resourceType.id = :serverType and not exists (")
                .append("select 1 from Server s where s.id = r.instanceId").append(")").toString();
        rtn.addAll(createQuery(serverHql).setInteger("serverType", AuthzConstants.authzServer).list());
        final String serviceHql = new StringBuilder(128)
                .append("from Resource r where r.resourceType.id = :serviceType and not exists (")
                .append("select 1 from Service s where s.id = r.instanceId").append(")").toString();
        rtn.addAll(createQuery(serviceHql).setInteger("serviceType", AuthzConstants.authzService).list());
        return rtn;
    }

}