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, 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


Reply via email to