Author: donsez
Date: Wed Jul 11 14:08:51 2007
New Revision: 555399
URL: http://svn.apache.org/viewvc?view=rev&rev=555399
Log:
refactor org.apache.felix.monitor --> org.apache.felix.sandbox.monitor
Added:
felix/sandbox/donsez/monitoradmin/src/main/java/org/apache/felix/sandbox/
felix/sandbox/donsez/monitoradmin/src/main/java/org/apache/felix/sandbox/monitor/
felix/sandbox/donsez/monitoradmin/src/main/java/org/apache/felix/sandbox/monitor/Constants.java
(with props)
felix/sandbox/donsez/monitoradmin/src/main/java/org/apache/felix/sandbox/monitor/MonitorAdminImpl.java
(with props)
Removed:
felix/sandbox/donsez/monitoradmin/src/main/java/org/apache/felix/monitor/
Modified:
felix/sandbox/donsez/monitoradmin/pom.xml
Modified: felix/sandbox/donsez/monitoradmin/pom.xml
URL:
http://svn.apache.org/viewvc/felix/sandbox/donsez/monitoradmin/pom.xml?view=diff&rev=555399&r1=555398&r2=555399
==============================================================================
--- felix/sandbox/donsez/monitoradmin/pom.xml (original)
+++ felix/sandbox/donsez/monitoradmin/pom.xml Wed Jul 11 14:08:51 2007
@@ -32,7 +32,7 @@
<modelVersion>4.0.0</modelVersion>
<packaging>bundle</packaging>
<name>Apache Felix Monitor Admin</name>
- <artifactId>org.apache.felix.monitor</artifactId>
+ <artifactId>org.apache.felix.sandbox.monitor</artifactId>
<description>${description}</description>
<dependencies>
Added:
felix/sandbox/donsez/monitoradmin/src/main/java/org/apache/felix/sandbox/monitor/Constants.java
URL:
http://svn.apache.org/viewvc/felix/sandbox/donsez/monitoradmin/src/main/java/org/apache/felix/sandbox/monitor/Constants.java?view=auto&rev=555399
==============================================================================
---
felix/sandbox/donsez/monitoradmin/src/main/java/org/apache/felix/sandbox/monitor/Constants.java
(added)
+++
felix/sandbox/donsez/monitoradmin/src/main/java/org/apache/felix/sandbox/monitor/Constants.java
Wed Jul 11 14:08:51 2007
@@ -0,0 +1,37 @@
+/*
+ * 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.felix.sandbox.monitor;
+
+/**
+ * this interface provides constants related to the Monitor Admin.
+ * @author <a href="mailto:[EMAIL PROTECTED]">Felix Project Team</a>
+ */
+
+public interface Constants {
+ // The events posted by MonitorAdmin contain the following properties:
+ public final static String TOPIC = "org/osgi/service/monitor";
+ // The identifier of the Monitorable
+ public final static String MON_MONITORABLE_PID="mon.monitorable.pid";
+ // The identifier of the StatusVariable within the given Monitorable
+ public final static String
MON_STATUSVARIABLE_NAME="mon.statusvariable.name";
+ // The value of the StatusVariable, represented as a String
+ public final static String
MON_STATUSVARIABLE_VALUE="mon.statusvariable.value";
+ // The identifier of the initiator of the monitoring job (only present
if the event was generated due to a monitoring job)
+ public final static String MON_LISTENER_ID="mon.listener.id";
+}
Propchange:
felix/sandbox/donsez/monitoradmin/src/main/java/org/apache/felix/sandbox/monitor/Constants.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
felix/sandbox/donsez/monitoradmin/src/main/java/org/apache/felix/sandbox/monitor/MonitorAdminImpl.java
URL:
http://svn.apache.org/viewvc/felix/sandbox/donsez/monitoradmin/src/main/java/org/apache/felix/sandbox/monitor/MonitorAdminImpl.java?view=auto&rev=555399
==============================================================================
---
felix/sandbox/donsez/monitoradmin/src/main/java/org/apache/felix/sandbox/monitor/MonitorAdminImpl.java
(added)
+++
felix/sandbox/donsez/monitoradmin/src/main/java/org/apache/felix/sandbox/monitor/MonitorAdminImpl.java
Wed Jul 11 14:08:51 2007
@@ -0,0 +1,912 @@
+/*
+ * 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.felix.sandbox.monitor;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+import org.osgi.service.monitor.MonitorAdmin;
+import org.osgi.service.monitor.MonitorListener;
+import org.osgi.service.monitor.Monitorable;
+import org.osgi.service.monitor.MonitoringJob;
+import org.osgi.service.monitor.StatusVariable;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+
+/**
+ * this class provides an implementation of the Monitor Admin.
+ * @author <a href="mailto:[EMAIL PROTECTED]">Felix Project Team</a>
+ */
+
+public class MonitorAdminImpl implements BundleActivator, ServiceFactory,
org.apache.felix.sandbox.monitor.Constants {
+
+ class MonitoringJobImpl implements MonitoringJob, MonitorListener {
+
+ private MonitorAdminProxy monitorAdminProxy;
+
+ private String initiator;
+
+ private String[] statusVariables;
+
+ private int schedule;
+
+ private int count;
+
+ private boolean isStopped=false;
+
+ private int currentCounter=0;
+
+ private Thread thread;
+
+ /**
+ * @param monitorAdminProxy
+ * the monitorAdminProxy which start the job
+ * @param initiator
+ * the identifier of the entity that initiated the
job
+ * @param statusVariables
+ * the list of StatusVariables to be monitored, with
each
+ * StatusVariable name given in
+ * [Monitorable_PID]/[StatusVariable_ID] format
+ * @param count
+ * the number of changes that must happen to a
StatusVariable
+ * before a new notification is sent
+ * @throws IllegalArgumentException
+ * @throws SecurityException
+ */
+ public MonitoringJobImpl(
+ MonitorAdminProxy monitorAdminProxy, String
initiator,
+ String[] statusVariables, int count)
+ throws IllegalArgumentException,
SecurityException {
+ this.monitorAdminProxy = monitorAdminProxy;
+ this.initiator = initiator;
+ this.statusVariables = statusVariables;
+ this.count = count;
+ this.schedule = 0;
+
+ subscribeStatusVariables();
+ }
+
+
+ /**
+ * @param monitorAdminProxy
+ * the monitorAdminProxy which start the job
+ * @param initiator
+ * the identifier of the entity that initiated the
job
+ * @param statusVariables
+ * the list of StatusVariables to be monitored, with
each
+ * StatusVariable 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 explicitely stopped
+ *
+ * @throws IllegalArgumentException
+ * @throws SecurityException
+ */
+ public MonitoringJobImpl(
+ MonitorAdminProxy monitorAdminProxy, String
initiator,
+ String[] statusVariables, int schedule, int
count)
+ throws IllegalArgumentException,
SecurityException {
+ this.monitorAdminProxy = monitorAdminProxy;
+ this.initiator = initiator;
+ this.statusVariables = statusVariables;
+ this.count = count;
+ this.schedule = schedule;
+
+ thread=new Thread(new MyRunnable());
+ thread.start();
+ }
+
+ class MyRunnable implements Runnable {
+
+ public void run() {
+ while(!isStopped){ // TODO check if
notification is before or after the sleep ?
+ for(int
i=0;i<statusVariables.length;i++){
+ String path=statusVariables[i];
+ StatusVariable
statusVariable=monitorAdminProxy.getStatusVariable(path);
+
updated(path.substring(0,path.indexOf('/')),statusVariable);
+ }
+
+ if(--count>0){
+ isStopped=true;
+ }
+
+ try {
+ Thread.sleep(schedule*1000);
+ } catch (InterruptedException e) {
+ }
+ // if(isStopped) break;
+
+ }
+ }
+ }
+
+ public void stop() {
+ isStopped=true;
+ unsubscribeStatusVariables();
+ monitorAdminProxy.monitoringJobs.remove(this);
+ }
+
+ private void subscribeStatusVariables() {
+ for(int i=0;i<statusVariables.length;i++){
+ String statusVariableName=statusVariables[i];
+ List
list=(List)subscriptions.get(statusVariableName);
+ if(list==null) {
+ list=new LinkedList();
+
subscriptions.put(statusVariableName,list);
+ }
+ list.add(this);
+ }
+ }
+
+ private void unsubscribeStatusVariables() {
+ for(int i=0;i<statusVariables.length;i++){
+ String statusVariableName=statusVariables[i];
+ List
list=(List)subscriptions.get(statusVariableName);
+ if(list!=null) {
+ list.remove(this);
+ } // else never occurs
+ if(list.isEmpty())
+
subscriptions.remove(statusVariableName);
+ }
+ }
+
+ public String getInitiator() {
+ return initiator;
+ }
+
+ public String[] getStatusVariableNames() {
+ return statusVariables;
+ }
+
+ public long getSchedule() {
+ return schedule;
+ }
+
+ public int getReportCount() {
+ return count;
+ }
+
+ public boolean isLocal() {
+ return true;
+ }
+
+ public void updated(String monitorableId, StatusVariable
statusVariable)
+ throws IllegalArgumentException {
+ if(isStopped) return;
+ if(schedule==0){
+ if((++currentCounter)<count) return;
+ currentCounter=0;
+ } else {
+ // TODO
+
+ }
+
+ if (monitorableId == null)
+ throw new IllegalArgumentException("null
monitorableId");
+ if (statusVariable == null)
+ throw new IllegalArgumentException("null
statusVariable");
+ String topic = TOPIC;
+ Dictionary properties = new Hashtable();
+ properties.put("mon.monitorable.pid", monitorableId);
+ properties.put("mon.statusvariable.name",
statusVariable.getID());
+
+ Object value = null;
+ switch (statusVariable.getType()) { // TODO
float->double, int->long
+ case StatusVariable.TYPE_BOOLEAN:
+ value = new
Boolean(statusVariable.getBoolean());
+ break;
+ case StatusVariable.TYPE_FLOAT:
+ value = new Float(statusVariable.getFloat());
+ break;
+ case StatusVariable.TYPE_INTEGER:
+ value = new
Integer(statusVariable.getInteger());
+ break;
+ case StatusVariable.TYPE_STRING:
+ value = statusVariable.getString();
+ break;
+ }
+ properties.put(MON_STATUSVARIABLE_VALUE, value);
+ properties.put(MON_LISTENER_ID, initiator);
+ Event event = new Event(topic, properties);
+ EventAdmin eventAdmin = (EventAdmin)
eventAdminServiceTracker
+ .getService();
+ if (eventAdmin != null)
+ eventAdmin.sendEvent(event);
+ }
+ }
+
+ class MonitorAdminServiceFactory implements ServiceFactory {
+
+ List monitorAdminProxies = new ArrayList();
+
+ MonitorAdminImpl monitorAdminImpl;
+
+ MonitorAdminServiceFactory(MonitorAdminImpl monitorAdminImpl) {
+ this.monitorAdminImpl = monitorAdminImpl;
+ }
+
+ public Object getService(Bundle bundle,
+ ServiceRegistration serviceRegistration) {
+ MonitorAdminProxy monitorAdminProxy = new
MonitorAdminProxy(bundle,
+ monitorAdminImpl);
+ monitorAdminProxies.add(monitorAdminProxy);
+ return monitorAdminProxy;
+ }
+
+ public void ungetService(Bundle bundle,
+ ServiceRegistration serviceRegistration, Object
object) {
+ monitorAdminProxies.remove(object);
+ }
+ }
+
+ class MonitorAdminProxy implements MonitorAdmin {
+ Bundle bundle;
+
+ MonitorAdminImpl monitorAdminImpl;
+
+ List monitoringJobs = new ArrayList();
+
+ MonitorAdminProxy(Bundle bundle, MonitorAdminImpl
monitorAdminImpl) {
+ this.bundle = bundle;
+ this.monitorAdminImpl = monitorAdminImpl;
+ }
+
+ /**
+ * ? Returns a StatusVariable addressed by its full path. The
entity
+ * which queries a StatusVariable needs to hold
MonitorPermission for
+ * the given target with the read action present.
+ *
+ * @param path
+ * the full path of the StatusVariable in
+ * [Monitorable_ID]/[StatusVariable_ID] format
+ * @return the StatusVariable object
+ * @throws IllegalArgumentException
+ * if path is null or otherwise invalid, or points
to a
+ * non-existing StatusVariable
+ * @throws SecurityException
+ * if the caller does not hold a MonitorPermission
for the
+ * StatusVariable specified by path with the read
action
+ * present
+ */
+ public StatusVariable getStatusVariable(String path)
+ throws IllegalArgumentException,
SecurityException {
+ checkPermissions();
+
+ if (path == null)
+ throw new IllegalArgumentException("null path");
+ int pos = path.indexOf('/');
+ if (pos <= 0 || pos == path.length() - 1)
+ throw new IllegalArgumentException("invalid
path");
+ String pid = path.substring(0, pos);
+ String name = path.substring(pos + 1);
+ MonitorableEntry monitorableEntry = (MonitorableEntry)
monitorables
+ .get(pid);
+ if (monitorableEntry == null)
+ throw new IllegalArgumentException(
+ "no such monitorable service
for this pid");
+ return
monitorableEntry.monitorable.getStatusVariable(name);
+ }
+
+ /**
+ * The Monitorable instances are not accessible through the
+ * MonitorAdmin, so that requests to individual status
variables can be
+ * filtered with respect to the publishing rights of the
Monitorable and
+ * the reading rights of the caller. The returned array
contains the
+ * names in alphabetical order. It cannot be null, an empty
array is
+ * returned if no Monitorable services are registered. Returns
the array
+ * of Monitorable names
+ *
+ * @return the names of the Monitorable services that are
currently
+ * registered.
+ */
+ public String[] getMonitorableNames() {
+ SortedSet pids = new TreeSet();
+ Iterator iterator = monitorables.keySet().iterator();
+ while (iterator.hasNext()) {
+ String pid = (String) iterator.next();
+ pids.add(pid);
+ }
+ return (String[]) pids.toArray(new String[pids.size()]);
+ }
+
+ /**
+ * The StatusVariables 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: the specified
Monitorable holds a
+ * MonitorPermission for the status variable with the publish
action
+ * present the caller holds a MonitorPermission for the status
+ * variable with the read action present
+ * <p>
+ * The elements in the returned array are in no particular
order. The
+ * return value cannot be null, an empty array is returned if no
+ * (authorized and readable) Status Variables are provided by
the given
+ * Monitorable. Returns a list of StatusVariable objects
published by
+ * the specified Monitorable
+ *
+ * @param monitorableId
+ * the identifier of a Monitorable instance
+ * @return the StatusVariable objects published by a Monitorable
+ * instance.
+ * @throws IllegalArgumentException
+ * if monitorableId is null or otherwise invalid,
or points
+ * to a non-existing Monitorable
+ */
+ public StatusVariable[] getStatusVariables(String monitorableId)
+ throws IllegalArgumentException {
+ checkPermissions();
+ if (monitorableId == null)
+ throw new IllegalArgumentException("null
monitorableId");
+ MonitorableEntry monitorableEntry = (MonitorableEntry)
monitorables
+ .get(monitorableId);
+ if (monitorableEntry == null)
+ throw new IllegalArgumentException(
+ "no such monitorable service
for this pid");
+ Monitorable monitorable = monitorableEntry.monitorable;
+ String[] statusVariableNames =
monitorableEntry.statusVariableNames;
+ StatusVariable[] statusVariables = new
StatusVariable[statusVariableNames.length];
+ for (int i = 0; i < statusVariableNames.length; i++) {
+ statusVariables[i] = monitorable
+
.getStatusVariable(statusVariableNames[i]);
+ }
+ return statusVariables;
+ }
+
+ /**
+ * ? Returns the list of StatusVariable names published by a
+ * Monitorable instance. Only those status variables are listed
where
+ * the following two conditions are met: the specified
Monitorable
+ * holds a MonitorPermission for the status variable with the
publish
+ * action present the caller holds a MonitorPermission for
the status
+ * variable with the read action present The returned array
does not
+ * contain duplicates, and the elements are in alphabetical
order. It
+ * cannot be null, an empty array is returned if no (authorized
and
+ * readable) Status Variables are provided by the given
Monitorable.
+ *
+ * @param monitorableId
+ * the identifier of a Monitorable instance
+ * @return a list of StatusVariable objects names published by
the
+ * specified Monitorable
+ * @throws IllegalArgumentException
+ * if monitorableId is null or otherwise invalid,
or points
+ * to a non-existing Monitorable
+ */
+ public String[] getStatusVariableNames(String monitorableId)
+ throws IllegalArgumentException {
+ checkPermissions();
+ if (monitorableId == null)
+ throw new IllegalArgumentException("null
monitorableId");
+ MonitorableEntry monitorableEntry = (MonitorableEntry)
monitorables
+ .get(monitorableId);
+ if (monitorableEntry == null)
+ throw new IllegalArgumentException(
+ "no such monitorable service
for this pid");
+ return monitorableEntry.statusVariableNames;
+ }
+
+ /**
+ * ? Switches event sending on or off for the specified
+ * StatusVariables. When the MonitorAdmin is notified about a
+ * StatusVariable 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 StatusVariables
must not
+ * be persistently stored. When a StatusVariable 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
+ * StatusVariable at the time of the method call, it does not
affect the
+ * event sending status of StatusVariables which are not yet
registered.
+ * As an example, when the switchEvents(MyMonitorable/ ,
false) method
+ * is executed, event sending from all StatusVariables of the
+ * MyMonitorable service are switched off. However, if the
MyMonitorable
+ * service starts to publish a new StatusVariable later, its
event
+ * sending status is on by default.
+ *
+ * @param path
+ * the identifier of the StatusVariable(s) in
+ * [Monitorable_id]/ [StatusVariable_id] format,
possibly
+ * with the * wildcard at the end of either path
fragment
+ * @param on
+ * false if event sending should be switched off,
true if it
+ * should be switched on for the given path
+ * @throws SecurityException
+ * if the caller does not hold MonitorPermission
with the
+ * switchevents action or if there is any
StatusVariable in
+ * the path field for which it is not allowed to
switch
+ * event sending on or off as per the target field
of the
+ * permission
+ * @throws IllegalArgumentException
+ * if path is null or otherwise invalid, or points
to a
+ * non-existing StatusVariable
+ * @see
org.osgi.service.monitor.MonitorAdmin#switchEvents(java.lang.String,
+ * boolean)
+ */
+ public void switchEvents(String path, boolean on)
+ throws IllegalArgumentException,
SecurityException {
+ checkPermissions();
+ // TODO
+ throw new IllegalArgumentException("not implemented");
+ }
+
+ /**
+ * ? Issues a request to reset a given StatusVariable.
Depending on the
+ * semantics of the StatusVariable this call may or may not
succeed: it
+ * makes sense to reset a counter to its starting value, but
e.g. a
+ * StatusVariable of type String might not have a meaningful
default
+ * value. Note that for numeric Status- Variables the starting
value may
+ * not necessarily be 0. Resetting a StatusVariable triggers a
monitor
+ * event if the StatusVariable supports update notifications.
+ * <p>
+ * The entity that wants to reset the StatusVariable needs to
hold
+ * MonitorPermission with the reset action present. The target
field of
+ * the permission must match the StatusVariable name to be
reset.
+ *
+ * @param path
+ * the identifier of the StatusVariable in
+ * [Monitorable_id]/[StatusVariable_id] format
+ * @return true if the Monitorable could successfully reset the
given
+ * StatusVariable, false otherwise
+ * @throws IllegalArgumentException
+ * if path is null or otherwise invalid, or points
to a
+ * non-existing StatusVariable
+ * @throws SecurityException
+ * if the caller does not hold MonitorPermission
with the
+ * reset action or if the specified StatusVariable
is not
+ * allowed to be reset as per the target field of
the
+ * permission
+ * @see
org.osgi.service.monitor.MonitorAdmin#resetStatusVariable(java.lang.String)
+ */
+ public boolean resetStatusVariable(String path)
+ throws IllegalArgumentException,
SecurityException {
+ checkPermissions();
+ if (path == null)
+ throw new IllegalArgumentException("null path");
+ int pos = path.indexOf('/');
+ if (pos <= 0 || pos == path.length() - 1)
+ throw new IllegalArgumentException("invalid
path");
+ String pid = path.substring(0, pos);
+ String name = path.substring(pos + 1);
+ MonitorableEntry monitorableEntry = (MonitorableEntry)
monitorables
+ .get(pid);
+ if (monitorableEntry == null)
+ throw new IllegalArgumentException(
+ "no such monitorable service
for this pid");
+ return
monitorableEntry.monitorable.resetStatusVariable(name);
+ }
+
+ /**
+ * The entity that queries a StatusVariable needs to hold
+ * MonitorPermission for the given target with the read action
present.
+ *
+ * @param path
+ * the full path of the StatusVariable in
+ * [Monitorable_ID]/[StatusVariable_ID] format
?return a
+ * human readable description of the given
StatusVariable.
+ * The null value may be returned if there is no
description
+ * for the given StatusVariable.
+ * @eturn the human readable description of this StatusVariable
or null
+ * if it is not set
+ * @throws IllegalArgumentException
+ * if path is null or otherwise invalid, or points
to a
+ * non-existing StatusVariable
+ * @throwsSecurityException if the caller does not hold a
+ * MonitorPermission for the
StatusVariable
+ * specified by path with the read
action
+ * present *
+ * @see
org.osgi.service.monitor.MonitorAdmin#getDescription(java.lang.String)
+ */
+ public String getDescription(String path)
+ throws IllegalArgumentException,
SecurityException {
+ checkPermissions();
+ if (path == null)
+ throw new IllegalArgumentException("null path");
+ int pos = path.indexOf('/');
+ if (pos <= 0 || pos == path.length() - 1)
+ throw new IllegalArgumentException("invalid
path");
+ String pid = path.substring(0, pos);
+ String name = path.substring(pos + 1);
+ MonitorableEntry monitorableEntry = (MonitorableEntry)
monitorables
+ .get(pid);
+ if (monitorableEntry == null)
+ throw new IllegalArgumentException(
+ "no such monitorable service
for this pid");
+ return
monitorableEntry.monitorable.getDescription(name);
+ }
+
+ /**
+ * ? Starts a time based MonitoringJob with the parameters
provided.
+ * Monitoring events will be sent according to the specified
schedule.
+ * All specified StatusVariables must exist when the job is
started. The
+ * initiator string is used in the mon.listener.id field of all
events
+ * triggered by the job, to allow filtering the events based on
the
+ * initiator.
+ * <p>
+ * The schedule 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 count 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 explicitely stopped.
+ * <p>
+ * The entity which initiates a MonitoringJob needs to hold
+ * MonitorPermission for all the specified target
StatusVariables with
+ * the startjob action present. If the permissions action
string
+ * specifies a minimal sampling interval then the schedule
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 StatusVariables to be monitored, with
each
+ * StatusVariable 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 explicitely stopped
+ *
+ * @return the successfully started job object, cannot be null
+ * @throws IllegalArgumentException
+ * if the list of StatusVariable names contains an
invalid
+ * or non-existing StatusVariable; if initiator is
null or
+ * empty; or if the schedule or count parameters
are invalid
+ * @throws SecurityException
+ * if the caller does not hold MonitorPermission
for all the
+ * specified StatusVariables, with the startjob
action
+ * present, or if the permission does not allow
starting the
+ * job with the given frequency
+ * @see
org.osgi.service.monitor.MonitorAdmin#startScheduledJob(java.lang.String,
+ * java.lang.String[], int, int)
+ */
+ public MonitoringJob startScheduledJob(String initiator,
+ String[] statusVariables, int schedule, int
count)
+ throws IllegalArgumentException,
SecurityException {
+ checkPermissions();
+ MonitoringJob monitoringJob = new
MonitoringJobImpl(this,
+ initiator, statusVariables, schedule,
count);
+ monitoringJobs.add(monitoringJob);
+ return monitoringJob;
+ }
+
+ /**
+ * Starts a change based MonitoringJob with the parameters
provided.
+ * Monitoring events will be sent when the StatusVariables of
this job
+ * are updated. All specified StatusVariables must exist when
the job is
+ * started, and all must support update notifications. The
initiator
+ * string is used in the mon.listener. id field of all events
triggered
+ * by the job, to allow filtering the events based on the
initiator.
+ * <p>
+ * The count parameter specifies the number of changes that
must happen
+ * to a StatusVariable before a new notification is sent, this
must be a
+ * positive integer.
+ * <p>
+ * The entity which initiates a MonitoringJob needs to hold
+ * MonitorPermission for all the specified target
StatusVariables with
+ * the startjob action present.
+ *
+ * @param initiator
+ * the identifier of the entity that initiated the
job
+ * @param statusVariables
+ * the list of StatusVariables to be monitored, with
each
+ * StatusVariable name given in
+ * [Monitorable_PID]/[StatusVariable_ID] format
+ * @param count
+ * the number of changes that must happen to a
StatusVariable
+ * before a new notification is sent
+ *
+ * @return the successfully started job object, cannot be null
+ * @throws IllegalArgumentException
+ * if the list of StatusVariable names contains an
invalid
+ * or non-existing StatusVariable, or one that does
not
+ * support notifications; if the initiator is null
or empty;
+ * or if count is invalid
+ * @throws SecurityException
+ * if the caller does not hold MonitorPermission
for all the
+ * specified StatusVariables, with the startjob
action
+ * present
+ * @see
org.osgi.service.monitor.MonitorAdmin#startJob(java.lang.String,
+ * java.lang.String[], int)
+ */
+ public MonitoringJob startJob(String initiator,
+ String[] statusVariables, int count)
+ throws IllegalArgumentException,
SecurityException {
+ checkPermissions();
+ MonitoringJob monitoringJob = new
MonitoringJobImpl(this,
+ initiator, statusVariables, count);
+ monitoringJobs.add(monitoringJob);
+ return monitoringJob;
+ }
+
+ /*
+ * Returns the list of currently running MonitoringJobs. 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 MonitorPermission with the proper
startjob
+ * action for all the Status Variables monitored by a job, then
that job
+ * will be silently omitted from the results. The returned
array cannot
+ * be null, an empty array is returned if there are no running
jobs
+ * visible to the caller at the time of the call. Returns the
list of
+ * running jobs visible to the caller
+ *
+ * @see org.osgi.service.monitor.MonitorAdmin#getRunningJobs()
+ */
+ public MonitoringJob[] getRunningJobs() {
+ return (MonitoringJob[]) monitoringJobs
+ .toArray(new
MonitoringJob[monitoringJobs.size()]);
+ }
+
+ private void checkPermissions() throws SecurityException {
+ // TODO
+
+ }
+ }
+
+ class MonitorListenerServiceFactory implements ServiceFactory {
+
+ List monitorListenerProxies = new ArrayList();
+
+ MonitorAdminImpl monitorAdminImpl;
+
+ MonitorListenerServiceFactory(MonitorAdminImpl
monitorAdminImpl) {
+ this.monitorAdminImpl = monitorAdminImpl;
+ }
+
+ public Object getService(Bundle bundle,
+ ServiceRegistration serviceRegistration) {
+ MonitorListenerProxy monitorListenerProxy = new
MonitorListenerProxy(
+ bundle, monitorAdminImpl);
+ monitorListenerProxies.add(monitorListenerProxy);
+ return monitorListenerProxy;
+ }
+
+ public void ungetService(Bundle bundle,
+ ServiceRegistration serviceRegistration, Object
object) {
+ monitorListenerProxies.remove(object);
+ }
+ }
+
+ class MonitorListenerProxy implements MonitorListener {
+ Bundle bundle;
+
+ MonitorAdminImpl monitorAdminImpl;
+
+ MonitorListenerProxy(Bundle bundle, MonitorAdminImpl
monitorAdminImpl) {
+ this.bundle = bundle;
+ this.monitorAdminImpl = monitorAdminImpl;
+ }
+
+ /**
+ * ? Callback for notification of a StatusVariable change.
+ *
+ * @param monitorableId
+ * the identifier of the Monitorable instance
reporting the
+ * change
+ * @param statusVariable
+ * the StatusVariable that has changed
+ * @throws IllegalArgumentException
+ * if the specified monitorable ID is invalid
(null, empty,
+ * or contains illegal characters), or if
statusVariable is
+ * null
+ * @see
org.osgi.service.monitor.MonitorListener#updated(java.lang.String,
+ * org.osgi.service.monitor.StatusVariable)
+ */
+ public void updated(String monitorableId, StatusVariable
statusVariable)
+ throws IllegalArgumentException {
+ if (monitorableId == null)
+ throw new IllegalArgumentException("null
monitorableId");
+ if (statusVariable == null)
+ throw new IllegalArgumentException("null
statusVariable");
+ String topic = TOPIC;
+ Dictionary properties = new Hashtable();
+ properties.put(MON_MONITORABLE_PID, monitorableId);
+ properties.put(MON_STATUSVARIABLE_NAME,
statusVariable.getID());
+
+ Object value = null;
+ switch (statusVariable.getType()) { // TODO
float->double, int->long
+ case StatusVariable.TYPE_BOOLEAN:
+ value = new
Boolean(statusVariable.getBoolean());
+ break;
+ case StatusVariable.TYPE_FLOAT:
+ value = new Float(statusVariable.getFloat());
+ break;
+ case StatusVariable.TYPE_INTEGER:
+ value = new
Integer(statusVariable.getInteger());
+ break;
+ case StatusVariable.TYPE_STRING:
+ value = statusVariable.getString();
+ break;
+ }
+ properties.put(MON_STATUSVARIABLE_VALUE, value);
+ // mon.listener.id: The identifier of the initiator of
the
+ // monitoring job (only present if the event was
generated due to a
+ // monitoring job))
+ Event event = new Event(topic, properties);
+ EventAdmin eventAdmin = (EventAdmin)
eventAdminServiceTracker
+ .getService();
+ if (eventAdmin != null)
+ eventAdmin.sendEvent(event);
+
+ // broadcast to MonitoringJob
+ StringBuffer sb=new StringBuffer(monitorableId);
+ sb.append('/').append(statusVariable.getID());
+ String path=sb.toString();
+ List list=(List)subscriptions.get(path);
+ if(list!=null) {
+ Iterator iterator=list.iterator();
+ while(iterator.hasNext()){
+ MonitoringJobImpl
monitoringJobImpl=(MonitoringJobImpl)iterator.next();
+
monitoringJobImpl.updated(monitorableId,statusVariable);
+ }
+ }
+ }
+ }
+
+ class MonitorableEntry {
+ Monitorable monitorable;
+
+ String pid;
+
+ String[] statusVariableNames;
+
+ MonitorableEntry(Monitorable monitorable, String pid,
+ String[] statusVariableNames) {
+ this.monitorable = monitorable;
+ this.pid = pid;
+ this.statusVariableNames = statusVariableNames;
+ }
+ }
+
+ class MyServiceTrackerCustomizerForMonitorable implements
+ ServiceTrackerCustomizer {
+
+ public Object addingService(ServiceReference serviceReference) {
+ String pid = (String) serviceReference
+ .getProperty(Constants.SERVICE_PID);
+ if (pid == null) {
+ System.err.println("Warning: The
"+Constants.SERVICE_PID+" of service "+Constants.SERVICE_ID+ " is not setted");
+ return null;
+ }
+
+ if(monitorables.containsKey(pid)){
+ // TODO change for logger
+ System.err.println("Warning: The
"+Constants.SERVICE_PID+"(="+pid+") of service "+Constants.SERVICE_ID+ " is
already registered by another bundle");
+ return null;
+ }
+
+ Monitorable monitorable = (Monitorable) bundleContext
+ .getService(serviceReference);
+ if (monitorable == null)
+ return null;
+ String[] statusVariableNames =
monitorable.getStatusVariableNames();
+ if (statusVariableNames == null ||
statusVariableNames.length == 0) {
+ bundleContext.ungetService(serviceReference);
+ return null;
+ }
+ monitorables.put(pid, new MonitorableEntry(monitorable,
pid,
+ statusVariableNames));
+ return monitorable;
+ }
+
+ public void modifiedService(ServiceReference serviceReference,
+ Object object) {
+ // TODO
+ }
+
+ public void removedService(ServiceReference serviceReference,
+ Object object) {
+ Monitorable monitorable = (Monitorable) object;
+ Iterator iterator = monitorables.entrySet().iterator();
+ while (iterator.hasNext()) {
+ Map.Entry mapEntry = (Map.Entry)
iterator.next();
+ MonitorableEntry monitorableEntry =
(MonitorableEntry) mapEntry
+ .getValue();
+ if
(monitorableEntry.monitorable.equals(monitorable)) {
+ iterator.remove();
+ break;
+ }
+ }
+ bundleContext.ungetService(serviceReference);
+ }
+ }
+
+ private BundleContext bundleContext;
+
+ private ServiceTracker eventAdminServiceTracker;
+
+ private ServiceTracker monitorableServiceTracker;
+
+ private Map monitorables = new HashMap();
+
+ /**
+ * path -> list of MonitoringJobImpl
+ */
+ private Map subscriptions = new HashMap();
+
+
+ public void start(BundleContext bundleContext) throws Exception {
+ this.bundleContext = bundleContext;
+ eventAdminServiceTracker = new ServiceTracker(bundleContext,
+ EventAdmin.class.getName(), null);
+ eventAdminServiceTracker.open();
+
+ monitorableServiceTracker = new ServiceTracker(bundleContext,
+ Monitorable.class.getName(),
+ new MyServiceTrackerCustomizerForMonitorable());
+ monitorableServiceTracker.open();
+
+ bundleContext.registerService(MonitorAdmin.class.getName(),
+ new MonitorAdminServiceFactory(this), null);
+ bundleContext.registerService(MonitorListener.class.getName(),
+ new MonitorListenerServiceFactory(this), null);
+ }
+
+ public void stop(BundleContext context) throws Exception {
+ stopAllMonitoringJobs();
+ monitorableServiceTracker.close(); // unget all services ???
+ Iterator iterator = monitorables.keySet().iterator();
+ while (iterator.hasNext()) {
+ ServiceReference serviceReference = (ServiceReference)
iterator
+ .next();
+ bundleContext.ungetService(serviceReference);
+ }
+ eventAdminServiceTracker.close();
+ }
+
+ private void stopAllMonitoringJobs() {
+ // TODO
+
+ }
+
+ public Object getService(Bundle bundle, ServiceRegistration
serviceRegistration) {
+ // TODO check permission here
+ return this;
+ }
+
+ public void ungetService(Bundle bundle, ServiceRegistration
serviceRegistration, Object servant) {
+ }
+
+}
Propchange:
felix/sandbox/donsez/monitoradmin/src/main/java/org/apache/felix/sandbox/monitor/MonitorAdminImpl.java
------------------------------------------------------------------------------
svn:eol-style = native