You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ma...@apache.org on 2008/01/30 17:46:39 UTC
svn commit: r616813 [7/9] - in /felix/trunk/deploymentadmin: ./ src/
src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/
src/main/java/org/apache/felix/
src/main/java/org/apache/felix/deploymentadmin/
src/main/java/org/apache/felix/de...
Added: felix/trunk/deploymentadmin/src/main/java/org/osgi/service/metatype/ObjectClassDefinition.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/src/main/java/org/osgi/service/metatype/ObjectClassDefinition.java?rev=616813&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/src/main/java/org/osgi/service/metatype/ObjectClassDefinition.java (added)
+++ felix/trunk/deploymentadmin/src/main/java/org/osgi/service/metatype/ObjectClassDefinition.java Wed Jan 30 08:46:24 2008
@@ -0,0 +1,121 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.metatype/src/org/osgi/service/metatype/ObjectClassDefinition.java,v 1.11 2006/06/16 16:31:23 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2001, 2006). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.osgi.service.metatype;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Description for the data type information of an objectclass.
+ *
+ * @version $Revision: 1.11 $
+ */
+public interface ObjectClassDefinition {
+ /**
+ * Argument for <code>getAttributeDefinitions(int)</code>.
+ * <p>
+ * <code>REQUIRED</code> indicates that only the required definitions are
+ * returned. The value is 1.
+ */
+ public static final int REQUIRED = 1;
+ /**
+ * Argument for <code>getAttributeDefinitions(int)</code>.
+ * <p>
+ * <code>OPTIONAL</code> indicates that only the optional definitions are
+ * returned. The value is 2.
+ */
+ public static final int OPTIONAL = 2;
+ /**
+ * Argument for <code>getAttributeDefinitions(int)</code>.
+ * <p>
+ * <code>ALL</code> indicates that all the definitions are returned. The value
+ * is -1.
+ */
+ public static final int ALL = 0xFFFFFFFF;
+
+ /**
+ * Return the name of this object class.
+ *
+ * The name may be localized.
+ *
+ * @return The name of this object class.
+ */
+ public String getName();
+
+ /**
+ * Return the id of this object class.
+ *
+ * <p>
+ * <code>ObjectDefintion</code> objects share a global namespace in the
+ * registry. They share this aspect with LDAP/X.500 attributes. In these
+ * standards the OSI Object Identifier (OID) is used to uniquely identify
+ * object classes. If such an OID exists, (which can be requested at several
+ * standard organisations and many companies already have a node in the
+ * tree) it can be returned here. Otherwise, a unique id should be returned
+ * which can be a java class name (reverse domain name) or generated with a
+ * GUID algorithm. Note that all LDAP defined object classes already have an
+ * OID associated. It is strongly advised to define the object classes from
+ * existing LDAP schemes which will give the OID for free. Many such schemes
+ * exist ranging from postal addresses to DHCP parameters.
+ *
+ * @return The id of this object class.
+ */
+ public String getID();
+
+ /**
+ * Return a description of this object class.
+ *
+ * The description may be localized.
+ *
+ * @return The description of this object class.
+ */
+ public String getDescription();
+
+ /**
+ * Return the attribute definitions for this object class.
+ *
+ * <p>
+ * Return a set of attributes. The filter parameter can distinguish between
+ * <code>ALL</code>,<code>REQUIRED</code> or the <code>OPTIONAL</code>
+ * attributes.
+ *
+ * @param filter <code>ALL</code>,<code>REQUIRED</code>,<code>OPTIONAL</code>
+ * @return An array of attribute definitions or <code>null</code> if no
+ * attributes are selected
+ */
+ public AttributeDefinition[] getAttributeDefinitions(int filter);
+
+ /**
+ * Return an <code>InputStream</code> object that can be used to create an
+ * icon from.
+ *
+ * <p>
+ * Indicate the size and return an <code>InputStream</code> object containing
+ * an icon. The returned icon maybe larger or smaller than the indicated
+ * size.
+ *
+ * <p>
+ * The icon may depend on the localization.
+ *
+ * @param size Requested size of an icon, e.g. a 16x16 pixels icon then size =
+ * 16
+ * @return An InputStream representing an icon or <code>null</code>
+ * @throws IOException If the <code>InputStream</code> cannot be returned.
+ */
+ public InputStream getIcon(int size) throws IOException;
+}
Added: felix/trunk/deploymentadmin/src/main/java/org/osgi/service/metatype/package.html
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/src/main/java/org/osgi/service/metatype/package.html?rev=616813&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/src/main/java/org/osgi/service/metatype/package.html (added)
+++ felix/trunk/deploymentadmin/src/main/java/org/osgi/service/metatype/package.html Wed Jan 30 08:46:24 2008
@@ -0,0 +1 @@
+<!-- $Header: /cvshome/build/org.osgi.service.metatype/src/org/osgi/service/metatype/package.html,v 1.5 2006/07/12 21:07:16 hargrave Exp $ -->
<BODY>
<p>Metatype Package Version 1.1.
<p>Bundles wishing to use this package must list the package
in the <TT>Import-Package</TT> header of the bundle's manifest.
For example:
<pre>
Import-Package: org.osgi.service.metatype; version=1.1
</pre>
</BODY>
\ No newline at end of file
Added: felix/trunk/deploymentadmin/src/main/java/org/osgi/service/metatype/packageinfo
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/src/main/java/org/osgi/service/metatype/packageinfo?rev=616813&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/src/main/java/org/osgi/service/metatype/packageinfo (added)
+++ felix/trunk/deploymentadmin/src/main/java/org/osgi/service/metatype/packageinfo Wed Jan 30 08:46:24 2008
@@ -0,0 +1 @@
+version 1.1
Added: felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/MonitorAdmin.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/MonitorAdmin.java?rev=616813&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/MonitorAdmin.java (added)
+++ felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/MonitorAdmin.java Wed Jan 30 08:46:24 2008
@@ -0,0 +1,359 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.monitor/src/org/osgi/service/monitor/MonitorAdmin.java,v 1.25 2006/06/16 16:31:25 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2004, 2006). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.service.monitor;
+
+/**
+ * The <code>MonitorAdmin</code> service is a singleton service that handles
+ * <code>StatusVariable</code> query requests and measurement job control
+ * requests.
+ * <p>
+ * Note that an alternative but not recommended way of obtaining
+ * <code>StatusVariable</code>s is that applications having the required
+ * <code>ServicePermissions</code> can query the list of
+ * <code>Monitorable</code> services from the service registry and then query
+ * the list of <code>StatusVariable</code> names from the
+ * <code>Monitorable</code> services. This way all services which publish
+ * <code>StatusVariable</code>s will be returned regardless of whether they
+ * do or do not hold the necessary <code>MonitorPermission</code> for
+ * publishing <code>StatusVariable</code>s. By using the
+ * <code>MonitorAdmin</code> to obtain the <code>StatusVariable</code>s it
+ * is guaranteed that only those <code>Monitorable</code> services will be
+ * accessed who are authorized to publish <code>StatusVariable</code>s. It is
+ * the responsibility of the <code>MonitorAdmin</code> implementation to check
+ * the required permissions and show only those variables which pass this check.
+ * <p>
+ * The events posted by <code>MonitorAdmin</code> contain the following
+ * properties:
+ * <ul>
+ * <li><code>mon.monitorable.pid</code>: The identifier of the
+ * <code>Monitorable</code>
+ * <li><code>mon.statusvariable.name</code>: The identifier of the
+ * <code>StatusVariable</code> within the given <code>Monitorable</code>
+ * <li><code>mon.statusvariable.value</code>: The value of the
+ * <code>StatusVariable</code>, represented as a <code>String</code>
+ * <li><code>mon.listener.id</code>: The identifier of the initiator of the
+ * monitoring job (only present if the event was generated due to a monitoring
+ * job)
+ * </ul>
+ * <p>
+ * Most of the methods require either a Monitorable ID or a Status Variable path
+ * parameter, the latter in [Monitorable_ID]/[StatusVariable_ID] format. These
+ * parameters must not be <code>null</code>, and the IDs they contain must
+ * conform to their respective definitions in {@link Monitorable} and
+ * {@link StatusVariable}. If any of the restrictions are violated, the method
+ * must throw an <code>IllegalArgumentException</code>.
+ */
+public interface MonitorAdmin {
+
+ /**
+ * Returns a <code>StatusVariable</code> addressed by its full path.
+ * The entity which queries a <code>StatusVariable</code> needs to hold
+ * <code>MonitorPermission</code> for the given target with the
+ * <code>read</code> action present.
+ *
+ * @param path the full path of the <code>StatusVariable</code> in
+ * [Monitorable_ID]/[StatusVariable_ID] format
+ * @return the <code>StatusVariable</code> object
+ * @throws java.lang.IllegalArgumentException if <code>path</code> is
+ * <code>null</code> or otherwise invalid, or points to a
+ * non-existing <code>StatusVariable</code>
+ * @throws java.lang.SecurityException if the caller does not hold a
+ * <code>MonitorPermission</code> for the
+ * <code>StatusVariable</code> specified by <code>path</code>
+ * with the <code>read</code> action present
+ */
+ public StatusVariable getStatusVariable(String path)
+ throws IllegalArgumentException, SecurityException;
+
+ /**
+ * Returns the names of the <code>Monitorable</code> services that are
+ * currently registered. The <code>Monitorable</code> instances are not
+ * accessible through the <code>MonitorAdmin</code>, so that requests to
+ * individual status variables can be filtered with respect to the
+ * publishing rights of the <code>Monitorable</code> and the reading
+ * rights of the caller.
+ * <p>
+ * The returned array contains the names in alphabetical order. It cannot be
+ * <code>null</code>, an empty array is returned if no
+ * <code>Monitorable</code> services are registered.
+ *
+ * @return the array of <code>Monitorable</code> names
+ */
+ public String[] getMonitorableNames();
+
+ /**
+ * Returns the <code>StatusVariable</code> objects published by a
+ * <code>Monitorable</code> instance. The <code>StatusVariables</code>
+ * will hold the values taken at the time of this method call. Only those
+ * status variables are returned where the following two conditions are met:
+ * <ul>
+ * <li>the specified <code>Monitorable</code> holds a
+ * <code>MonitorPermission</code> for the status variable with the
+ * <code>publish</code> action present
+ * <li>the caller holds a <code>MonitorPermission</code> for the status
+ * variable with the <code>read</code> action present
+ * </ul>
+ * All other status variables are silently ignored, they are omitted from
+ * the result.
+ * <p>
+ * The elements in the returned array are in no particular order. The return
+ * value cannot be <code>null</code>, an empty array is returned if no
+ * (authorized and readable) Status Variables are provided by the given
+ * <code>Monitorable</code>.
+ *
+ * @param monitorableId the identifier of a <code>Monitorable</code>
+ * instance
+ * @return a list of <code>StatusVariable</code> objects published
+ * by the specified <code>Monitorable</code>
+ * @throws java.lang.IllegalArgumentException if <code>monitorableId</code>
+ * is <code>null</code> or otherwise invalid, or points to a
+ * non-existing <code>Monitorable</code>
+ */
+ public StatusVariable[] getStatusVariables(String monitorableId)
+ throws IllegalArgumentException;
+
+ /**
+ * Returns the list of <code>StatusVariable</code> names published by a
+ * <code>Monitorable</code> instance. Only those status variables are
+ * listed where the following two conditions are met:
+ * <ul>
+ * <li>the specified <code>Monitorable</code> holds a
+ * <code>MonitorPermission</code> for the status variable with the
+ * <code>publish</code> action present
+ * <li>the caller holds a <code>MonitorPermission</code> for
+ * the status variable with the <code>read</code> action present
+ * </ul>
+ * All other status variables are silently ignored, their names are omitted
+ * from the list.
+ * <p>
+ * The returned array does not contain duplicates, and the elements are in
+ * alphabetical order. It cannot be <code>null</code>, an empty array is
+ * returned if no (authorized and readable) Status Variables are provided
+ * by the given <code>Monitorable</code>.
+ *
+ * @param monitorableId the identifier of a <code>Monitorable</code>
+ * instance
+ * @return a list of <code>StatusVariable</code> objects names
+ * published by the specified <code>Monitorable</code>
+ * @throws java.lang.IllegalArgumentException if <code>monitorableId</code>
+ * is <code>null</code> or otherwise invalid, or points to a
+ * non-existing <code>Monitorable</code>
+ */
+ public String[] getStatusVariableNames(String monitorableId)
+ throws IllegalArgumentException;
+
+ /**
+ * Switches event sending on or off for the specified
+ * <code>StatusVariable</code>s. When the <code>MonitorAdmin</code> is
+ * notified about a <code>StatusVariable</code> being updated it sends an
+ * event unless this feature is switched off. Note that events within a
+ * monitoring job can not be switched off. The event sending state of the
+ * <code>StatusVariables</code> must not be persistently stored. When a
+ * <code>StatusVariable</code> is registered for the first time in a
+ * framework session, its event sending state is set to ON by default.
+ * <p>
+ * Usage of the "*" wildcard is allowed in the path argument of this method
+ * as a convenience feature. The wildcard can be used in either or both path
+ * fragments, but only at the end of the fragments. The semantics of the
+ * wildcard is that it stands for any matching <code>StatusVariable</code>
+ * at the time of the method call, it does not affect the event sending
+ * status of <code>StatusVariable</code>s which are not yet registered. As
+ * an example, when the <code>switchEvents("MyMonitorable/*", false)</code>
+ * method is executed, event sending from all <code>StatusVariables</code>
+ * of the MyMonitorable service are switched off. However, if the
+ * MyMonitorable service starts to publish a new <code>StatusVariable</code>
+ * later, it's event sending status is on by default.
+ *
+ * @param path the identifier of the <code>StatusVariable</code>(s) in
+ * [Monitorable_id]/[StatusVariable_id] format, possibly with the
+ * "*" wildcard at the end of either path fragment
+ * @param on <code>false</code> if event sending should be switched off,
+ * <code>true</code> if it should be switched on for the given path
+ * @throws java.lang.SecurityException if the caller does not hold
+ * <code>MonitorPermission</code> with the
+ * <code>switchevents</code> action or if there is any
+ * <code>StatusVariable</code> in the <code>path</code> field for
+ * which it is not allowed to switch event sending on or off as per
+ * the target field of the permission
+ * @throws java.lang.IllegalArgumentException if <code>path</code> is
+ * <code>null</code> or otherwise invalid, or points to a
+ * non-existing <code>StatusVariable</code>
+ */
+ public void switchEvents(String path, boolean on)
+ throws IllegalArgumentException, SecurityException;
+
+ /**
+ * Issues a request to reset a given <code>StatusVariable</code>.
+ * Depending on the semantics of the <code>StatusVariable</code> this call
+ * may or may not succeed: it makes sense to reset a counter to its starting
+ * value, but e.g. a <code>StatusVariable</code> of type String might not
+ * have a meaningful default value. Note that for numeric
+ * <code>StatusVariable</code>s the starting value may not necessarily be
+ * 0. Resetting a <code>StatusVariable</code> triggers a monitor event if
+ * the <code>StatusVariable</code> supports update notifications.
+ * <p>
+ * The entity that wants to reset the <code>StatusVariable</code> needs to
+ * hold <code>MonitorPermission</code> with the <code>reset</code>
+ * action present. The target field of the permission must match the
+ * <code>StatusVariable</code> name to be reset.
+ *
+ * @param path the identifier of the <code>StatusVariable</code> in
+ * [Monitorable_id]/[StatusVariable_id] format
+ * @return <code>true</code> if the <code>Monitorable</code> could
+ * successfully reset the given <code>StatusVariable</code>,
+ * <code>false</code> otherwise
+ * @throws java.lang.IllegalArgumentException if <code>path</code> is
+ * <code>null</code> or otherwise invalid, or points to a
+ * non-existing <code>StatusVariable</code>
+ * @throws java.lang.SecurityException if the caller does not hold
+ * <code>MonitorPermission</code> with the <code>reset</code>
+ * action or if the specified <code>StatusVariable</code> is not
+ * allowed to be reset as per the target field of the permission
+ */
+ public boolean resetStatusVariable(String path)
+ throws IllegalArgumentException, SecurityException;
+
+ /**
+ * Returns a human readable description of the given
+ * <code>StatusVariable</code>. The <code>null</code> value may be returned
+ * if there is no description for the given <code>StatusVariable</code>.
+ * <p>
+ * The entity that queries a <code>StatusVariable</code> needs to hold
+ * <code>MonitorPermission</code> for the given target with the
+ * <code>read</code> action present.
+ *
+ * @param path the full path of the <code>StatusVariable</code> in
+ * [Monitorable_ID]/[StatusVariable_ID] format
+ * @return the human readable description of this
+ * <code>StatusVariable</code> or <code>null</code> if it is not
+ * set
+ * @throws java.lang.IllegalArgumentException if <code>path</code> is
+ * <code>null</code> or otherwise invalid, or points to a
+ * non-existing <code>StatusVariable</code>
+ * @throws java.lang.SecurityException if the caller does not hold a
+ * <code>MonitorPermission</code> for the
+ * <code>StatusVariable</code> specified by <code>path</code>
+ * with the <code>read</code> action present
+ */
+ public String getDescription(String path)
+ throws IllegalArgumentException, SecurityException;
+
+ /**
+ * Starts a time based <code>MonitoringJob</code> with the parameters
+ * provided. Monitoring events will be sent according to the specified
+ * schedule. All specified <code>StatusVariable</code>s must exist when the
+ * job is started. The initiator string is used in the
+ * <code>mon.listener.id</code> field of all events triggered by the job,
+ * to allow filtering the events based on the initiator.
+ * <p>
+ * The <code>schedule</code> parameter specifies the time in seconds
+ * between two measurements, it must be greater than 0. The first
+ * measurement will be taken when the timer expires for the first time, not
+ * when this method is called.
+ * <p>
+ * The <code>count</code> parameter defines the number of measurements to be
+ * taken, and must either be a positive integer, or 0 if the measurement is
+ * to run until explicitely stopped.
+ * <p>
+ * The entity which initiates a <code>MonitoringJob</code> needs to hold
+ * <code>MonitorPermission</code> for all the specified target
+ * <code>StatusVariable</code>s with the <code>startjob</code> action
+ * present. If the permission's action string specifies a minimal sampling
+ * interval then the <code>schedule</code> parameter should be at least as
+ * great as the value in the action string.
+ *
+ * @param initiator the identifier of the entity that initiated the job
+ * @param statusVariables the list of <code>StatusVariable</code>s to be
+ * monitored, with each <code>StatusVariable</code> name given in
+ * [Monitorable_PID]/[StatusVariable_ID] format
+ * @param schedule the time in seconds between two measurements
+ * @param count the number of measurements to be taken, or 0 for the
+ * measurement to run until explicitely stopped
+ * @return the successfully started job object, cannot be <code>null</code>
+ * @throws java.lang.IllegalArgumentException if the list of
+ * <code>StatusVariable</code> names contains an invalid or
+ * non-existing <code>StatusVariable</code>; if
+ * <code>initiator</code> is <code>null</code> or empty; or if the
+ * <code>schedule</code> or <code>count</code> parameters are
+ * invalid
+ * @throws java.lang.SecurityException if the caller does not hold
+ * <code>MonitorPermission</code> for all the specified
+ * <code>StatusVariable</code>s, with the <code>startjob</code>
+ * action present, or if the permission does not allow starting the
+ * job with the given frequency
+ */
+ public MonitoringJob startScheduledJob(String initiator,
+ String[] statusVariables, int schedule, int count)
+ throws IllegalArgumentException, SecurityException;
+
+ /**
+ * Starts a change based <code>MonitoringJob</code> with the parameters
+ * provided. Monitoring events will be sent when the
+ * <code>StatusVariable</code>s of this job are updated. All specified
+ * <code>StatusVariable</code>s must exist when the job is started, and
+ * all must support update notifications. The initiator string is used in
+ * the <code>mon.listener.id</code> field of all events triggered by the
+ * job, to allow filtering the events based on the initiator.
+ * <p>
+ * The <code>count</code> parameter specifies the number of changes that
+ * must happen to a <code>StatusVariable</code> before a new notification is
+ * sent, this must be a positive integer.
+ * <p>
+ * The entity which initiates a <code>MonitoringJob</code> needs to hold
+ * <code>MonitorPermission</code> for all the specified target
+ * <code>StatusVariable</code>s with the <code>startjob</code> action
+ * present.
+ *
+ * @param initiator the identifier of the entity that initiated the job
+ * @param statusVariables the list of <code>StatusVariable</code>s to be
+ * monitored, with each <code>StatusVariable</code> name given in
+ * [Monitorable_PID]/[StatusVariable_ID] format
+ * @param count the number of changes that must happen to a
+ * <code>StatusVariable</code> before a new notification is sent
+ * @return the successfully started job object, cannot be <code>null</code>
+ * @throws java.lang.IllegalArgumentException if the list of
+ * <code>StatusVariable</code> names contains an invalid or
+ * non-existing <code>StatusVariable</code>, or one that does not
+ * support notifications; if the <code>initiator</code> is
+ * <code>null</code> or empty; or if <code>count</code> is invalid
+ * @throws java.lang.SecurityException if the caller does not hold
+ * <code>MonitorPermission</code> for all the specified
+ * <code>StatusVariable</code>s, with the <code>startjob</code>
+ * action present
+ */
+ public MonitoringJob startJob(String initiator, String[] statusVariables,
+ int count) throws IllegalArgumentException, SecurityException;
+
+ /**
+ * Returns the list of currently running <code>MonitoringJob</code>s.
+ * Jobs are only visible to callers that have the necessary permissions: to
+ * receive a Monitoring Job in the returned list, the caller must hold all
+ * permissions required for starting the job. This means that if the caller
+ * does not have <code>MonitorPermission</code> with the proper
+ * <code>startjob</code> action for all the Status Variables monitored by a
+ * job, then that job will be silently omitted from the results.
+ * <p>
+ * The returned array cannot be <code>null</code>, an empty array is
+ * returned if there are no running jobs visible to the caller at the time
+ * of the call.
+ *
+ * @return the list of running jobs visible to the caller
+ */
+ public MonitoringJob[] getRunningJobs();
+}
Added: felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/MonitorListener.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/MonitorListener.java?rev=616813&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/MonitorListener.java (added)
+++ felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/MonitorListener.java Wed Jan 30 08:46:24 2008
@@ -0,0 +1,42 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.monitor/src/org/osgi/service/monitor/MonitorListener.java,v 1.11 2006/06/16 16:31:25 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2004, 2006). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.service.monitor;
+
+/**
+ * The <code>MonitorListener</code> is used by <code>Monitorable</code>
+ * services to send notifications when a <code>StatusVariable</code> value is
+ * changed. The <code>MonitorListener</code> should register itself as a
+ * service at the OSGi Service Registry. This interface must (only) be
+ * implemented by the Monitor Admin component.
+ */
+public interface MonitorListener {
+ /**
+ * Callback for notification of a <code>StatusVariable</code> change.
+ *
+ * @param monitorableId the identifier of the <code>Monitorable</code>
+ * instance reporting the change
+ * @param statusVariable the <code>StatusVariable</code> that has changed
+ * @throws java.lang.IllegalArgumentException if the specified monitorable
+ * ID is invalid (<code>null</code>, empty, or contains illegal
+ * characters) or points to a non-existing <code>Monitorable</code>,
+ * or if <code>statusVariable</code> is <code>null</code>
+ */
+ public void updated(String monitorableId, StatusVariable statusVariable)
+ throws IllegalArgumentException;
+}
Added: felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/MonitorPermission.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/MonitorPermission.java?rev=616813&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/MonitorPermission.java (added)
+++ felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/MonitorPermission.java Wed Jan 30 08:46:24 2008
@@ -0,0 +1,366 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.monitor/src/org/osgi/service/monitor/MonitorPermission.java,v 1.17 2006/06/21 15:17:16 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2005, 2006). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.service.monitor;
+
+import java.io.UnsupportedEncodingException;
+import java.security.Permission;
+import java.util.StringTokenizer;
+
+/**
+ * Indicates the callers authority to publish, read or reset
+ * <code>StatusVariable</code>s, to switch event sending on or off or to
+ * start monitoring jobs. The target of the permission is the identifier of the
+ * <code>StatusVariable</code>, the action can be <code>read</code>,
+ * <code>publish</code>, <code>reset</code>, <code>startjob</code>,
+ * <code>switchevents</code>, or the combination of these separated by
+ * commas. Action names are interpreted case-insensitively, but the canonical
+ * action string returned by {@link #getActions} uses the forms defined by the
+ * action constants.
+ * <p>
+ * If the wildcard <code>*</code> appears in the actions field, all legal
+ * monitoring commands are allowed on the designated target(s) by the owner of
+ * the permission.
+ */
+public class MonitorPermission extends Permission {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -9084425194463274314L;
+
+ /**
+ * Holders of <code>MonitorPermission</code> with the <code>read</code>
+ * action present are allowed to read the value of the
+ * <code>StatusVariable</code>s specified in the permission's target field.
+ */
+ public static final String READ = "read";
+
+ /**
+ * Holders of <code>MonitorPermission</code> with the <code>reset</code>
+ * action present are allowed to reset the value of the
+ * <code>StatusVariable</code>s specified in the permission's target field.
+ */
+ public static final String RESET = "reset";
+
+ /**
+ * Holders of <code>MonitorPermission</code> with the <code>publish</code>
+ * action present are <code>Monitorable</code> services that are allowed
+ * to publish the <code>StatusVariable</code>s specified in the
+ * permission's target field. Note, that this permission cannot be enforced
+ * when a <code>Monitorable</code> registers to the framework, because the
+ * Service Registry does not know about this permission. Instead, any
+ * <code>StatusVariable</code>s published by a <code>Monitorable</code>
+ * without the corresponding <code>publish</code> permission are silently
+ * ignored by <code>MonitorAdmin</code>, and are therefore invisible to the
+ * users of the monitoring service.
+ */
+ public static final String PUBLISH = "publish";
+
+ /**
+ * Holders of <code>MonitorPermission</code> with the <code>startjob</code>
+ * action present are allowed to initiate monitoring jobs involving the
+ * <code>StatusVariable</code>s specified in the permission's target field.
+ * <p>
+ * A minimal sampling interval can be optionally defined in the following
+ * form: <code>startjob:n</code>. This allows the holder of the permission
+ * to initiate time based jobs with a measurement interval of at least
+ * <code>n</code> seconds. If <code>n</code> is not specified or 0 then the
+ * holder of this permission is allowed to start monitoring jobs specifying
+ * any frequency.
+ */
+ public static final String STARTJOB = "startjob";
+
+ /**
+ * Holders of <code>MonitorPermission</code> with the
+ * <code>switchevents</code> action present are allowed to switch event
+ * sending on or off for the value of the <code>StatusVariable</code>s
+ * specified in the permission's target field.
+ */
+ public static final String SWITCHEVENTS = "switchevents";
+
+ private static final int READ_FLAG = 0x1;
+ private static final int RESET_FLAG = 0x2;
+ private static final int PUBLISH_FLAG = 0x4;
+ private static final int STARTJOB_FLAG = 0x8;
+ private static final int SWITCHEVENTS_FLAG = 0x10;
+
+ private static final int ALL_FLAGS = READ_FLAG | RESET_FLAG |
+ PUBLISH_FLAG | STARTJOB_FLAG | SWITCHEVENTS_FLAG;
+
+ private String monId;
+ private String varId;
+ private boolean prefixMonId;
+ private boolean prefixVarId;
+ private int mask;
+ private int minJobInterval;
+
+ /**
+ * Create a <code>MonitorPermission</code> object, specifying the target
+ * and actions.
+ * <p>
+ * The <code>statusVariable</code> parameter is the target of the
+ * permission, defining one or more status variable names to which the
+ * specified actions apply. Multiple status variable names can be selected
+ * by using the wildcard <code>*</code> in the target string. The wildcard
+ * is allowed in both fragments, but only at the end of the fragments.
+ * <p>
+ * For example, the following targets are valid:
+ * <code>com.mycomp.myapp/queue_length</code>,
+ * <code>com.mycomp.myapp/*</code>, <code>com.mycomp.*/*</code>,
+ * <code>*/*</code>, <code>*/queue_length</code>,
+ * <code>*/queue*</code>.
+ * <p>
+ * The following targets are invalid:
+ * <code>*.myapp/queue_length</code>, <code>com.*.myapp/*</code>,
+ * <code>*</code>.
+ * <p>
+ * The <code>actions</code> parameter specifies the allowed action(s):
+ * <code>read</code>, <code>publish</code>, <code>startjob</code>,
+ * <code>reset</code>, <code>switchevents</code>, or the combination of
+ * these separated by commas. String constants are defined in this class for
+ * each valid action. Passing <code>"*"</code> as the action
+ * string is equivalent to listing all actions.
+ *
+ * @param statusVariable the identifier of the <code>StatusVariable</code>
+ * in [Monitorable_id]/[StatusVariable_id] format
+ * @param actions the list of allowed actions separated by commas, or
+ * <code>*</code> for all actions
+ * @throws java.lang.IllegalArgumentException if either parameter is
+ * <code>null</code>, or invalid with regard to the constraints
+ * defined above and in the documentation of the used actions
+ */
+ public MonitorPermission(String statusVariable, String actions)
+ throws IllegalArgumentException {
+ super(statusVariable);
+
+ if(statusVariable == null)
+ throw new IllegalArgumentException(
+ "Invalid StatusVariable path 'null'.");
+
+ if(actions == null)
+ throw new IllegalArgumentException(
+ "Invalid actions string 'null'.");
+
+ int sep = statusVariable.indexOf('/');
+ int len = statusVariable.length();
+
+ if (sep == -1)
+ throw new IllegalArgumentException(
+ "Invalid StatusVariable path: should contain '/' separator.");
+ if (sep == 0 || sep == statusVariable.length() - 1)
+ throw new IllegalArgumentException(
+ "Invalid StatusVariable path: empty monitorable ID or StatusVariable name.");
+
+ prefixMonId = statusVariable.charAt(sep - 1) == '*';
+ prefixVarId = statusVariable.charAt(len - 1) == '*';
+
+ monId = statusVariable.substring(0, prefixMonId ? sep - 1 : sep);
+ varId = statusVariable.substring(sep + 1, prefixVarId ? len - 1 : len);
+
+ checkId(monId, "Monitorable ID part of the target");
+ checkId(varId, "Status Variable ID part of the target");
+
+ minJobInterval = 0;
+
+ if(actions.equals("*"))
+ mask = ALL_FLAGS;
+ else {
+ mask = 0;
+ StringTokenizer st = new StringTokenizer(actions, ",");
+ while (st.hasMoreTokens()) {
+ String action = st.nextToken();
+ if (action.equalsIgnoreCase(READ)) {
+ addToMask(READ_FLAG, READ);
+ } else if (action.equalsIgnoreCase(RESET)) {
+ addToMask(RESET_FLAG, RESET);
+ } else if (action.equalsIgnoreCase(PUBLISH)) {
+ addToMask(PUBLISH_FLAG, PUBLISH);
+ } else if (action.equalsIgnoreCase(SWITCHEVENTS)) {
+ addToMask(SWITCHEVENTS_FLAG, SWITCHEVENTS);
+ } else if (action.toLowerCase().startsWith(STARTJOB)) {
+ minJobInterval = 0;
+
+ int slen = STARTJOB.length();
+ if (action.length() != slen) {
+ if (action.charAt(slen) != ':')
+ throw new IllegalArgumentException(
+ "Invalid action '" + action + "'.");
+
+ try {
+ minJobInterval = Integer.parseInt(action
+ .substring(slen + 1));
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException(
+ "Invalid parameter in startjob action '"
+ + action + "'.");
+ }
+ }
+ addToMask(STARTJOB_FLAG, STARTJOB);
+ } else
+ throw new IllegalArgumentException("Invalid action '" +
+ action + "'");
+ }
+ }
+ }
+
+ private void addToMask(int action, String actionString) {
+ if((mask & action) != 0)
+ throw new IllegalArgumentException("Invalid action string: " +
+ actionString + " appears multiple times.");
+
+ mask |= action;
+ }
+
+ private void checkId(String id, String idName)
+ throws IllegalArgumentException {
+
+ byte[] nameBytes;
+ try {
+ nameBytes = id.getBytes("UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ // never happens, "UTF-8" must always be supported
+ throw new IllegalStateException(e.getMessage());
+ }
+ if(nameBytes.length > StatusVariable.MAX_ID_LENGTH)
+ throw new IllegalArgumentException(idName + " is too long (over " +
+ StatusVariable.MAX_ID_LENGTH + " bytes in UTF-8 encoding).");
+
+
+ if (id.equals(".") || id.equals(".."))
+ throw new IllegalArgumentException(idName + " is invalid.");
+
+ char[] chars = id.toCharArray();
+ for (int i = 0; i < chars.length; i++)
+ if (StatusVariable.SYMBOLIC_NAME_CHARACTERS.indexOf(chars[i]) == -1)
+ throw new IllegalArgumentException(idName +
+ " contains invalid characters.");
+ }
+
+ /**
+ * Create an integer hash of the object. The hash codes of
+ * <code>MonitorPermission</code>s <code>p1</code> and <code>p2</code> are
+ * the same if <code>p1.equals(p2)</code>.
+ *
+ * @return the hash of the object
+ */
+ public int hashCode() {
+ return new Integer(mask).hashCode()
+ ^ new Integer(minJobInterval).hashCode() ^ monId.hashCode()
+ ^ new Boolean(prefixMonId).hashCode()
+ ^ varId.hashCode()
+ ^ new Boolean(prefixVarId).hashCode();
+ }
+
+ /**
+ * Determines the equality of two <code>MonitorPermission</code> objects.
+ * Two <code>MonitorPermission</code> objects are equal if their target
+ * strings are equal and the same set of actions are listed in their action
+ * strings.
+ *
+ * @param o the object being compared for equality with this object
+ * @return <code>true</code> if the two permissions are equal
+ */
+ public boolean equals(Object o) {
+ if (!(o instanceof MonitorPermission))
+ return false;
+
+ MonitorPermission other = (MonitorPermission) o;
+
+ return mask == other.mask && minJobInterval == other.minJobInterval
+ && monId.equals(other.monId)
+ && prefixMonId == other.prefixMonId
+ && varId.equals(other.varId)
+ && prefixVarId == other.prefixVarId;
+ }
+
+ /**
+ * Get the action string associated with this permission. The actions are
+ * returned in the following order: <code>read</code>, <code>reset</code>,
+ * <code>publish</code>, <code>startjob</code>, <code>switchevents</code>.
+ *
+ * @return the allowed actions separated by commas, cannot be
+ * <code>null</code>
+ */
+ public String getActions() {
+ StringBuffer sb = new StringBuffer();
+
+ appendAction(sb, READ_FLAG, READ);
+ appendAction(sb, RESET_FLAG, RESET);
+ appendAction(sb, PUBLISH_FLAG, PUBLISH);
+ appendAction(sb, STARTJOB_FLAG, STARTJOB);
+ appendAction(sb, SWITCHEVENTS_FLAG, SWITCHEVENTS);
+
+ return sb.toString();
+ }
+
+ private void appendAction(StringBuffer sb, int flag, String actionName) {
+ if ((mask & flag) != 0) {
+ if(sb.length() != 0)
+ sb.append(',');
+ sb.append(actionName);
+
+ if(flag == STARTJOB_FLAG && minJobInterval != 0)
+ sb.append(':').append(minJobInterval);
+ }
+ }
+
+ /**
+ * Determines if the specified permission is implied by this permission.
+ * <p>
+ * This method returns <code>false</code> if and only if at least one of the
+ * following conditions are fulfilled for the specified permission:
+ * <ul>
+ * <li>it is not a <code>MonitorPermission</code>
+ * <li>it has a broader set of actions allowed than this one
+ * <li>it allows initiating time based monitoring jobs with a lower minimal
+ * sampling interval
+ * <li>the target set of <code>Monitorable</code>s is not the same nor a
+ * subset of the target set of <code>Monitorable</code>s of this permission
+ * <li>the target set of <code>StatusVariable</code>s is not the same
+ * nor a subset of the target set of <code>StatusVariable</code>s of this
+ * permission
+ * </ul>
+ *
+ * @param p the permission to be checked
+ * @return <code>true</code> if the given permission is implied by this
+ * permission
+ */
+ public boolean implies(Permission p) {
+ if (!(p instanceof MonitorPermission))
+ return false;
+
+ MonitorPermission other = (MonitorPermission) p;
+
+ if ((mask & other.mask) != other.mask)
+ return false;
+
+ if ((other.mask & STARTJOB_FLAG) != 0
+ && minJobInterval > other.minJobInterval)
+ return false;
+
+ return implies(monId, prefixMonId, other.monId, other.prefixMonId)
+ && implies(varId, prefixVarId, other.varId, other.prefixVarId);
+ }
+
+ private boolean implies(String id, boolean prefix, String oid,
+ boolean oprefix) {
+
+ return prefix ? oid.startsWith(id) : !oprefix && id.equals(oid);
+ }
+}
Added: felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/Monitorable.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/Monitorable.java?rev=616813&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/Monitorable.java (added)
+++ felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/Monitorable.java Wed Jan 30 08:46:24 2008
@@ -0,0 +1,140 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.monitor/src/org/osgi/service/monitor/Monitorable.java,v 1.17 2006/06/16 16:31:25 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2004, 2006). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.service.monitor;
+
+/**
+ * A <code>Monitorable</code> can provide information about itself in the form
+ * of <code>StatusVariables</code>. Instances of this interface should
+ * register themselves at the OSGi Service Registry. The
+ * <code>MonitorAdmin</code> listens to the registration of
+ * <code>Monitorable</code> services, and makes the information they provide
+ * available also through the Device Management Tree (DMT) for remote access.
+ * <p>
+ * The monitorable service is identified by its PID string which must be a non-
+ * <code>null</code>, non-empty string that conforms to the "symbolic-name"
+ * definition in the OSGi core specification. This means that only the
+ * characters [-_.a-zA-Z0-9] may be used. The length of the PID must not exceed
+ * 20 characters.
+ * <p>
+ * A <code>Monitorable</code> may optionally support sending notifications
+ * when the status of its <code>StatusVariables</code> change. Support for
+ * change notifications can be defined per <code>StatusVariable</code>.
+ * <p>
+ * Publishing <code>StatusVariables</code> requires the presence of the
+ * <code>MonitorPermission</code> with the <code>publish</code> action
+ * string. This permission, however, is not checked during registration of the
+ * <code>Monitorable</code> service. Instead, the <code>MonitorAdmin</code>
+ * implemenatation must make sure that when a <code>StatusVariable</code> is
+ * queried, it is shown only if the <code>Monitorable</code> is authorized to
+ * publish the given <code>StatusVariable</code>.
+ */
+public interface Monitorable {
+ /**
+ * Returns the list of <code>StatusVariable</code> identifiers published
+ * by this <code>Monitorable</code>. A <code>StatusVariable</code> name
+ * is unique within the scope of a <code>Monitorable</code>. The array
+ * contains the elements in no particular order. The returned value must not
+ * be <code>null</code>.
+ *
+ * @return the <code>StatusVariable<code> identifiers published by this
+ * object, or an empty array if none are published
+ */
+ public String[] getStatusVariableNames();
+
+ /**
+ * Returns the <code>StatusVariable</code> object addressed by its
+ * identifier. The <code>StatusVariable</code> will hold the value taken
+ * at the time of this method call.
+ * <p>
+ * The given identifier does not contain the Monitorable PID, i.e. it
+ * specifies the name and not the path of the Status Variable.
+ *
+ * @param id the identifier of the <code>StatusVariable</code>, cannot be
+ * <code>null</code>
+ * @return the <code>StatusVariable</code> object
+ * @throws java.lang.IllegalArgumentException if <code>id</code> points to a
+ * non-existing <code>StatusVariable</code>
+ */
+ public StatusVariable getStatusVariable(String id)
+ throws IllegalArgumentException;
+
+ /**
+ * Tells whether the <code>StatusVariable</code> provider is able to send
+ * instant notifications when the given <code>StatusVariable</code>
+ * changes. If the <code>Monitorable</code> supports sending change
+ * updates it must notify the <code>MonitorListener</code> when the value
+ * of the <code>StatusVariable</code> changes. The
+ * <code>Monitorable</code> finds the <code>MonitorListener</code>
+ * service through the Service Registry.
+ * <p>
+ * The given identifier does not contain the Monitorable PID, i.e. it
+ * specifies the name and not the path of the Status Variable.
+ *
+ * @param id the identifier of the <code>StatusVariable</code>, cannot be
+ * <code>null</code>
+ * @return <code>true</code> if the <code>Monitorable</code> can send
+ * notification when the given <code>StatusVariable</code>
+ * changes, <code>false</code> otherwise
+ * @throws java.lang.IllegalArgumentException if <code>id</code> points to a
+ * non-existing <code>StatusVariable</code>
+ */
+ public boolean notifiesOnChange(String id) throws IllegalArgumentException;
+
+ /**
+ * Issues a request to reset a given <code>StatusVariable</code>.
+ * Depending on the semantics of the actual Status Variable this call may or
+ * may not succeed: it makes sense to reset a counter to its starting value,
+ * but for example a <code>StatusVariable</code> of type <code>String</code>
+ * might not have a meaningful default value. Note that for numeric
+ * <code>StatusVariables</code> the starting value may not necessarily be
+ * 0. Resetting a <code>StatusVariable</code> must trigger a monitor event.
+ * <p>
+ * The given identifier does not contain the Monitorable PID, i.e. it
+ * specifies the name and not the path of the Status Variable.
+ *
+ * @param id the identifier of the <code>StatusVariable</code>, cannot be
+ * <code>null</code>
+ * @return <code>true</code> if the <code>Monitorable</code> could
+ * successfully reset the given <code>StatusVariable</code>,
+ * <code>false</code> otherwise
+ * @throws java.lang.IllegalArgumentException if <code>id</code> points to a
+ * non-existing <code>StatusVariable</code>
+ */
+ public boolean resetStatusVariable(String id)
+ throws IllegalArgumentException;
+
+ /**
+ * Returns a human readable description of a <code>StatusVariable</code>.
+ * This can be used by management systems on their GUI. The
+ * <code>null</code> return value is allowed if there is no description for
+ * the specified Status Variable.
+ * <p>
+ * The given identifier does not contain the Monitorable PID, i.e. it
+ * specifies the name and not the path of the Status Variable.
+ *
+ * @param id the identifier of the <code>StatusVariable</code>, cannot be
+ * <code>null</code>
+ * @return the human readable description of this
+ * <code>StatusVariable</code> or <code>null</code> if it is not
+ * set
+ * @throws java.lang.IllegalArgumentException if <code>id</code> points to a
+ * non-existing <code>StatusVariable</code>
+ */
+ public String getDescription(String id) throws IllegalArgumentException;
+}
Added: felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/MonitoringJob.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/MonitoringJob.java?rev=616813&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/MonitoringJob.java (added)
+++ felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/MonitoringJob.java Wed Jan 30 08:46:24 2008
@@ -0,0 +1,126 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.monitor/src/org/osgi/service/monitor/MonitoringJob.java,v 1.14 2006/06/16 16:31:25 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2004, 2006). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.service.monitor;
+
+/**
+ * A Monitoring Job is a request for scheduled or event based notifications on
+ * update of a set of <code>StatusVariable</code>s. The job is a data
+ * structure that holds a non-empty list of <code>StatusVariable</code> names,
+ * an identification of the initiator of the job, and the sampling parameters.
+ * There are two kinds of monitoring jobs: time based and change based. Time
+ * based jobs take samples of all <code>StatusVariable</code>s with a
+ * specified frequency. The number of samples to be taken before the job
+ * finishes may be specified. Change based jobs are only interested in the
+ * changes of the monitored <code>StatusVariable</code>s. In this case, the
+ * number of changes that must take place between two notifications can be
+ * specified.
+ * <p>
+ * The job can be started on the <code>MonitorAdmin</code> interface. Running
+ * the job (querying the <code>StatusVariable</code>s, listening to changes,
+ * and sending out notifications on updates) is the task of the
+ * <code>MonitorAdmin</code> implementation.
+ * <p>
+ * Whether a monitoring job keeps track dynamically of the
+ * <code>StatusVariable</code>s it monitors is not specified. This means that
+ * if we monitor a <code>StatusVariable</code> of a <code>Monitorable</code>
+ * service which disappears and later reappears then it is implementation
+ * specific whether we still receive updates of the <code>StatusVariable</code>
+ * changes or not.
+ */
+public interface MonitoringJob {
+ /**
+ * Stops a Monitoring Job. Note that a time based job can also stop
+ * automatically if the specified number of samples have been taken.
+ */
+ public void stop();
+
+ /**
+ * Returns the identitifier of the principal who initiated the job. This is
+ * set at the time when
+ * {@link MonitorAdmin#startJob MonitorAdmin.startJob()} method is called.
+ * This string holds the ServerID if the operation was initiated from a
+ * remote manager, or an arbitrary ID of the initiator entity in the local
+ * case (used for addressing notification events).
+ *
+ * @return the ID of the initiator, cannot be <code>null</code>
+ */
+ public String getInitiator();
+
+ /**
+ * Returns the list of <code>StatusVariable</code> names that are the
+ * targets of this measurement job. For time based jobs, the
+ * <code>MonitorAdmin</code> will iterate through this list and query all
+ * <code>StatusVariable</code>s when its timer set by the job's frequency
+ * rate expires.
+ *
+ * @return the target list of the measurement job in
+ * [Monitorable_ID]/[StatusVariable_ID] format, cannot be
+ * <code>null</code>
+ */
+ public String[] getStatusVariableNames();
+
+ /**
+ * Returns the delay (in seconds) between two samples. If this call returns
+ * N (greater than 0) then the <code>MonitorAdmin</code> queries each
+ * <code>StatusVariable</code> that belongs to this job every N seconds.
+ * The value 0 means that the job is not scheduled but event based: in this
+ * case instant notification on changes is requested (at every nth change of
+ * the value, as specified by the report count parameter).
+ *
+ * @return the delay (in seconds) between samples, or 0 for change based
+ * jobs
+ */
+ public int getSchedule();
+
+ /**
+ * Returns the number of times <code>MonitorAdmin</code> will query the
+ * <code>StatusVariable</code>s (for time based jobs), or the number of
+ * changes of a <code>StatusVariable</code> between notifications (for
+ * change based jobs). Time based jobs with non-zero report count will take
+ * <code>getReportCount()</code>*<code>getSchedule()</code> time to
+ * finish. Time based jobs with 0 report count and change based jobs do not
+ * stop automatically, but all jobs can be stopped with the {@link #stop}
+ * method.
+ *
+ * @return the number of measurements to be taken, or the number of changes
+ * between notifications
+ */
+ public int getReportCount();
+
+ /**
+ * Returns whether the job was started locally or remotely. Jobs started by
+ * the clients of this API are always local, remote jobs can only be started
+ * using the Device Management Tree.
+ *
+ * @return <code>true</code> if the job was started from the local device,
+ * <code>false</code> if the job was initiated from a management
+ * server through the device management tree
+ */
+ public boolean isLocal();
+
+ /**
+ * Returns whether the job is running. A job is running until it is
+ * explicitely stopped, or, in case of time based jobs with a finite report
+ * count, until the given number of measurements have been made.
+ *
+ * @return <code>true</code> if the job is still running, <code>false</code>
+ * if it has finished
+ */
+ public boolean isRunning();
+}
Added: felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/StatusVariable.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/StatusVariable.java?rev=616813&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/StatusVariable.java (added)
+++ felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/StatusVariable.java Wed Jan 30 08:46:24 2008
@@ -0,0 +1,433 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.monitor/src/org/osgi/service/monitor/StatusVariable.java,v 1.14 2006/06/16 16:31:25 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2004, 2006). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.service.monitor;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Date;
+
+/**
+ * A <code>StatusVariable</code> object represents the value of a status
+ * variable taken with a certain collection method at a certain point of time.
+ * The type of the <code>StatusVariable</code> can be <code>int</code>,
+ * <code>float</code>, <code>boolean</code> or <code>String</code>.
+ * <p>
+ * A <code>StatusVariable</code> is identified by an ID string that is unique
+ * within the scope of a <code>Monitorable</code>. The ID must be a non-
+ * <code>null</code>, non-empty string that conforms to the "symbolic-name"
+ * definition in the OSGi core specification. This means that only the
+ * characters [-_.a-zA-Z0-9] may be used. The length of the ID must not exceed
+ * 32 bytes when UTF-8 encoded.
+ */
+public final class StatusVariable {
+ //----- Public constants -----//
+ /**
+ * Constant for identifying <code>int</code> data type.
+ */
+ public static final int TYPE_INTEGER = 0;
+
+ /**
+ * Constant for identifying <code>float</code> data type.
+ */
+ public static final int TYPE_FLOAT = 1;
+
+ /**
+ * Constant for identifying <code>String</code> data type.
+ */
+ public static final int TYPE_STRING = 2;
+
+ /**
+ * Constant for identifying <code>boolean</code> data type.
+ */
+ public static final int TYPE_BOOLEAN = 3;
+
+ /**
+ * Constant for identifying 'Cumulative Counter' data collection method.
+ */
+ public static final int CM_CC = 0;
+
+ /**
+ * Constant for identifying 'Discrete Event Registration' data collection
+ * method.
+ */
+ public static final int CM_DER = 1;
+
+ /**
+ * Constant for identifying 'Gauge' data collection method.
+ */
+ public static final int CM_GAUGE = 2;
+
+ /**
+ * Constant for identifying 'Status Inspection' data collection method.
+ */
+ public static final int CM_SI = 3;
+
+ //----- Package private constants -----//
+
+ static final String SYMBOLIC_NAME_CHARACTERS =
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" +
+ "-_."; // a subset of the characters allowed in DMT URIs
+
+ static final int MAX_ID_LENGTH = 32;
+
+ //----- Private fields -----//
+ private String id;
+ private Date timeStamp;
+ private int cm;
+ private int type;
+
+ private int intData;
+ private float floatData;
+ private String stringData;
+ private boolean booleanData;
+
+
+ //----- Constructors -----//
+ /**
+ * Constructor for a <code>StatusVariable</code> of <code>int</code>
+ * type.
+ *
+ * @param id the identifier of the <code>StatusVariable</code>
+ * @param cm the collection method, one of the <code>CM_</code> constants
+ * @param data the <code>int</code> value of the
+ * <code>StatusVariable</code>
+ * @throws java.lang.IllegalArgumentException if the given <code>id</code>
+ * is not a valid <code>StatusVariable</code> name, or if
+ * <code>cm</code> is not one of the collection method constants
+ * @throws java.lang.NullPointerException if the <code>id</code>
+ * parameter is <code>null</code>
+ */
+ public StatusVariable(String id, int cm, int data) {
+ setCommon(id, cm);
+ type = TYPE_INTEGER;
+ intData = data;
+ }
+
+ /**
+ * Constructor for a <code>StatusVariable</code> of <code>float</code>
+ * type.
+ *
+ * @param id the identifier of the <code>StatusVariable</code>
+ * @param cm the collection method, one of the <code>CM_</code> constants
+ * @param data the <code>float</code> value of the
+ * <code>StatusVariable</code>
+ * @throws java.lang.IllegalArgumentException if the given <code>id</code>
+ * is not a valid <code>StatusVariable</code> name, or if
+ * <code>cm</code> is not one of the collection method constants
+ * @throws java.lang.NullPointerException if the <code>id</code> parameter
+ * is <code>null</code>
+ */
+ public StatusVariable(String id, int cm, float data) {
+ setCommon(id, cm);
+ type = TYPE_FLOAT;
+ floatData = data;
+ }
+
+ /**
+ * Constructor for a <code>StatusVariable</code> of <code>boolean</code>
+ * type.
+ *
+ * @param id the identifier of the <code>StatusVariable</code>
+ * @param cm the collection method, one of the <code>CM_</code> constants
+ * @param data the <code>boolean</code> value of the
+ * <code>StatusVariable</code>
+ * @throws java.lang.IllegalArgumentException if the given <code>id</code>
+ * is not a valid <code>StatusVariable</code> name, or if
+ * <code>cm</code> is not one of the collection method constants
+ * @throws java.lang.NullPointerException if the <code>id</code> parameter
+ * is <code>null</code>
+ */
+ public StatusVariable(String id, int cm, boolean data) {
+ setCommon(id, cm);
+ type = TYPE_BOOLEAN;
+ booleanData = data;
+ }
+
+ /**
+ * Constructor for a <code>StatusVariable</code> of <code>String</code>
+ * type.
+ *
+ * @param id the identifier of the <code>StatusVariable</code>
+ * @param cm the collection method, one of the <code>CM_</code> constants
+ * @param data the <code>String</code> value of the
+ * <code>StatusVariable</code>, can be <code>null</code>
+ * @throws java.lang.IllegalArgumentException if the given <code>id</code>
+ * is not a valid <code>StatusVariable</code> name, or if
+ * <code>cm</code> is not one of the collection method constants
+ * @throws java.lang.NullPointerException if the <code>id</code> parameter
+ * is <code>null</code>
+ */
+ public StatusVariable(String id, int cm, String data) {
+ setCommon(id, cm);
+ type = TYPE_STRING;
+ stringData = data;
+ }
+
+
+ // ----- Public methods -----//
+ /**
+ * Returns the ID of this <code>StatusVariable</code>. The ID is unique
+ * within the scope of a <code>Monitorable</code>.
+ *
+ * @return the ID of this <code>StatusVariable</code>
+ */
+ public String getID() {
+ return id;
+ }
+
+ /**
+ * Returns information on the data type of this <code>StatusVariable</code>.
+ *
+ * @return one of the <code>TYPE_</code> constants indicating the type of
+ * this <code>StatusVariable</code>
+ */
+ public int getType() {
+ return type;
+ }
+
+ /**
+ * Returns the timestamp associated with the <code>StatusVariable</code>.
+ * The timestamp is stored when the <code>StatusVariable</code> instance is
+ * created, generally during the {@link Monitorable#getStatusVariable}
+ * method call.
+ *
+ * @return the time when the <code>StatusVariable</code> value was
+ * queried, cannot be <code>null</code>
+ *
+ */
+ public Date getTimeStamp() {
+ return timeStamp;
+ }
+
+ /**
+ * Returns the <code>StatusVariable</code> value if its type is
+ * <code>String</code>.
+ *
+ * @return the <code>StatusVariable</code> value as a <code>String</code>
+ * @throws java.lang.IllegalStateException if the type of the
+ * <code>StatusVariable</code> is not <code>String</code>
+ */
+ public String getString() throws IllegalStateException {
+ if (type != TYPE_STRING)
+ throw new IllegalStateException(
+ "This StatusVariable does not contain a String value.");
+ return stringData;
+ }
+
+ /**
+ * Returns the <code>StatusVariable</code> value if its type is
+ * <code>int</code>.
+ *
+ * @return the <code>StatusVariable</code> value as an <code>int</code>
+ * @throws java.lang.IllegalStateException if the type of this
+ * <code>StatusVariable</code> is not <code>int</code>
+ */
+ public int getInteger() throws IllegalStateException {
+ if (type != TYPE_INTEGER)
+ throw new IllegalStateException(
+ "This StatusVariable does not contain an integer value.");
+ return intData;
+ }
+
+ /**
+ * Returns the <code>StatusVariable</code> value if its type is
+ * <code>float</code>.
+ *
+ * @return the <code>StatusVariable</code> value as a <code>float</code>
+ * @throws java.lang.IllegalStateException if the type of this
+ * <code>StatusVariable</code> is not <code>float</code>
+ */
+ public float getFloat() throws IllegalStateException {
+ if (type != TYPE_FLOAT)
+ throw new IllegalStateException(
+ "This StatusVariable does not contain a float value.");
+ return floatData;
+ }
+
+ /**
+ * Returns the <code>StatusVariable</code> value if its type is
+ * <code>boolean</code>.
+ *
+ * @return the <code>StatusVariable</code> value as a <code>boolean</code>
+ * @throws java.lang.IllegalStateException if the type of this
+ * <code>StatusVariable</code> is not <code>boolean</code>
+ */
+ public boolean getBoolean() throws IllegalStateException {
+ if (type != TYPE_BOOLEAN)
+ throw new IllegalStateException(
+ "This StatusVariable does not contain a boolean value.");
+ return booleanData;
+ }
+
+ /**
+ * Returns the collection method of this <code>StatusVariable</code>. See
+ * section 3.3 b) in [ETSI TS 132 403]
+ *
+ * @return one of the <code>CM_</code> constants
+ */
+ public int getCollectionMethod() {
+ return cm;
+ }
+
+ /**
+ * Compares the specified object with this <code>StatusVariable</code>.
+ * Two <code>StatusVariable</code> objects are considered equal if their
+ * full path, collection method and type are identical, and the data
+ * (selected by their type) is equal.
+ *
+ * @param obj the object to compare with this <code>StatusVariable</code>
+ * @return <code>true</code> if the argument represents the same
+ * <code>StatusVariable</code> as this object
+ */
+ public boolean equals(Object obj) {
+ if (!(obj instanceof StatusVariable))
+ return false;
+
+ StatusVariable other = (StatusVariable) obj;
+
+ if (!equals(id, other.id) || cm != other.cm || type != other.type)
+ return false;
+
+ switch (type) {
+ case TYPE_INTEGER: return intData == other.intData;
+ case TYPE_FLOAT: return floatData == other.floatData;
+ case TYPE_STRING: return equals(stringData, other.stringData);
+ case TYPE_BOOLEAN: return booleanData == other.booleanData;
+ }
+
+ return false; // never reached
+ }
+
+ /**
+ * Returns the hash code value for this <code>StatusVariable</code>. The
+ * hash code is calculated based on the full path, collection method and
+ * value of the <code>StatusVariable</code>.
+ *
+ * @return the hash code of this object
+ */
+ public int hashCode() {
+ int hash = hashCode(id) ^ cm;
+
+ switch (type) {
+ case TYPE_INTEGER: return hash ^ intData;
+ case TYPE_FLOAT: return hash ^ hashCode(new Float(floatData));
+ case TYPE_BOOLEAN: return hash ^ hashCode(new Boolean(booleanData));
+ case TYPE_STRING: return hash ^ hashCode(stringData);
+ }
+
+ return 0; // never reached
+ }
+
+ // String representation: StatusVariable(path, cm, time, type, value)
+ /**
+ * Returns a <code>String</code> representation of this
+ * <code>StatusVariable</code>. The returned <code>String</code>
+ * contains the full path, collection method, timestamp, type and value
+ * parameters of the <code>StatusVariable</code> in the following format:
+ * <pre>StatusVariable(<path>, <cm>, <timestamp>, <type>, <value>)</pre>
+ * The collection method identifiers used in the string representation are
+ * "CC", "DER", "GAUGE" and "SI" (without the quotes). The format of the
+ * timestamp is defined by the <code>Date.toString</code> method, while the
+ * type is identified by one of the strings "INTEGER", "FLOAT", "STRING" and
+ * "BOOLEAN". The final field contains the string representation of the
+ * value of the status variable.
+ *
+ * @return the <code>String</code> representation of this
+ * <code>StatusVariable</code>
+ */
+ public String toString() {
+ String cmName = null;
+ switch (cm) {
+ case CM_CC: cmName = "CC"; break;
+ case CM_DER: cmName = "DER"; break;
+ case CM_GAUGE: cmName = "GAUGE"; break;
+ case CM_SI: cmName = "SI"; break;
+ }
+
+ String beg = "StatusVariable(" + id + ", " + cmName + ", "
+ + timeStamp + ", ";
+
+ switch (type) {
+ case TYPE_INTEGER: return beg + "INTEGER, " + intData + ")";
+ case TYPE_FLOAT: return beg + "FLOAT, " + floatData + ")";
+ case TYPE_STRING: return beg + "STRING, " + stringData + ")";
+ case TYPE_BOOLEAN: return beg + "BOOLEAN, " + booleanData + ")";
+ }
+
+ return null; // never reached
+ }
+
+ //----- Private methods -----//
+
+ private void setCommon(String id, int cm)
+ throws IllegalArgumentException, NullPointerException {
+ checkId(id, "StatusVariable ID");
+
+ if (cm != CM_CC && cm != CM_DER && cm != CM_GAUGE && cm != CM_SI)
+ throw new IllegalArgumentException(
+ "Unknown data collection method constant '" + cm + "'.");
+
+ this.id = id;
+ this.cm = cm;
+ timeStamp = new Date();
+ }
+
+
+ private boolean equals(Object o1, Object o2) {
+ return o1 == null ? o2 == null : o1.equals(o2);
+ }
+
+ private int hashCode(Object o) {
+ return o == null ? 0 : o.hashCode();
+ }
+
+ private static void checkId(String id, String idName)
+ throws IllegalArgumentException, NullPointerException {
+ if (id == null)
+ throw new NullPointerException(idName + " is null.");
+ if(id.length() == 0)
+ throw new IllegalArgumentException(idName + " is empty.");
+
+ byte[] nameBytes;
+ try {
+ nameBytes = id.getBytes("UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ // never happens, "UTF-8" must always be supported
+ throw new IllegalStateException(e.getMessage());
+ }
+ if(nameBytes.length > MAX_ID_LENGTH)
+ throw new IllegalArgumentException(idName + " is too long " +
+ "(over " + MAX_ID_LENGTH + " bytes in UTF-8 encoding).");
+
+ if(id.equals(".") || id.equals(".."))
+ throw new IllegalArgumentException(idName + " is invalid.");
+
+ if(!containsValidChars(id))
+ throw new IllegalArgumentException(idName +
+ " contains invalid characters.");
+ }
+
+ private static boolean containsValidChars(String name) {
+ char[] chars = name.toCharArray();
+ for(int i = 0; i < chars.length; i++)
+ if(SYMBOLIC_NAME_CHARACTERS.indexOf(chars[i]) == -1)
+ return false;
+
+ return true;
+ }
+}
Added: felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/package.html
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/package.html?rev=616813&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/package.html (added)
+++ felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/package.html Wed Jan 30 08:46:24 2008
@@ -0,0 +1,10 @@
+<!-- $Header: /cvshome/build/org.osgi.service.monitor/src/org/osgi/service/monitor/package.html,v 1.4 2006/07/12 21:07:13 hargrave Exp $ -->
+<BODY>
+<p>Monitor Admin Package Version 1.0.
+<p>Bundles wishing to use this package must list the package
+in the <TT>Import-Package</TT> header of the bundle's manifest.
+For example:
+<pre>
+Import-Package: org.osgi.service.monitor; version=1.0
+</pre>
+</BODY>
Added: felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/packageinfo
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/packageinfo?rev=616813&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/packageinfo (added)
+++ felix/trunk/deploymentadmin/src/main/java/org/osgi/service/monitor/packageinfo Wed Jan 30 08:46:24 2008
@@ -0,0 +1 @@
+version 1.0
Added: felix/trunk/deploymentadmin/src/main/java/org/osgi/service/prefs/BackingStoreException.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/src/main/java/org/osgi/service/prefs/BackingStoreException.java?rev=616813&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/src/main/java/org/osgi/service/prefs/BackingStoreException.java (added)
+++ felix/trunk/deploymentadmin/src/main/java/org/osgi/service/prefs/BackingStoreException.java Wed Jan 30 08:46:24 2008
@@ -0,0 +1,83 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.prefs/src/org/osgi/service/prefs/BackingStoreException.java,v 1.12 2006/07/11 13:15:55 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2001, 2006). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.osgi.service.prefs;
+
+/**
+ * Thrown to indicate that a preferences operation could not complete because of
+ * a failure in the backing store, or a failure to contact the backing store.
+ *
+ * @version $Revision: 1.12 $
+ */
+public class BackingStoreException extends Exception {
+ static final long serialVersionUID = -1415637364122829574L;
+ /**
+ * Nested exception.
+ */
+ private final Throwable cause;
+
+ /**
+ * Constructs a <code>BackingStoreException</code> with the specified detail
+ * message.
+ *
+ * @param s The detail message.
+ */
+ public BackingStoreException(String s) {
+ super(s);
+ this.cause = null;
+ }
+
+ /**
+ * Constructs a <code>BackingStoreException</code> with the specified detail
+ * message.
+ *
+ * @param s The detail message.
+ * @param cause The cause of the exception. May be <code>null</code>.
+ * @since 1.1
+ */
+ public BackingStoreException(String s, Throwable cause) {
+ super(s);
+ this.cause = cause;
+ }
+
+ /**
+ * Returns the cause of this exception or <code>null</code> if no cause was
+ * specified when this exception was created.
+ *
+ * @return The cause of this exception or <code>null</code> if no cause was
+ * specified.
+ * @since 1.1
+ */
+ public Throwable getCause() {
+ return cause;
+ }
+
+ /**
+ * The cause of this exception can only be set when constructed.
+ *
+ * @param cause Cause of the exception.
+ * @return This object.
+ * @throws java.lang.IllegalStateException This method will always throw an
+ * <code>IllegalStateException</code> since the cause of this
+ * exception can only be set when constructed.
+ * @since 1.1
+ */
+ public Throwable initCause(Throwable cause) {
+ throw new IllegalStateException();
+ }
+
+}