public void markStaleServersDown(Subject subject) {
    if (!authorizationManager.isOverlord(subject)) {
      throw new IllegalArgumentException(
          "The markStaleServersDown method must be called by the overlord");
    }

    long staleTime = System.currentTimeMillis() - SERVER_DOWN_INTERVAL;

    String serverName = null;
    try {
      serverName = serverManager.getIdentity();
      if (log.isDebugEnabled()) {
        log.debug(serverName + " is marking stale servers DOWN");
      }
    } catch (Exception e) {
      log.error("Could not determine which instance is marking stale servers DOWN");
    }
    Query query = entityManager.createNamedQuery(Server.QUERY_UPDATE_SET_STALE_DOWN);
    query.setParameter("downMode", Server.OperationMode.DOWN);
    query.setParameter("normalMode", Server.OperationMode.NORMAL);
    query.setParameter("staleTime", staleTime);
    query.setParameter("thisServerName", serverName); // might be null
    int resultCount = query.executeUpdate();

    if (log.isDebugEnabled()) {
      log.debug(String.valueOf(resultCount) + " stale servers were marked DOWN");
    }

    // Perform requested partition events. Note that we only need to execute one cloud partition
    // regardless of the number of pending requests, as the work would be duplicated.
    partitionEventManager.processRequestedPartitionEvents();
  }
  public PageList<Dashboard> findDashboardsByCriteria(Subject subject, DashboardCriteria criteria) {
    if (criteria.isInventoryManagerRequired()) {
      if (!authorizationManager.isInventoryManager(subject)) {
        throw new PermissionException(
            "Subject ["
                + subject.getName()
                + "] requires InventoryManager permission for requested query criteria.");
      }

      Integer ownerId = criteria.getFilterOwnerId();
      if (null != ownerId && 0 == ownerId.intValue()) {
        criteria.addFilterOwnerId(null);
      }
    } else {
      criteria.addFilterOwnerId(subject.getId());
    }

    if (null == criteria.getFilterCategory()) {
      criteria.addFilterCategory(DashboardCategory.INVENTORY);
    }

    CriteriaQueryGenerator generator = new CriteriaQueryGenerator(subject, criteria);

    CriteriaQueryRunner<Dashboard> queryRunner =
        new CriteriaQueryRunner<Dashboard>(criteria, generator, entityManager);
    return queryRunner.execute();
  }
  @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
  public MeasurementBaseline calculateAutoBaselineForGroupInNewTransaction(
      Subject subject, int groupId, int definitionId, long startDate, long endDate, boolean save)
      throws BaselineCreationException, MeasurementNotFoundException {

    if (save
        && !authorizationManager.hasGroupPermission(
            subject, Permission.MANAGE_MEASUREMENTS, groupId)) {
      throw new PermissionException(
          "User["
              + subject.getName()
              + "] does not have permission to calculate and set baselines for group[id="
              + groupId
              + "]");
    }

    MeasurementBaseline baseline;
    try {
      baseline = calculateBaselineForGroup(groupId, definitionId, true, startDate, endDate, save);
      if (save) {
        // We have changed the baseline information for the schedule, so remove the now outdated OOB
        // info.
        oobManager.removeOOBsForGroupAndDefinition(subject, groupId, definitionId);
      }
    } catch (DataNotAvailableException e) {
      throw new BaselineCreationException(
          "Error fetching data for baseline calculation for group[id="
              + groupId
              + "], definition[id="
              + definitionId
              + "]");
    }

    return baseline;
  }
  public void removeDashboard(Subject subject, int dashboardId) {

    Dashboard toDelete = entityManager.find(Dashboard.class, dashboardId);

    if (!authorizationManager.hasGlobalPermission(subject, Permission.MANAGE_SETTINGS)
        && toDelete.getOwner().getId() != subject.getId()) {
      throw new PermissionException("You may only delete dashboards you own.");
    }

    entityManager.remove(toDelete);
  }
 public Dashboard storeDashboard(Subject subject, Dashboard dashboard) {
   Dashboard d = null;
   if ((d = entityManager.find(Dashboard.class, dashboard.getId())) == null) {
     dashboard.setOwner(subject);
     entityManager.persist(dashboard);
     return dashboard;
   } else {
     if (!authorizationManager.hasGlobalPermission(subject, Permission.MANAGE_SETTINGS)
         && d.getOwner().getId() != subject.getId()) {
       throw new PermissionException("You may only alter dashboards you own.");
     }
     return entityManager.merge(dashboard);
   }
 }
  public void setLdapGroupsForRole(int roleId, List<String> groupIds) throws RuntimeException {
    try {
      // add permissions check
      Set<Permission> globalPermissions =
          authorizationManager.getExplicitGlobalPermissions(getSessionSubject());
      Boolean accessGranted = globalPermissions.contains(Permission.MANAGE_SECURITY);

      if (accessGranted) {
        // clean out existing roles as this defines the new list of roles
        PageList<LdapGroup> existing =
            ldapManager.findLdapGroupsByRole(roleId, PageControl.getUnlimitedInstance());
        log.trace("Removing " + existing.getTotalSize() + " groups from role '" + roleId + "'.");
        int[] groupIndices = new int[existing.size()];
        int indx = 0;
        for (LdapGroup lg : existing) {
          groupIndices[indx++] = lg.getId();
        }
        log.trace("Removing " + groupIndices.length + " LDAP Groups." + groupIndices);
        ldapManager.removeLdapGroupsFromRole(subjectManager.getOverlord(), roleId, groupIndices);
        PageList<LdapGroup> nowGroups =
            ldapManager.findLdapGroupsByRole(roleId, PageControl.getUnlimitedInstance());

        // from among all available groups, if group name matches then add it to the list.
        ArrayList<String> validGroupIds = new ArrayList<String>();
        Set<Map<String, String>> allAvailableLdapGroups = ldapManager.findAvailableGroups();
        for (String group : groupIds) {
          for (Map<String, String> map : allAvailableLdapGroups) {
            if (map.get("name").equals(group)) {
              validGroupIds.add(group);
            }
          }
        }
        log.trace("Adding " + validGroupIds.size() + " ldap groups to role[" + roleId + "].");
        ldapManager.addLdapGroupsToRole(subjectManager.getOverlord(), roleId, groupIds);
        nowGroups = ldapManager.findLdapGroupsByRole(roleId, PageControl.getUnlimitedInstance());
      } else {
        String message =
            "User '"
                + getSessionSubject().getName()
                + "' does not have sufficient permissions to modify LDAP group assignments for roles.";
        log.debug(message);
        throw new PermissionException(message);
      }

    } catch (Throwable t) {
      throw getExceptionToThrowToClient(t);
    }
  }
  @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
  public MeasurementBaseline calculateAutoBaselineInNewTransaction(
      Subject subject, Integer measurementScheduleId, long startDate, long endDate, boolean save)
      throws BaselineCreationException, MeasurementNotFoundException {

    MeasurementBaseline baseline;
    MeasurementSchedule sched =
        entityManager.find(MeasurementSchedule.class, measurementScheduleId);

    if (sched != null) {
      Resource resource = sched.getResource();

      // only check permissions if the user is attempting to save a new baseline
      if (save
          && !authorizationManager.hasResourcePermission(
              subject, Permission.MANAGE_MEASUREMENTS, resource.getId())) {
        log.error(
            "Cannot calculate baseline - permission denied. "
                + "resource="
                + resource
                + "; user="******"; perm="
                + Permission.MANAGE_MEASUREMENTS);
        throw new PermissionException(
            "Cannot calculate baseline - you do not have permission on this resource");
      }
    } else {
      throw new MeasurementNotFoundException(
          "Scheduled measurement [" + measurementScheduleId + "] not found");
    }

    try {
      baseline = calculateBaseline(sched, true, startDate, endDate, save);
      if (save) {
        // We have changed the baseline information for the schedule, so remove the now outdated OOB
        // info.
        oobManager.removeOOBsForSchedule(subject, sched);
      }
    } catch (DataNotAvailableException e) {
      throw new BaselineCreationException(
          "Error fetching data for baseline calculation for measurementSchedule[id="
              + measurementScheduleId
              + "]");
    }

    return baseline;
  }
  @SuppressWarnings("unchecked")
  public List<MeasurementBaseline> findBaselinesForResource(Subject subject, int resourceId) {
    if (authorizationManager.canViewResource(subject, resourceId) == false) {
      throw new PermissionException(
          "User["
              + subject.getName()
              + " ] does not have permission to view baselines for resource[id="
              + resourceId
              + "]");
    }

    Query query = entityManager.createNamedQuery(MeasurementBaseline.QUERY_FIND_BY_RESOURCE);
    query.setParameter("resourceId", resourceId);
    List<MeasurementBaseline> results = query.getResultList();
    return results;
  }
  @SuppressWarnings("unchecked")
  public PageList<CallTimeDataComposite> findCallTimeDataForResource(
      Subject subject, int scheduleId, long beginTime, long endTime, PageControl pageControl) {
    pageControl.initDefaultOrderingField(
        "SUM(value.total)/SUM(value.count)",
        PageOrdering.DESC); // only set if no ordering yet specified
    pageControl.addDefaultOrderingField(
        "key.callDestination", PageOrdering.ASC); // add this to sort, if not already specified

    MeasurementSchedule schedule = entityManager.find(MeasurementSchedule.class, scheduleId);
    int resourceId = schedule.getResource().getId();
    if (authorizationManager.canViewResource(subject, resourceId) == false) {
      throw new PermissionException(
          "User ["
              + subject
              + "] does not have permission to view call time data for measurementSchedule[id="
              + scheduleId
              + "] and resource[id="
              + resourceId
              + "]");
    }

    String query = CallTimeDataValue.QUERY_FIND_COMPOSITES_FOR_RESOURCE;

    Query queryWithOrderBy =
        PersistenceUtility.createQueryWithOrderBy(entityManager, query, pageControl);
    Query queryCount = PersistenceUtility.createCountQuery(this.entityManager, query);

    queryWithOrderBy.setParameter("scheduleId", scheduleId);
    queryWithOrderBy.setParameter("beginTime", beginTime);
    queryWithOrderBy.setParameter("endTime", endTime);

    List<CallTimeDataComposite> results = queryWithOrderBy.getResultList();

    queryCount.setParameter("scheduleId", scheduleId);
    queryCount.setParameter("beginTime", beginTime);
    queryCount.setParameter("endTime", endTime);

    // Because of the use of the GROUP BY clause, the result list count will be returned as
    // the number of rows, rather than as a single number.
    long count = queryCount.getResultList().size();

    return new PageList<CallTimeDataComposite>(results, (int) count, pageControl);
  }
  public void enableAutoBaselineCalculation(
      Subject subject, Integer[] resourceIds, Integer[] definitionIds) {
    // bail out early if there's nothing to do
    if ((resourceIds.length < 1) || (definitionIds.length < 1)) {
      return;
    }

    List<MeasurementBaseline> bList =
        getBaselinesForResourcesAndDefinitionIds(resourceIds, definitionIds);
    for (MeasurementBaseline bl : bList) {
      if (!authorizationManager.hasResourcePermission(
          subject, Permission.MANAGE_MEASUREMENTS, bl.getSchedule().getResource().getId())) {
        throw new PermissionException(
            "Cannot enable baseline [" + bl + "] - you do not have permission");
      }

      bl.setUserEntered(false);
    }
  }
  @Override
  public Set<Map<String, String>> findAvailableGroupsStatus() throws RuntimeException {
    try {
      // add permissions check
      Set<Permission> globalPermissions =
          authorizationManager.getExplicitGlobalPermissions(getSessionSubject());
      Boolean accessGranted = globalPermissions.contains(Permission.MANAGE_SECURITY);

      Set<Map<String, String>> results = null;
      if (accessGranted) {
        results = ldapManager.findAvailableGroupsStatus();
      } else {
        String message =
            "User '"
                + getSessionSubject().getName()
                + "' does not have sufficient permissions to query the status of available LDAP groups request.";
        log.debug(message);
        throw new PermissionException(message);
      }
      return SerialUtility.prepare(results, "findAvailableGroups");
    } catch (Throwable t) {
      throw getExceptionToThrowToClient(t);
    }
  }
  public PageList<LdapGroup> findLdapGroupsAssignedToRole(int roleId) throws RuntimeException {
    try {
      // add permissions check
      Set<Permission> globalPermissions =
          authorizationManager.getExplicitGlobalPermissions(getSessionSubject());
      Boolean accessGranted = globalPermissions.contains(Permission.MANAGE_SECURITY);

      PageList<LdapGroup> allAssignedLdapGroups = null;
      if (accessGranted) {
        allAssignedLdapGroups =
            ldapManager.findLdapGroupsByRole(roleId, PageControl.getUnlimitedInstance());
      } else {
        String message =
            "User '"
                + getSessionSubject().getName()
                + "' does not have permissions to query LDAP group by role.";
        log.debug(message);
        throw new PermissionException(message);
      }
      return SerialUtility.prepare(allAssignedLdapGroups, "findLdapGroupsAssignedToRole");
    } catch (Throwable t) {
      throw getExceptionToThrowToClient(t);
    }
  }
  public PageList<CallTimeDataComposite> findCallTimeDataForContext(
      Subject subject,
      EntityContext context,
      long beginTime,
      long endTime,
      String destination,
      PageControl pageControl) {

    // lookup measurement definition id

    CallTimeDataCriteria criteria = new CallTimeDataCriteria();
    criteria.addFilterBeginTime(beginTime);
    criteria.addFilterEndTime(endTime);
    if (destination != null && !destination.trim().equals("")) {
      criteria.addFilterDestination(destination);
    }

    pageControl.initDefaultOrderingField(
        "SUM(calltimedatavalue.total)/SUM(calltimedatavalue.count)",
        PageOrdering.DESC); // only set if no ordering yet specified
    pageControl.addDefaultOrderingField(
        "calltimedatavalue.key.callDestination",
        PageOrdering.ASC); // add this to sort, if not already specified
    criteria.setPageControl(pageControl);

    // criteria.addSortAverage(PageOrdering.DESC);

    if (context.type == EntityContext.Type.Resource) {
      criteria.addFilterResourceId(context.resourceId);
    } else if (context.type == EntityContext.Type.ResourceGroup) {
      criteria.addFilterResourceGroupId(context.groupId);
    } else if (context.type == EntityContext.Type.AutoGroup) {
      criteria.addFilterAutoGroupParentResourceId(context.parentResourceId);
      criteria.addFilterAutoGroupResourceTypeId(context.resourceTypeId);
    }

    CriteriaQueryGenerator generator = new CriteriaQueryGenerator(subject, criteria);
    ;
    String replacementSelectList =
        "" //
            + " new org.rhq.core.domain.measurement.calltime.CallTimeDataComposite( " //
            + "   calltimedatavalue.key.callDestination, " //
            + "   MIN(calltimedatavalue.minimum), " //
            + "   MAX(calltimedatavalue.maximum), " //
            + "   SUM(calltimedatavalue.total), " //
            + "   SUM(calltimedatavalue.count), " //
            + "   SUM(calltimedatavalue.total) / SUM(calltimedatavalue.count) ) ";
    generator.alterProjection(replacementSelectList);
    generator.setGroupByClause("calltimedatavalue.key.callDestination");

    if (authorizationManager.isInventoryManager(subject) == false) {
      generator.setAuthorizationResourceFragment(
          CriteriaQueryGenerator.AuthorizationTokenType.RESOURCE,
          "key.schedule.resource",
          subject.getId());
    }

    // log.info(generator.getParameterReplacedQuery(false));
    // log.info(generator.getParameterReplacedQuery(true));

    CriteriaQueryRunner<CallTimeDataComposite> queryRunner =
        new CriteriaQueryRunner<CallTimeDataComposite>(criteria, generator, entityManager);
    PageList<CallTimeDataComposite> results = queryRunner.execute();
    return results;
  }