Package org.knowhowlab.osgi.monitoradmin

Source Code of org.knowhowlab.osgi.monitoradmin.MonitorAdminImpl

/*
* Copyright (c) 2010 Dmytro Pishchukhin (http://knowhowlab.org)
*
* 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.knowhowlab.osgi.monitoradmin;

import org.knowhowlab.osgi.monitoradmin.job.ScheduledMonitoringJob;
import org.knowhowlab.osgi.monitoradmin.job.SubscriptionMonitoringJob;
import org.knowhowlab.osgi.monitoradmin.util.StatusVariablePath;
import org.knowhowlab.osgi.monitoradmin.util.StatusVariablePathFilter;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.service.monitor.*;

import java.util.*;

/**
* MonitorAdmin implementation
*
* @author dmytro.pishchukhin
*/
public class MonitorAdminImpl implements MonitorAdmin {
    private static final String STARTJOB_PERMISSION_PATTERN = String.format("%s:%%d", MonitorPermission.STARTJOB);

    private final LogVisitor logVisitor;
    private final MonitorAdminCommon common;
    private final Bundle consumer;

    /**
     * Initialize MonitorAdmin implementation instance
     *
     * @param logVisitor loggers visitor
     * @param common     commons actions
     * @param consumer   bundle-consumer
     */
    public MonitorAdminImpl(LogVisitor logVisitor, MonitorAdminCommon common, Bundle consumer) {
        this.logVisitor = logVisitor;
        this.common = common;
        this.consumer = consumer;
    }

    /**
     * Returns a <code>StatusVariable</code> addressed by its full path.
     * The entity which queries a <code>StatusVariable</code> needs to hold
     * <code>MonitorPermission</code> for the given target with the
     * <code>read</code> action present.
     *
     * @param path the full path of the <code>StatusVariable</code> in
     *             [Monitorable_ID]/[StatusVariable_ID] format
     * @return the <code>StatusVariable</code> object
     * @throws java.lang.IllegalArgumentException
     *                                     if <code>path</code> is
     *                                     <code>null</code> or otherwise invalid, or points to a
     *                                     non-existing <code>StatusVariable</code>
     * @throws java.lang.SecurityException if the caller does not hold a
     *                                     <code>MonitorPermission</code> for the
     *                                     <code>StatusVariable</code> specified by <code>path</code>
     *                                     with the <code>read</code> action present
     */
    public StatusVariable getStatusVariable(String path)
            throws IllegalArgumentException, SecurityException {
        logVisitor.debug("ENTRY: getStatusVariable: " + path, null);
        try {
            StatusVariablePath statusVariablePath = new StatusVariablePath(path);
            ServiceReference serviceReference = common.findMonitorableReferenceById(statusVariablePath.getMonitorableId());

            checkPermissions(statusVariablePath, serviceReference, MonitorPermission.PUBLISH, MonitorPermission.READ);

            return common.getStatusVariable(serviceReference, statusVariablePath.getStatusVariableId());
        } finally {
            logVisitor.debug("EXIT: getStatusVariable: " + path, null);
        }
    }

    /**
     * Check permissions for StatusVariable path
     *
     * @param statusVariablePath path
     * @param serviceReference   Monitorable service reference
     * @param producerPermission producer permission action
     * @param consumerPermission consumer permission action
     * @throws java.lang.IllegalArgumentException
     *                                     if <code>path</code> is
     *                                     <code>null</code> or otherwise invalid, or points to a
     *                                     non-existing <code>StatusVariable</code> (SV is not published)
     * @throws java.lang.SecurityException if the caller does not hold a
     *                                     <code>MonitorPermission</code> for the
     *                                     <code>StatusVariable</code> specified by <code>path</code>
     *                                     with the <code>read</code> action present
     */
    private void checkPermissions(StatusVariablePath statusVariablePath, ServiceReference serviceReference, String producerPermission, String consumerPermission) {
        String[] variableNames = common.getStatusVariableNames(statusVariablePath.getMonitorableId());

        Collection<String> producerVariables = filterVariableNames(statusVariablePath.getMonitorableId(), variableNames, serviceReference.getBundle(), producerPermission);
        if (!producerVariables.contains(statusVariablePath.getStatusVariableId())) {
            throw new IllegalArgumentException(statusVariablePath.getPath() + " StatusVariable is unavailable");
        }

        Collection<String> consumerVariables = filterVariableNames(statusVariablePath.getMonitorableId(), variableNames, consumer, consumerPermission);
        if (!consumerVariables.contains(statusVariablePath.getStatusVariableId())) {
            throw new SecurityException(consumerPermission + " permissions not set for StatusVariable: " + statusVariablePath.getPath());
        }
    }

    /**
     * Returns a human readable description of the given
     * <code>StatusVariable</code>. The <code>null</code> value may be returned
     * if there is no description for the given <code>StatusVariable</code>.
     * <p/>
     * The entity that queries a <code>StatusVariable</code> needs to hold
     * <code>MonitorPermission</code> for the given target with the
     * <code>read</code> action present.
     *
     * @param path the full path of the <code>StatusVariable</code> in
     *             [Monitorable_ID]/[StatusVariable_ID] format
     * @return the human readable description of this
     *         <code>StatusVariable</code> or <code>null</code> if it is not
     *         set
     * @throws java.lang.IllegalArgumentException
     *                                     if <code>path</code> is
     *                                     <code>null</code> or otherwise invalid, or points to a
     *                                     non-existing <code>StatusVariable</code>
     * @throws java.lang.SecurityException if the caller does not hold a
     *                                     <code>MonitorPermission</code> for the
     *                                     <code>StatusVariable</code> specified by <code>path</code>
     *                                     with the <code>read</code> action present
     */
    public String getDescription(String path)
            throws IllegalArgumentException, SecurityException {
        logVisitor.debug("ENTRY: getDescription: " + path, null);
        try {
            StatusVariablePath statusVariablePath = new StatusVariablePath(path);
            ServiceReference serviceReference = common.findMonitorableReferenceById(statusVariablePath.getMonitorableId());

            checkPermissions(statusVariablePath, serviceReference, MonitorPermission.PUBLISH, MonitorPermission.READ);

            return common.getDescription(serviceReference, statusVariablePath.getStatusVariableId());
        } finally {
            logVisitor.debug("EXIT: getDescription: " + path, null);
        }
    }

    /**
     * Returns the names of the <code>Monitorable</code> services that are
     * currently registered. The <code>Monitorable</code> instances are not
     * accessible through the <code>MonitorAdmin</code>, so that requests to
     * individual status variables can be filtered with respect to the
     * publishing rights of the <code>Monitorable</code> and the reading
     * rights of the caller.
     * <p/>
     * The returned array contains the names in alphabetical order. It cannot be
     * <code>null</code>, an empty array is returned if no
     * <code>Monitorable</code> services are registered.
     *
     * @return the array of <code>Monitorable</code> names
     */
    public String[] getMonitorableNames() {
        logVisitor.debug("ENTRY: getMonitorableNames", null);
        try {
            ServiceReference[] serviceReferences = common.getMonitorableReferences();
            SortedSet<String> names = new TreeSet<String>();
            for (ServiceReference serviceReference : serviceReferences) {
                String pid = (String) serviceReference.getProperty(Constants.SERVICE_PID);
                String[] variableNames = common.getStatusVariableNames(pid);
                // monitorable contains status variable - check permissions
                if (variableNames.length > 0) {
                    Collection<String> producerPublishedVariables = filterVariableNames(pid, variableNames, serviceReference.getBundle(), MonitorPermission.PUBLISH);
                    Collection<String> consumerReadVariables = filterVariableNames(pid, variableNames, consumer, MonitorPermission.READ);
                    if (!Collections.disjoint(producerPublishedVariables, consumerReadVariables)) {
                        names.add(pid);
                    }
                } else {
                    // monitorable does not contain status variable - just add it to the list
                    names.add(pid);
                }
            }
            return names.toArray(new String[names.size()]);
        } finally {
            logVisitor.debug("EXIT: getMonitorableNames", null);
        }
    }

    /**
     * Filter <code>StatusVariable</code> names by <code>MonitorPermission</code> action and for given <code>Bundle</code>
     *
     * @param pid              <code>Monitorable</code> service PID
     * @param variableNames    list of <code>StatusVariable</code> names
     * @param bundle           <code>Bundle</code> for permission check
     * @param permissionAction <code>MonitorPermission</code> action
     * @return filtered collection of <code>StatusVariable</code> names
     */
    private Collection<String> filterVariableNames(String pid, String[] variableNames, Bundle bundle, String permissionAction) {
        List<String> result = new ArrayList<String>();
        if (bundle != null) {
            for (String variableName : variableNames) {
                try {
                    if (bundle.hasPermission(new MonitorPermission(String.format(MonitorAdminCommon.PATH_PATERN, pid, variableName), permissionAction))) {
                        result.add(variableName);
                    }
                } catch (IllegalArgumentException e) {
                    logVisitor.debug("Unable to check permission", e);
                }
            }
        } else {
            result.addAll(Arrays.asList(variableNames));
        }
        return result;
    }

    /**
     * Returns the <code>StatusVariable</code> objects published by a
     * <code>Monitorable</code> instance. The <code>StatusVariables</code>
     * will hold the values taken at the time of this method call. Only those
     * status variables are returned where the following two conditions are met:
     * <ul>
     * <li>the specified <code>Monitorable</code> holds a
     * <code>MonitorPermission</code> for the status variable with the
     * <code>publish</code> action present
     * <li>the caller holds a <code>MonitorPermission</code> for the status
     * variable with the <code>read</code> action present
     * </ul>
     * All other status variables are silently ignored, they are omitted from
     * the result.
     * <p/>
     * The elements in the returned array are in no particular order. The return
     * value cannot be <code>null</code>, an empty array is returned if no
     * (authorized and readable) Status Variables are provided by the given
     * <code>Monitorable</code>.
     *
     * @param monitorableId the identifier of a <code>Monitorable</code>
     *                      instance
     * @return a list of <code>StatusVariable</code> objects published
     *         by the specified <code>Monitorable</code>
     * @throws java.lang.IllegalArgumentException
     *          if <code>monitorableId</code>
     *          is <code>null</code> or otherwise invalid, or points to a
     *          non-existing <code>Monitorable</code>
     */
    public StatusVariable[] getStatusVariables(String monitorableId)
            throws IllegalArgumentException {
        logVisitor.debug("ENTRY: getStatusVariables: " + monitorableId, null);
        try {
            List<StatusVariable> result = new ArrayList<StatusVariable>();

            Set<String> availableNames = new TreeSet<String>();

            ServiceReference serviceReference = common.findMonitorableReferenceById(monitorableId);
            String[] variableNames = common.getStatusVariableNames(monitorableId);
            Collection<String> producerPublishedVariables = filterVariableNames(monitorableId, variableNames, serviceReference.getBundle(), MonitorPermission.PUBLISH);
            Collection<String> consumerReadVariables = filterVariableNames(monitorableId, variableNames, consumer, MonitorPermission.READ);

            availableNames.addAll(producerPublishedVariables);
            availableNames.retainAll(consumerReadVariables);

            for (String availableName : availableNames) {
                result.add(common.getStatusVariable(serviceReference, availableName));
            }

            return result.toArray(new StatusVariable[result.size()]);
        } finally {
            logVisitor.debug("EXIT: getStatusVariables: " + monitorableId, null);
        }
    }

    /**
     * Returns the list of <code>StatusVariable</code> names published by a
     * <code>Monitorable</code> instance. Only those status variables are
     * listed where the following two conditions are met:
     * <ul>
     * <li>the specified <code>Monitorable</code> holds a
     * <code>MonitorPermission</code> for the status variable with the
     * <code>publish</code> action present
     * <li>the caller holds a <code>MonitorPermission</code> for
     * the status variable with the <code>read</code> action present
     * </ul>
     * All other status variables are silently ignored, their names are omitted
     * from the list.
     * <p/>
     * The returned array does not contain duplicates, and the elements are in
     * alphabetical order. It cannot be <code>null</code>, an empty array is
     * returned if no (authorized and readable) Status Variables are provided
     * by the given <code>Monitorable</code>.
     *
     * @param monitorableId the identifier of a <code>Monitorable</code>
     *                      instance
     * @return a list of <code>StatusVariable</code> objects names
     *         published by the specified <code>Monitorable</code>
     * @throws java.lang.IllegalArgumentException
     *          if <code>monitorableId</code>
     *          is <code>null</code> or otherwise invalid, or points to a
     *          non-existing <code>Monitorable</code>
     */
    public String[] getStatusVariableNames(String monitorableId)
            throws IllegalArgumentException {
        logVisitor.debug("ENTRY: getStatusVariableNames: " + monitorableId, null);
        try {
            Set<String> result = new TreeSet<String>();

            ServiceReference serviceReference = common.findMonitorableReferenceById(monitorableId);
            String[] variableNames = common.getStatusVariableNames(monitorableId);
            Collection<String> producerPublishedVariables = filterVariableNames(monitorableId, variableNames, serviceReference.getBundle(), MonitorPermission.PUBLISH);
            Collection<String> consumerReadVariables = filterVariableNames(monitorableId, variableNames, consumer, MonitorPermission.READ);

            result.addAll(producerPublishedVariables);
            result.retainAll(consumerReadVariables);

            return result.toArray(new String[result.size()]);
        } finally {
            logVisitor.debug("EXIT: getStatusVariableNames: " + monitorableId, null);
        }
    }

    /**
     * Issues a request to reset a given <code>StatusVariable</code>.
     * Depending on the semantics of the <code>StatusVariable</code> this call
     * may or may not succeed: it makes sense to reset a counter to its starting
     * value, but e.g. a <code>StatusVariable</code> of type String might not
     * have a meaningful default value. Note that for numeric
     * <code>StatusVariable</code>s the starting value may not necessarily be
     * 0. Resetting a <code>StatusVariable</code> triggers a monitor event if
     * the <code>StatusVariable</code> supports update notifications.
     * <p/>
     * The entity that wants to reset the <code>StatusVariable</code> needs to
     * hold <code>MonitorPermission</code> with the <code>reset</code>
     * action present. The target field of the permission must match the
     * <code>StatusVariable</code> name to be reset.
     *
     * @param path the identifier of the <code>StatusVariable</code> in
     *             [Monitorable_id]/[StatusVariable_id] format
     * @return <code>true</code> if the <code>Monitorable</code> could
     *         successfully reset the given <code>StatusVariable</code>,
     *         <code>false</code> otherwise
     * @throws java.lang.IllegalArgumentException
     *                                     if <code>path</code> is
     *                                     <code>null</code> or otherwise invalid, or points to a
     *                                     non-existing <code>StatusVariable</code>
     * @throws java.lang.SecurityException if the caller does not hold
     *                                     <code>MonitorPermission</code> with the <code>reset</code>
     *                                     action or if the specified <code>StatusVariable</code> is not
     *                                     allowed to be reset as per the target field of the permission
     */
    public boolean resetStatusVariable(String path)
            throws IllegalArgumentException, SecurityException {
        logVisitor.debug("ENTRY: resetStatusVariable: " + path, null);
        try {
            StatusVariablePath statusVariablePath = new StatusVariablePath(path);
            ServiceReference serviceReference = common.findMonitorableReferenceById(statusVariablePath.getMonitorableId());

            checkPermissions(statusVariablePath, serviceReference, MonitorPermission.PUBLISH, MonitorPermission.RESET);

            return common.resetStatusVariable(serviceReference, statusVariablePath.getStatusVariableId());
        } finally {
            logVisitor.debug("EXIT: resetStatusVariable: " + path, null);
        }
    }

    /**
     * Switches event sending on or off for the specified
     * <code>StatusVariable</code>s. When the <code>MonitorAdmin</code> is
     * notified about a <code>StatusVariable</code> being updated it sends an
     * event unless this feature is switched off. Note that events within a
     * monitoring job can not be switched off. The event sending state of the
     * <code>StatusVariables</code> must not be persistently stored. When a
     * <code>StatusVariable</code> is registered for the first time in a
     * framework session, its event sending state is set to ON by default.
     * <p/>
     * Usage of the "*" wildcard is allowed in the path argument of this method
     * as a convenience feature. The wildcard can be used in either or both path
     * fragments, but only at the end of the fragments.  The semantics of the
     * wildcard is that it stands for any matching <code>StatusVariable</code>
     * at the time of the method call, it does not affect the event sending
     * status of <code>StatusVariable</code>s which are not yet registered. As
     * an example, when the <code>switchEvents("MyMonitorable/*", false)</code>
     * method is executed, event sending from all <code>StatusVariables</code>
     * of the MyMonitorable service are switched off. However, if the
     * MyMonitorable service starts to publish a new <code>StatusVariable</code>
     * later, it's event sending status is on by default.
     *
     * @param path the identifier of the <code>StatusVariable</code>(s) in
     *             [Monitorable_id]/[StatusVariable_id] format, possibly with the
     *             "*" wildcard at the end of either path fragment
     * @param on   <code>false</code> if event sending should be switched off,
     *             <code>true</code> if it should be switched on for the given path
     * @throws java.lang.SecurityException if the caller does not hold
     *                                     <code>MonitorPermission</code> with the
     *                                     <code>switchevents</code> action or if there is any
     *                                     <code>StatusVariable</code> in the <code>path</code> field for
     *                                     which it is not allowed to switch event sending on or off as per
     *                                     the target field of the permission
     * @throws java.lang.IllegalArgumentException
     *                                     if <code>path</code> is
     *                                     <code>null</code> or otherwise invalid, or points to a
     *                                     non-existing <code>StatusVariable</code>
     */
    public void switchEvents(String path, boolean on)
            throws IllegalArgumentException, SecurityException {
        logVisitor.debug("ENTRY: switchEvents: " + path + ", " + on, null);
        try {
            StatusVariablePathFilter filter = new StatusVariablePathFilter(path);

            Set<String> paths = new TreeSet<String>();

            ServiceReference[] monitorableReferences = common.getMonitorableReferences(filter.getMonitorableIdFilter());
            for (ServiceReference monitorableReference : monitorableReferences) {
                String pid = (String) monitorableReference.getProperty(Constants.SERVICE_PID);
                String[] statusVariableNames = common.getStatusVariableNames(pid);
                for (String statusVariableName : statusVariableNames) {
                    if (filter.match(pid, statusVariableName)) {
                        checkPermissions(new StatusVariablePath(pid, statusVariableName), monitorableReference,
                                MonitorPermission.PUBLISH, MonitorPermission.SWITCHEVENTS);
                        paths.add(String.format(MonitorAdminCommon.PATH_PATERN, pid, statusVariableName));
                    }
                }
            }

            if (paths.isEmpty()) {
                throw new IllegalArgumentException(String.format("%s does not point any existing StatusVariables", path));
            }
            common.switchEvents(paths, on);
        } finally {
            logVisitor.debug("EXIT: switchEvents: " + path + ", " + on, null);
        }
    }

    /**
     * Starts a time based <code>MonitoringJob</code> with the parameters
     * provided. Monitoring events will be sent according to the specified
     * schedule. All specified <code>StatusVariable</code>s must exist when the
     * job is started. The initiator string is used in the
     * <code>mon.listener.id</code> field of all events triggered by the job,
     * to allow filtering the events based on the initiator.
     * <p/>
     * The <code>schedule</code> parameter specifies the time in seconds
     * between two measurements, it must be greater than 0.  The first
     * measurement will be taken when the timer expires for the first time, not
     * when this method is called.
     * <p/>
     * The <code>count</code> parameter defines the number of measurements to be
     * taken, and must either be a positive integer, or 0 if the measurement is
     * to run until explicitly stopped.
     * <p/>
     * The entity which initiates a <code>MonitoringJob</code> needs to hold
     * <code>MonitorPermission</code> for all the specified target
     * <code>StatusVariable</code>s with the <code>startjob</code> action
     * present. If the permission's action string specifies a minimal sampling
     * interval then the <code>schedule</code> parameter should be at least as
     * great as the value in the action string.
     *
     * @param initiator       the identifier of the entity that initiated the job
     * @param statusVariables the list of <code>StatusVariable</code>s to be
     *                        monitored, with each <code>StatusVariable</code> name given in
     *                        [Monitorable_PID]/[StatusVariable_ID] format
     * @param schedule        the time in seconds between two measurements
     * @param count           the number of measurements to be taken, or 0 for the
     *                        measurement to run until explicitly stopped
     * @return the successfully started job object, cannot be <code>null</code>
     * @throws java.lang.IllegalArgumentException
     *                                     if the list of
     *                                     <code>StatusVariable</code> names contains an invalid or
     *                                     non-existing <code>StatusVariable</code>; if
     *                                     <code>initiator</code> is <code>null</code> or empty; or if the
     *                                     <code>schedule</code> or <code>count</code> parameters are
     *                                     invalid
     * @throws java.lang.SecurityException if the caller does not hold
     *                                     <code>MonitorPermission</code> for all the specified
     *                                     <code>StatusVariable</code>s, with the <code>startjob</code>
     *                                     action present, or if the permission does not allow starting the
     *                                     job with the given frequency
     */
    public MonitoringJob startScheduledJob(String initiator, String[] statusVariables, int schedule, int count)
            throws IllegalArgumentException, SecurityException {
        logVisitor.debug("ENTRY: startScheduledJob: " + initiator, null);
        try {
            if (initiator == null) {
                throw new IllegalArgumentException("Initiator is null");
            }
            if (statusVariables == null) {
                throw new IllegalArgumentException("StatusVariables are null");
            }
            if (schedule <= 0) {
                throw new IllegalArgumentException("Schedule is invalid: " + count);
            }
            if (count < 0) {
                throw new IllegalArgumentException("Count is invalid: " + count);
            }
            for (String path : statusVariables) {
                StatusVariablePath statusVariablePath = new StatusVariablePath(path);
                ServiceReference monitorableReference = common.findMonitorableReferenceById(statusVariablePath.getMonitorableId());
                String pid = (String) monitorableReference.getProperty(Constants.SERVICE_PID);

                checkPermissions(new StatusVariablePath(pid, statusVariablePath.getStatusVariableId()), monitorableReference,
                        MonitorPermission.PUBLISH, String.format(STARTJOB_PERMISSION_PATTERN, schedule));
            }
            ScheduledMonitoringJob job = new ScheduledMonitoringJob(common, logVisitor, initiator,
                    statusVariables, schedule, count);
            common.addJob(job);
            logVisitor.info("New Scheduled Job is started: " + initiator, null);
            return job;
        } finally {
            logVisitor.debug("EXIT: startScheduledJob: " + initiator, null);
        }
    }

    /**
     * Starts a change based <code>MonitoringJob</code> with the parameters
     * provided. Monitoring events will be sent when the
     * <code>StatusVariable</code>s of this job are updated. All specified
     * <code>StatusVariable</code>s must exist when the job is started, and
     * all must support update notifications. The initiator string is used in
     * the <code>mon.listener.id</code> field of all events triggered by the
     * job, to allow filtering the events based on the initiator.
     * <p/>
     * The <code>count</code> parameter specifies the number of changes that
     * must happen to a <code>StatusVariable</code> before a new notification is
     * sent, this must be a positive integer.
     * <p/>
     * The entity which initiates a <code>MonitoringJob</code> needs to hold
     * <code>MonitorPermission</code> for all the specified target
     * <code>StatusVariable</code>s with the <code>startjob</code> action
     * present.
     *
     * @param initiator       the identifier of the entity that initiated the job
     * @param statusVariables the list of <code>StatusVariable</code>s to be
     *                        monitored, with each <code>StatusVariable</code> name given in
     *                        [Monitorable_PID]/[StatusVariable_ID] format
     * @param count           the number of changes that must happen to a
     *                        <code>StatusVariable</code> before a new notification is sent
     * @return the successfully started job object, cannot be <code>null</code>
     * @throws java.lang.IllegalArgumentException
     *                                     if the list of
     *                                     <code>StatusVariable</code> names contains an invalid or
     *                                     non-existing <code>StatusVariable</code>, or one that does not
     *                                     support notifications; if the <code>initiator</code> is
     *                                     <code>null</code> or empty; or if <code>count</code> is invalid
     * @throws java.lang.SecurityException if the caller does not hold
     *                                     <code>MonitorPermission</code> for all the specified
     *                                     <code>StatusVariable</code>s, with the <code>startjob</code>
     *                                     action present
     */
    public MonitoringJob startJob(String initiator, String[] statusVariables, int count)
            throws IllegalArgumentException, SecurityException {
        logVisitor.debug("ENTRY: startJob: " + initiator, null);
        try {
            if (initiator == null) {
                throw new IllegalArgumentException("Initiator is null");
            }
            if (statusVariables == null) {
                throw new IllegalArgumentException("StatusVariables are null");
            }
            if (count <= 0) {
                throw new IllegalArgumentException("Count is invalid: " + count);
            }
            for (String path : statusVariables) {
                StatusVariablePath statusVariablePath = new StatusVariablePath(path);
                ServiceReference monitorableReference = common.findMonitorableReferenceById(statusVariablePath.getMonitorableId());
                String pid = (String) monitorableReference.getProperty(Constants.SERVICE_PID);

                if (!common.notifiesOnChange(monitorableReference, statusVariablePath.getStatusVariableId())) {
                    throw new IllegalArgumentException("StatusVariable: " + path + " does not support notifications");
                }

                checkPermissions(new StatusVariablePath(pid, statusVariablePath.getStatusVariableId()), monitorableReference,
                        MonitorPermission.PUBLISH, MonitorPermission.STARTJOB);
            }
            SubscriptionMonitoringJob job = new SubscriptionMonitoringJob(common, logVisitor, initiator, statusVariables, count);

            common.addJob(job);

            logVisitor.info("New Subscription Job is started: " + initiator, null);
            return job;
        } finally {
            logVisitor.debug("EXIT: startJob: " + initiator, null);
        }
    }

    /**
     * Returns the list of currently running <code>MonitoringJob</code>s.
     * Jobs are only visible to callers that have the necessary permissions: to
     * receive a Monitoring Job in the returned list, the caller must hold all
     * permissions required for starting the job.  This means that if the caller
     * does not have <code>MonitorPermission</code> with the proper
     * <code>startjob</code> action for all the Status Variables monitored by a
     * job, then that job will be silently omitted from the results.
     * <p/>
     * The returned array cannot be <code>null</code>, an empty array is
     * returned if there are no running jobs visible to the caller at the time
     * of the call.
     *
     * @return the list of running jobs visible to the caller
     */
    public MonitoringJob[] getRunningJobs() {
        logVisitor.debug("ENTRY: getRunningJobs", null);
        try {
            List<MonitoringJob> runningJobs = common.getRunningJobs();
            List<MonitoringJob> result = new ArrayList<MonitoringJob>();
            for (MonitoringJob runningJob : runningJobs) {
                String[] statusVariableNames = runningJob.getStatusVariableNames();
                String action = String.format(STARTJOB_PERMISSION_PATTERN, runningJob.getSchedule());
                boolean hasPermissions = true;
                if (consumer != null) {
                    for (String statusVariableName : statusVariableNames) {
                        if (!consumer.hasPermission(new MonitorPermission(statusVariableName, action))) {
                            hasPermissions = false;
                            break;
                        }
                    }
                }
                if (hasPermissions) {
                    result.add(runningJob);
                }
            }
            return result.toArray(new MonitoringJob[result.size()]);
        } finally {
            logVisitor.debug("EXIT: getRunningJobs", null);
        }
    }
}
TOP

Related Classes of org.knowhowlab.osgi.monitoradmin.MonitorAdminImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.