felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From don...@apache.org
Subject svn commit: r555399 - in /felix/sandbox/donsez/monitoradmin: ./ src/main/java/org/apache/felix/monitor/ src/main/java/org/apache/felix/sandbox/ src/main/java/org/apache/felix/sandbox/monitor/
Date Wed, 11 Jul 2007 21:08:52 GMT
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:dev@felix.apache.org">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:dev@felix.apache.org">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, it’s 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 permission’s 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



Mime
View raw message