The Wire Admin service is an administrative service that is used to control a wiring topology in the OSGi Framework. It is intended to be used by user interfaces or management programs that control the wiring of services in an OSGi Framework.
The Wire Admin service plays a crucial role in minimizing the amount of context-specific knowledge required by bundles when used in a large array of configurations. The Wire Admin service fulfills this role by dynamically wiring services together. Bundles participate in this wiring process by registering services that produce or consume data. The Wire Admin service wires the services that produce data to services which consume data.
The purpose of wiring services together is to allow configurable cooperation of bundles in an OSGi Framework. For example, a temperature sensor can be connected to a heating module to provide a controlled system.
The Wire Admin service is a very important OSGi configuration service and is designed to cooperate closely with the Configuration Admin service, as defined in Configuration Admin Service Specification.
-
Topology Management - Provide a comprehensive mechanism to link data-producing components with data-consuming components in an OSGi environment.
-
Configuration Management - Contains configuration data in order to allow either party to adapt to the special needs of the wire.
-
Data Type Handling - Facilitate the negotiation of the data type to be used for data transfer between producers of data and consumers of data. Consumers and producers must be able to handle multiple data types for data exchanges using a preferred order.
-
Composites - Support producers and consumers that can handle a large number of data items.
-
Security - Separate connected parties from each other. Each party must not be required to hold the service object of the other party.
-
Simplicity - The interfaces should be designed so that both parties, the Producer and the Consumer services, should be easy to implement.
-
Producer - A service object that generates information to be used by a Consumer service.
-
Consumer - A service object that receives information generated by a Producer service.
-
Wire - An object created by the Wire Admin service that defines an association between a Producer service and a Consumer service. Multiple Wire objects can exist between the same Producer and Consumer pair.
-
WireAdmin - The service that provides methods to create, update, remove, and list
Wire
objects. -
WireAdminListener - A service that receives events from the Wire Admin service when the
Wire
object is manipulated or used. -
WireAdminEvent - The event that is sent to a
WireAdminListener
object, describing the details of what happened. -
Configuration Properties - Properties that are associated with a
Wire
object and that contain identity and configuration information set by the administrator of the Wire Admin service. -
PID - The Persistent IDentity as defined in the Configuration Admin specification.
-
Flavors - The different data types that can be used to exchange information between Producer and Consumer services.
-
Composite Producer/Consumer - A Producer/Consumer service that can generate/accept different kinds of values.
-
Envelope - An interface for objects that can identify a value that is transferred over the wire.
Envelope
objects contain also a scope name that is used to verify access permissions. -
Scope - A set of names that categorizes the kind of values contained in
Envelope
objects for security and selection purposes. -
Basic Envelope - A concrete implementation of the
Envelope
interface. -
WirePermission - A Permission sub-class that is used to verify if a Consumer service or Producer service has permission for specific scope names.
-
Composite Identity - A name that is agreed between a composite Consumer and Producer service to identify the kind of objects that they can exchange.
The Wire Admin service maintains a set of persistent
Wire
objects. A Wire
object contains a
Persistent IDentity (PID) for a Consumer service and a PID for a
Producer service. (Wire
objects can therefore be created
when the Producer or Consumer service is not registered.)
If both those Producer and Consumer services are registered with
the Framework, they are connected by the Wire Admin service. The Wire
Admin service calls a method on each service object and provides the
list of Wire
objects to which they are connected.
When a Producer service has new information, it should send this
information to each of the connected Wire
objects. Each
Wire
object then must check the filtering and security. If
both filtering and security allow the transfer, the Producer service
should inform the associated Consumer service with the new information.
The Consumer services can also poll a Wire
object for an
new value at any time.
When a Consumer or Producer service is unregistered from the OSGi
Framework, the other object in the association is informed that the
Wire
object is no longer valid.
Administrative applications can use the Wire Admin service to create and delete wires. These changes are immediately reflected in the current topology and are broadcast to Wire Admin Listener services.
A Producer
is a service that can produce a sequence of
data objects. For example, a Producer
service can produce,
among others, the following type of objects:
-
Measurement
objects that represent a sensor measurement such as temperature, movement, or humidity. -
A
String
object containing information for user consumption, such as headlines. -
A
Date
object indicating the occurrence of a periodic event. -
Position information.
-
Envelope
objects containing status items which can be any type.
A Producer service must be registered with the OSGi Framework
under the interface name
org.osgi.service.wireadmin.Producer
. The following service
properties must be set:
-
service.pid
- The value of this property, also known as the PID, defines the Persistent IDentity of a service. A Producer service must always use the same PID value whenever it is registered. The PID value allows the Wire Admin service to consistently identify the Producer service and create a persistentWire
object that links a Producer service to a Consumer service. See [1] Design Patterns specification for the rules regarding PIDs. -
wireadmin.producer.flavors
- The value of this property is an array ofClass
objects (Class[]
) that are the classes of the objects the service can produce. See Flavors for more information about the data type negotiation between Producer and Consumer services. -
wireadmin.producer.filters
- This property indicates to the Wire Admin service that this Producer service performs its own update filtering, meaning that the consumer can limit the number of update calls with a filter expression. This does not modify the data; it only determines whether an update via the wire occurs. If this property is not set, the Wire object must filter according to the description in Composite objects. This service registration property does not need to have a specific value. -
wireadmin.producer.scope
- Only for a composite Producer service, a list of scope names that define the scope of this Producer service, as explained in Scope. -
wireadmin.producer.composite
- List the composite identities of Consumer services with which this Producer service can interoperate. This property is of typeString[]
. A composite Consumer service can inter-operate with a composite Producer service when there is at least one name that occurs in both the Consumer service's array and the Producer service's array for this property.
The Wire Admin service connects a Producer service and a Consumer
service by creating a Wire
object. If the Consumer and
Producer services that are bound to a Wire
object are
registered with the Framework, the Wire Admin service must call the
consumersConnected(Wire[]) method on the Producer
service
object. Every change in the Wire Admin service that affects the Wire
object to which a Producer service is connected must result in a call to
this method. This requirement ensures that the Producer
object is informed of its role in the wiring topology. If the Producer
service has no Wire
objects attached when it is registered,
the Wire Admin service must always call
consumersConnected(null)
. This situation implies that a
Producer service can assume it always gets called back from the Wire
Admin service when it registers.
The following example shows a clock producer service that sends
out a Date
object every second.
public class Clock extends Thread implementsProducer {
Wire wires[];
BundleContext context;
boolean quit;
Clock( BundleContext context ) {
this.context = context;
start();
}
public synchronized void run() {
Hashtable p = new Hashtable();
p.put( org.osgi.service.wireadmin.WireConstants.
WIREADMIN_PRODUCER_FLAVORS,
new Class[] { Date.class } );
p.put( org.osgi.framework.Constants.SERVICE_PID,
"com.acme.clock" );
context.registerService(
Producer.class.getName(),this,p );
while( ! quit )
try {
Date now = new Date();
for( int i=0; wires!=null && i<wires.length;i++ )
wires[i].update( now );
wait( 1000 );
}
catch( InterruptedException ie) {
/* will recheck quit */
}
}
public void synchronized consumersConnected(Wire wires[])
{
this.wires = wires;
}
public Object polled(Wire wire) { return new Date(); }
...
}
Communication between Consumer and Producer services can be initiated in one of the following ways.
-
The Producer service calls the update(Object) method on the Wire object. The
Wire
object implementation must then call the updated(Wire,Object) method on theConsumer
service, if the filtering allows this. -
The
Consumer
service can call poll() on theWire
object. TheWire
object must then call polled(Wire) on theProducer
object. Update filtering must not apply to polling.
Consumer services can only understand specific data types, and are
therefore restricted in what data they can process. The acceptable
object classes, the flavors, are communicated by the Consumer service to
the Wire Admin service using the Consumer service's service registration
properties. The method getFlavors() on the Wire
object returns this
list of classes. This list is an ordered list in which the first class
is the data type that is the most preferred data type supported by the
Consumer service. The last class is the least preferred data type. The
Producer service must attempt to convert its data into one of the data
types according to the preferred order, or will return null
from the poll
method to the Consumer service if none of the
types are recognized.
Classes cannot be easily compared for equivalence. Sub-classes and
interfaces allow classes to masquerade as other classes. The
Class.isAssignableFrom(Class)
method verifies whether a
class is type compatible, as in the following example:
Object polled(Wire wire) {
Class clazzes[] = wire.getFlavors();
for ( int i=0; i<clazzes.length; i++ ) {
Class clazz = clazzes[i];
if ( clazz.isAssignableFrom( Date.class ) )
return new Date();
if ( clazz.isAssignableFrom( String.class) )
return new Date().toString();
}
return null;
}
The order of the if
statements defines the
preferences of the Producer
object. Preferred data types
are checked first. This order normally works as expected but in rare
cases, sub-classes can change it. Normally, however, that is not a
problem.
A Consumer service is a service that receives information from one or more Producer services and is wired to Producer services by the Wire Admin service. Typical Consumer services are as follows:
-
The control of an actuator, such as a heating element, oven, or electric shades
-
A display
-
A log
-
A state controller such as an alarm system
A Consumer service must be registered with the OSGi Framework
under the interface name
org.osgi.service.wireadmin.Consumer
. The following service
properties must be set:
-
service.pid
- The value of this property, also known as the PID, defines the Persistent IDentity of a service. A Consumer service must always use the same PID value whenever it is registered. The PID value allows the Wire Admin service to consistently identify the Consumer service and create a persistentWire
object that links a Producer service to a Consumer service. See the Configuration Admin specification for the rules regarding PIDs. -
wireadmin.consumer.flavors
- The value of this property is an array ofClass
objects (Class[]
) that are the acceptable classes of the objects the service can process. See Flavors for more information about the data type negotiation between Producer and Consumer services. -
wireadmin.consumer.scope
- Only for a composite Consumer service, a list of scope names that define the scope of this Consumer service, as explained in Scope. -
wireadmin.consumer.composite
- List the composite identities of Producer services that this Consumer service can interoperate with. This property is of typeString[]
. A composite Consumer service can interoperate with a composite Producer service when at least one name occurs in both the Consumer service's array and the Producer service's array for this property.
When a Consumer
service is registered and a
Wire
object exists that associates it to a registered
Producer service, the producersConnected(Wire[]) method is called on the Consumer
service.
Every change in the Wire Admin service that affects a
Wire
object to which a Consumer service is connected must
result in a call to the producersConnected(Wire[]) method. This rule ensures that the Consumer
object is informed of its role in the wiring topology. If the Consumer
service has no Wire
objects attached, the argument to the
producersConnected(Wire[]) method must be null
. This method
must also be called when a Producer service registers for the first time
and no Wire
objects are available.
For example, a service can implement a Consumer service that logs all objects that are sent to it in order to allow debugging of a wiring topology.
public class LogConsumer implements Consumer{
public LogConsumer( BundleContext context ) {
Hashtable ht = new Hashtable();
ht.put(
Constants.SERVICE_PID, "com.acme.logconsumer" );
ht.put( WireConstants.WIREADMIN_CONSUMER_FLAVORS,
new Class[] { Object.class } );
context.registerService( Consumer.class.getName(),
this, ht );
}
public void updated( Wire wire, Object o ) {
getLog().log( LogService.LOG_INFO, o.toString() );
}
public void producersConnected( Wire [] wires) {}
LogService getLog() { ... }
}
When the Producer
service produces a new value, it
calls the update(Object) method on the Wire
object, which in
turn calls the updated(Wire,Object) method on the Consumer
service
object. When the Consumer service needs a value immediately, it can call
the poll() method on the Wire
object which in
turn calls the polled(Wire) method on the Producer
service.
If the poll() method on the Wire object is called and the
Producer is unregistered, it must return a null
value.
Producer
objects send objects of different data types
through Wire
objects. A Consumer
service
object should offer a list of preferred data types (classes) in its
service registration properties. The Producer service, however, can
still send a null
object or an object that is not of the
preferred types. Therefore, the Consumer
service must check
the data type and take the appropriate action. If an object type is
incompatible, then a log message should be logged to allow the operator
to correct the situation.
The following example illustrates how a Consumer service can
handle objects of type Date
, Measurement
, and
String
.
void process( Object in ) {
if ( in instanceof Date )
processDate( (Date) in );
else if ( in instanceof Measurement )
processMeasurement( (Measurement) in );
else if ( in instanceof String )
processString( (String) in );
else
processError( in );
}
The Wire Admin service can call the consumersConnected
or producersConnected
methods during the registration of the
Consumer or Producer service. Care should be taken in this method call so
that no variables are used that are not yet set, such as the
ServiceRegistration
object that is returned from the
registration. The same is true for the updated
or
polled
callback because setting the Wire
objects
on the Producer service causes such a callback from the
consumersConnected
or producersConnected
method.
A Wire Admin service must call the producersConnected
and consumersConnected
method asynchronously from the
registrations, meaning that the Consumer or Producer service can use
synchronized
to restrict access to critical variables.
When the Wire Admin service is stopped, it must disconnect all
connected consumers and producers by calling
producersConnected
and consumersConnected
with a
null
for the wires
parameter.
A Wire
object has a set of properties (a
Dictionary
object) that configure the association between a
Consumer service and a Producer service. The type and usage of the keys,
as well as the allowed types for the values are defined in Configuration Properties.
The Wire properties are explained in the following table.
Table 108.1 Standard Wire Properties
Constant | Description |
---|---|
WIREADMIN_PID |
The value of this property is a unique Persistent
IDentity as defined in chapter Configuration Admin Service Specification. This
PID must be automatically created by the Wire Admin service for
each new |
WIREADMIN_PRODUCER_PID |
The value of the property is the PID of the
|
WIREADMIN_CONSUMER_PID |
The value of this property is the PID of the
|
WIREADMIN_FILTER |
The value of this property is an OSGi filter string that is used to control the update of produced values. This filter can contain a number of attributes as explained in Wire Flow Control. |
The properties associated with a Wire
object are not
limited to the ones defined in Table 108.1. The
Dictionary
object can also be used for configuring
both Consumer
services and
Producer
services. Both services receive the
Wire
object and can inspect the properties and adapt their
behavior accordingly.
In the following example, the properties of a Wire
object, which are set by the Operator or User, are used to configure a
Producer
service that monitors a user's email account
regularly and sends a message when the user has received email. This
WireMail
service is illustrated as follows:
public class WireMail extends Thread
implements Producer {
Wire wires[];
BundleContext context;
boolean quit;
public void start( BundleContext context ) {
Hashtable ht = new Hashtable();
ht.put( Constants.SERVICE_PID, "com.acme.wiremail" );
ht.put( WireConstants.WIREADMIN_PRODUCER_FLAVORS,
new Class[] { Integer.class } );
context.registerService( this,
Producer.class.getName(),
ht );
}
public synchronized void consumersConnected(
Wire wires[] ) {
this.wires = wires;
}
public Object polled( Wire wire ) {
Dictionary p = wire.getProperties();
// The password should be
// obtained from User Admin Service
int n = getNrMails(
p.get( "userid" ),
p.get( "mailhost" ) );
return new Integer( n );
}
public synchronized void run() {
while ( !quit )
try {
for ( int i=0; wires != null && i<wires.length;i++)
wires[i].update( polled( wires[i] ) );
wait( 150000 );
}
catch( InterruptedException e ) { break; }
}
...
}
A Producer and/or Consumer service for each information item is usually the best solution. This solution is not feasible, however, when there are hundreds or thousands of information items. Each registered Consumer or Producer service carries the overhead of the registration, which may overwhelm a Framework implementation on smaller platforms.
When the size of the platform is an issue, a Producer and a Consumer service should abstract a larger number of information items. These Consumer and Producer services are called composite.
Composite Producer and Consumer services should register
respectively the WIREADMIN_PRODUCER_COMPOSITE and WIREADMIN_CONSUMER_COMPOSITE composite identity property
with their service registration. These properties should contain a list of
composite identities. These identities are not defined here, but are up to
a mutual agreement between the Consumer and Producer service. For example,
a composite identity could be MOST-1.5
or
GSM-Phase2-Terminal
. The name may follow any scheme but will
usually have some version information embedded. The composite identity
properties are used to match Consumer and Producer services with each
other during configuration of the Wire Admin service. A Consumer and
Producer service should inter-operate when at least one equal composite
identity is listed in both the Producer and Consumer composite identity
service property.
Composite producers/consumers must identify the
kind of objects that are transferred over the
Wire
object, where kind refers to the
intent of the object, not the data type. For example, a Producer service
can represent the status of a door-lock and the status of a window as a
boolean
. If the status of the window is transferred as a
boolean
to the Consumer service, how would it know that this
boolean
represents the window and not the door-lock
To avoid this confusion, the Wire Admin service includes an
Envelope
interface. The purpose of the Envelope
interface is to associate a value object with:
-
An identification object
-
A scope name
The Envelope
object's identification object is used
to identify the value carried in the Envelope
object. Each
unique kind of value must have its own unique identification object. For
example, a left-front-window should have a different identification
object than a rear-window.
The identification is of type Object
. Using the
Object
class allows String
objects to be used,
but also makes it possible to use more complex objects. These objects
can convey information in a way that is mutually agreed between the
Producer and Consumer service. For example, its type may differ
depending on each kind of value so that the Visitor
pattern, see [1] Design Patterns, can be used. Or it may contain
specific information that makes the Envelope
object easier
to dispatch for the Consumer service.
The scope name is a String
object that
categorizes the Envelope
object. The
scope name is used to limit the kind of objects that can be exchanged
between composite Producer and Consumer services, depending on security
settings.
The name-space for this scope should be mutually agreed between the Consumer and Producer services a priori. For the Wire Admin service, the scope name is an opaque string. Its syntax is specified in Scope name syntax.
Both composite Producer and Consumer services must add a list of
their supported scope names to the service registration properties. This
list is called the scope of that service. A
Consumer service must add this scope property with the name of WIREADMIN_CONSUMER_SCOPE, a Producer service must add this scope property
with the name WIREADMIN_PRODUCER_SCOPE. The type of this property must be a
String[]
object.
Not registering this property by the Consumer or the Producer
service indicates to the Wire Admin service that any Wire
object connected to that service must return null
for the
Wire.
getScope() method. This case must be interpreted by the
Consumer or Producer service that no scope verification is taking place.
Secure Producer services should not produce values for this
Wire
object and secure Consumer services should not accept
values.
It is also allowed to register with a
wildcard, indicating that all scope names are
supported. In that case, the WIREADMIN_SCOPE_ALL (which is String[] { "*" }
) should
be registered as the scope of the service. The Wire
object's scope is then fully defined by the other service connected to
the Wire
object.
The following example shows how a scope is registered.
static String [] scope = { "DoorLock", "DoorOpen","VIN" };
public void start( BundleContext context ) {
Dictionary properties = new Hashtable();
properties.put(
WireConstants.WIREADMIN_CONSUMER_SCOPE,
scope );
properties.put( WireConstants.WIREADMIN_CONSUMER_PID,
"com.acme.composite.consumer" );
properties.put(
WireConstants.WIREADMIN_CONSUMER_COMPOSITE,
new String[] { "OSGiSP-R3" } );
context.registerService( Consumer.class.getName(),
new AcmeConsumer(),
properties );
}
Both a composite Consumer and Producer service must register a
scope to receive scope support from the Wire
object. These
two scopes must be converted into a single Wire
object's
scope and scope names in this list must be checked for the appropriate
permissions. This resulting scope is available from the
Wire.
getScope() method.
If no scope is set by either the Producer or the Consumer service
the result must be null
. In that case, the Producer or
Consumer service must assume that no security checking is in place. A
secure Consumer or Producer service should then refuse to operate with
that Wire
object.
Otherwise, the resulting scope is the intersection of the Consumer
and Producer service scope where each name in the scope, called
m
, must be implied by a
WirePermission[m,CONSUME]
of the Consumer service, and
WirePermission[m,PRODUCE]
of the Producer service.
If either the Producer or Consumer service has registered a
wildcard scope then it must not restrict the list of the other service,
except for the permission check. If both the Producer and Consumer
service registered a wild-card, the resulting list must be WIREADMIN_SCOPE_ALL ( String[]{"*"}
).
For example, the Consumer service has registered a scope of
{A,B,C}
and has WirePermission[*,CONSUME]
. The
Producer service has registered a scope of {B,C,E}
and has
WirePermission[C|E, PRODUCE,]
. The resulting scope is then
{C}
. The following table shows this and more
examples.
Table 108.2 Examples of scope calculation. C=Consumer, P=Producer, p=WirePermission, s=scope
Cs | Cp | Ps | Pp | Wire Scope |
---|---|---|---|---|
null |
null |
null |
||
{A,B,C} |
* |
null |
null |
|
null |
{C,D,E} |
null |
||
{A,B,C} |
B|C |
{A,B,C} |
A|B |
{B} |
* |
* |
{A,B,C} |
A|B|C |
{A,B,C} |
* |
* |
* |
* |
{*} |
{A,B,C} |
A|B|C |
{A,B,C} |
X |
{} |
{A,B,C} |
* |
{B,C,E} |
C|E |
{C} |
The Wire
object's scope must be calculated only once,
when both the Producer and Consumer service become connected. When a
Producer or Consumer service subsequently modifies its scope, the Wire
object must not modify the original scope. A
Consumer and a Produce service can thus assume that the scope does not
change after the producersConnected
method or
consumersConnected
method has been called.
When an Envelope
object is used as argument in
Wire.update(Object)
then the Wire
object must
verify that the Envelope
object's scope name is included in
the Wire
object's scope. If this is not the case, the
update must be ignored (the updated
method on the Consumer
service must not be called).
A composite Producer represents a number of values, which is
different from a normal Producer that can always return a single object
from the poll
method. A composite Producer must therefore
return an array of Envelope
objects
(Envelope[]
). This array must contain Envelope
objects for all the values that are in the Wire
object's
scope. It is permitted to return all possible values for the Producer
because the Wire
object must remove all
Envelope
objects that have a scope name not listed in the
Wire
object's scope.
Composite Producer and Consumer services must always use a flavor
of the Envelope
class. The data types of the values must be
associated with the scope name or identification and mutually agreed
between the Consumer and Producer services.
Flavors and Envelope
objects both represent
categories of different values. Flavors, however, are different Java
classes that represent the same kind of value. For example, the tire
pressure of the left front wheel could be passed as a
Float
, an Integer
, or a
Measurement
object. Whatever data type is chosen, it is
still the tire pressure of the left front wheel. The
Envelope
object represents the kind of object, for example
the right front wheel tire pressure, or the left rear wheel.
Scope names are normal String
objects and can, in
principle, contain any Unicode character. In use, scope names can be a
full wildcard ('*') but they cannot be partially wildcarded for matching
scopes.
Scope names are used with the WirePermission
class
that extends java.security.BasicPermission
. The
BasicPermission
class implements the implies
method and performs the name matching. The wildcard matching of this
class is based on the concept of names where the constituents of the
name are separated with a period ('.'
): for example,
org.osgi.service.http.port
.
Scope names must therefore follow the rules for fully qualified
Java class names. For example, door.lock
is a correct scope
name while door-lock
is not.
The WIREADMIN_FILTER
property contains a filter
expression (as defined in the OSGi Framework Filter
class)
that is used to limit the number of updates to the Consumer
service. This is necessary because information can arrive at a much
greater rate than can be processed by a Consumer
service. For
example, a single CAN bus (the electronic control bus used in current
cars) in a car can easily deliver hundreds of measurements per second to
an OSGi based controller. Most of these measurements are not relevant to
the OSGi bundles, at least not all the time. For example, a bundle that
maintains an indicator for the presence of frost is only interested in
measurements when the outside temperature passes the 4 degrees Celsius
mark.
Limiting the number of updates from a Producer service can make a significant difference in performance (meaning that less hardware is needed). For example, a vendor can implement the filter in native code and remove unnecessary updates prior to processing in the Java Virtual Machine (JVM). This is depicted in Figure 108.5 on page .
The filter can use any combination of the following attributes in a filter to implement many common filtering schemes:
Table 108.3 Filter Attribute Names
Constant | Description |
---|---|
WIREVALUE_CURRENT |
Current value of the data from the Producer service. |
WIREVALUE_PREVIOUS |
Previous data value that was reported to the Consumer service. |
WIREVALUE_DELTA_ABSOLUTE |
The actual positive difference between the previous data value and the current data value. For example, if the previous data value was 3 and the current data value is -0.5, then the absolute delta is 3.5. This filter attribute is not set when the current or previous value is not a number. |
WIREVALUE_DELTA_RELATIVE |
The absolute (meaning always positive) relative
change between the current and the previous data values,
calculated with the following formula: |
WIREVALUE_ELAPSED |
The time in milliseconds between the last time the
|
Filter attributes can be used to implement many common filtering
schemes that limit the number of updates that are sent to a Consumer
service. The Wire Admin service specification requires that updates to a
Consumer service are always filtered if the WIREADMIN_FILTER
Wire property is present. Producer services that wish to perform the
filtering themselves should register with a service property
WIREADMIN_PRODUCER_FILTERS
. Filtering must be performed by
the Wire
object for all other Producer services.
Filtering for composite Producer services is not supported. When a
filter is set on a Wire
object, the Wire must still perform
the filtering (which is limited to time filtering because an
Envelope
object is not a magnitude), but this approach may
lose relevant information because the objects are of a different kind. For
example, an update of every 500 ms could miss all speed updates because
there is a wheel pressure update that resets the elapsed time. Producer
services should, however, still implement a filtering scheme that could
use proprietary attributes to filter on different kind of objects.
The simplest filter mechanism is based on time. The
wirevalue.elapsed
attribute contains the amount of
milliseconds that have passed since the last update to the associated
Consumer
service. The following example filter expression
illustrates how the updates can be limited to approximately 40 times per
minute (once every 1500 ms).
(wirevalue.elapsed>=1500)
Figure 108.6 depicts this example graphically.
A Consumer service is often not interested in an update if the data value has not changed. The following filter expression shows how a Consumer service can limit the updates from a temperature sensor to be sent only when the temperature has changed at least 1 °K.
(wirevalue.delta.absolute>=1)
Figure 108.7 depicts a band that is created by the absolute delta between the previous data value and the current data value. The Consumer is only notified with the updated(Wire,Object) method when a data value is outside of this band.
The delta may also be relative. For example, if a car is moving slowly, then updates for the speed of the car are interesting even for small variations. When a car is moving at a high rate of speed, updates are only interesting for larger variations in speed. The following example shows how the updates can be limited to data value changes of at least 10%.
(wirevalue.delta.relative>=0.1)
Figure 108.8 on page depicts a relative band. Notice that the size of the band is directly proportional to the size of the sample value.
A thermostat is a control device that usually has a hysteresis, which means that a heater should be switched on below a certain specified low temperature and should be switched off at a specified high temperature, where high > low. This is graphically depicted in Figure 108.9 on page . The specified acceptable temperatures reduce the amount of start/stops of the heater.
A Consumer
service that controls the heater is only
interested in events at the top and bottom of the hysteresis. If the
specified high value is 250 °K and the specified low value is 249 °K,
the following filter illustrates this concept:
(|(&(wirevalue.previous<=250)(wirevalue.current>250))
(&(wirevalue.previous>=249)(wirevalue.current<249))
)
Both Consumer
and Producer
services should
register with a property describing the classes of the data types they can
consume or produce respectively. The classes are the
flavors that the service supports. The purpose of
flavors is to allow an administrative user interface bundle to connect
Consumer and Producer services. Bundles should only create a connection
when there is at least one class shared between the flavors from a
Consumer service and a Producer service. Producer services are responsible
for selecting the preferred object type from the list of the object types
preferred by the Consumer service. If the Producer service cannot convert
its data to any of the flavors listed by the Consumer service,
null
should be used instead.
A converter is a bundle that registers a Consumer and a Producer service that are related and performs data conversions. Data values delivered to the Consumer service are processed and transferred via the related Producer service. The Producer service sends the converted data to other Consumer services. This is shown in Figure 108.10.
The Wire Admin service is the administrative service that is used to control the wiring topology in the OSGi Framework. It contains methods to create or update wires, delete wires, and list existing wires. It is intended to be used by user interfaces or management programs that control the wiring topology of the OSGi Framework.
The createWire(String,String,Dictionary) method is used to associate a Producer service with a Consumer service. The method always creates and returns a new object. It is therefore possible to create multiple, distinct wires between a Producer and a Consumer service. The properties can be used to create multiple associations between Producer and Consumer services in that act in different ways.
The properties of a Wire
object can be updated with the
update(Object) method. This method must update the properties in
the Wire object and must notify the associated Consumer and Producer
services if they are registered. Wire
objects that are no
longer needed can be removed with the deleteWire(Wire) method. All these methods are in the
WireAdmin
class and not in the Wire
class for
security reasons. See Security.
The getWires(String) method returns an array of Wire
objects (or null
). All objects are returned when the filter
argument is null
. Specifying a filter argument limits the
returned objects. The filter uses the same syntax as the Framework Filter
specification. This filter is applied to the properties of the
Wire
object and only Wire
objects that match
this filter are returned.
The following example shows how the getWires
method can
be used to print the PIDs of Producer
services that are wired
to a specific Consumer
service.
String f = "(wireadmin.consumer.pid=com.acme.x)";
Wire [] wires = getWireAdmin().getWires( f );
for ( int i=0; wires != null && i < wires.length;i++ )
System.out.println(
wires[i].getProperties().get(
"wireadmin.producer.pid")
);
The Wire Admin service has an extensive list of events that it can
deliver. The events allow other bundles to track changes in the topology
as they happen. For example, a graphic user interface program can use the
events to show when Wire
objects become connected, when these
objects are deleted, and when data flows over a Wire object.
A bundle that is interested in such events must register a
WireAdminListener
service object with a special
Integer
property WIREADMIN_EVENTS
("
wireadmin.events
"). This Integer
object contains
a bitmap of all the events in which this Wire Admin Listener service is
interested (events have associated constants that can be ORed together). A
Wire Admin service must not deliver events to the Wire Admin Listener
service when that event type is not in the bitmap. If no such property is
registered, no events are delivered to the Wire Admin Listener
service.
The WireAdminListener
interface has only one method:
wireAdminEvent(WireAdminEvent). The argument is a WireAdminEvent
object that contains the event type and associated data.
A WireAdminEvent
object can be sent asynchronously but
must be ordered for each Wire Admin Listener service. The way events must
be delivered is the same as described in Delivering
Events of OSGi Core Release 8. Wire Admin Listener services must not assume
that the state reflected by the event is still true when they receive the
event.
The following types are defined for a WireEvent
object:
Table 108.4 Events
Event type | Description |
---|---|
WIRE_CREATED |
A new |
WIRE_CONNECTED |
Both the |
WIRE_UPDATED |
The |
WIRE_TRACE |
The Consumer has seen a new value, either after the
Producer service has called the |
WIRE_DISCONNECTED |
The Producer service or Consumer service have become
unregistered and the |
WIRE_DELETED |
The |
CONSUMER_EXCEPTION |
The Consumer service generated an exception and the exception is included in the event. |
PRODUCER_EXCEPTION |
The Producer service generated an exception in a callback and the exception is included in the event. |
Wire admin events must be sent asynchronously to the Event Admin service by the Wire Admin implementation, if present. The topic of a Wire Admin Event is one of the following:
org/osgi/service/wireadmin/WireAdminEvent/<eventtype>
The following event types are supported:
WIRE_CREATED
WIRE_CONNECTED
WIRE_UPDATED
WIRE_TRACE
WIRE_DISCONNECTED
WIRE_DELETED
PRODUCER_EXCEPTION
CONSUMER_EXCEPTION
The properties of a wire admin event are the following.
-
event
- (WireAdminEvent)
TheWireAdminEvent
object broadcast by the Wire Admin service.
If the getWire
method returns a non null
value:
-
wire
- (Wire
) TheWire
object returned by thegetWire
method. -
wire.flavors
- (String[])
The names of the classes returned by theWire
getFlavors
method. -
wire.scope
- (String[])
The scope of theWire
object, as returned by itsgetScope
method. -
wire.connected
- (Boolean)
The result of theWire
isConnected
method. -
wire.valid
- (Boolean
) The result of theWire isValid
method.
If the getThrowable
method does not return
null
:
-
exception
- (Throwable)
The Exception returned by thegetThrowable
method. -
exception.class
- (String)
The fully-qualified class name of the related Exception. -
exception.message
- (String)
The message of the related Exception -
service
- (ServiceReference)
The Service Reference of the Wire Admin service. -
service.id
- (Long)
The service id of the WireAdmin service. -
service.objectClass
- (String[])
The Wire Admin service's object class (which must includeorg.osgi.service.wireadmin.WireAdmin
) -
service.pid
- (String)
The Wire Admin service's PID.
The Wire Admin service can be used to control the topology of consumers and producers that are services, as well as external entities. For example, a video camera controlled over an IEEE 1394B bus can be registered as a Producer service in the Framework's service registry and a TV, also connected to this bus, can be registered as a Consumer service. It would be very inefficient to stream the video data through the OSGi environment. Therefore, the Wire Admin service can be used to supply the external addressing information to the camera and the monitor to make a direct connection outside the OSGi environment. The Wire Admin service provides a uniform mechanism to connect both external entities and internal entities.
A Consumer service and a Producer service associated with a
Wire
object receive enough information to establish a direct
link because the PIDs of both services are in the Wire
object's properties. This situation, however, does not guarantee
compatibility between Producer and the Consumer
service. It is therefore recommended that flavors are used to ensure this
compatibility. Producer services that participate in an external
addressing scheme, like IEEE 1394B, should have a flavor that reflects
this address. In this case, there should then for example be a IEEE 1394B
address class. Consumer services that participate in this external
addressing scheme should only accept data of this flavor.
The OSGi Device Access Specification, defines the concept of a device category. This is a description of what classes and properties are used in a specific device category: for example, a UPnP device category that defines the interface that must be used to register for a UPnP device, among other things.
Device category descriptions should include a section that addresses the external wiring issue. This section should include what objects are send over the wire to exchange addressing information.
The Wire Admin service leverages the component architecture that the Framework service registry offers. Java Beans attempt to achieve similar goals. Java Beans are classes that follow a number of recommendations that allow them to be configured at run time. The techniques that are used by Java Beans during configuration are serialization and the construction of adapter classes.
Creating adapter classes in a resource constrained OSGi Framework was considered too heavy weight. Also, the dynamic nature of the OSGi environment, where services are registered and unregistered continuously, creates a mismatch between the intended target area of Java Beans and the OSGi Framework.
Also, Java Beans can freely communicate once they have a reference to each other. This freedom makes it impossible to control the communication between Java Beans.
This Wire Admin service specification was developed because it is
lightweight and leverages the unique characteristics of the OSGi
Framework. The concept of a Wire
object that acts as an
intermediate between the Producer and Consumer service allows the
implementation of a security policy because both parties cannot
communicate directly.
The Consumer and Producer service never directly communicate with
each other. All communication takes place through a Wire
object. This allows a Wire Admin service implementation to control the
security aspects of creating a connection, and implies that the Wire
Admin service must be a trusted service in a secure environment. Only
one bundle should have the ServicePermission[WireAdmin,
REGISTER]
.
ServicePermission[Producer|Consumer, REGISTER]
should
not be restricted. ServicePermission[Producer|Consumer,GET]
must be limited to trusted bundles (the Wire Admin service
implementation) because a bundle with this permission can call such
services and access information that it should not be able to
access.
This specification assumes that only a few applications require
access to the Wire Admin service. The WireAdmin
interface
contains all the security sensitive methods that create, update, and
remove Wire
objects. (This is the reason that the update
and delete methods are on the WireAdmin
interface and not
on the Wire
interface).
ServicePermission[WireAdmin,GET]
should therefore only be
given to trusted bundles that can manage the topology.
Composite Producer and Consumer services can be restricted in
their use of scope names. This restriction is managed with the
WirePermission
class. A WirePermission
consists of a scope name and the action CONSUME
or
PRODUCE
. The name used with the WirePermission
may contain wild-cards as specified in the
java.security.BasicPermission
class.
Wire Admin Package Version 1.0.
Bundles wishing to use this package must list the package in the Import-Package header of the bundle's manifest. This package has two types of users: the consumers that use the API in this package and the providers that implement the API in this package.
Example import for consumers using the API in this package:
Import-Package: org.osgi.service.wireadmin; version="[1.0,2.0)"
Example import for providers implementing the API in this package:
Import-Package: org.osgi.service.wireadmin; version="[1.0,1.1)"
-
BasicEnvelope
-BasicEnvelope
is an implementation of the Envelope interface -
Consumer
- Data Consumer, a service that can receive updated values from Producer services. -
Envelope
- Identifies a contained value. -
Producer
- Data Producer, a service that can generate values to be used by Consumer services. -
Wire
- A connection between a Producer service and a Consumer service. -
WireAdmin
- Wire Administration service. -
WireAdminEvent
- A Wire Admin Event. -
WireAdminListener
- Listener for Wire Admin Events. -
WireConstants
- Defines standard names forWire
properties, wire filter attributes, Consumer and Producer service properties. -
WirePermission
- Permission for the scope of aWire
object.
BasicEnvelope
is an implementation of the Envelope interface
Immutable
Content of this envelope, may be null
.
Identifying object for this Envelope
object, must not be null
Scope name for this object, must not be null
Constructor.
Return the identification of this Envelope
object.
An identification may be of any Java type. The type must be mutually
agreed between the Consumer and Producer services.
an object which identifies the status item in the address space of the composite producer, must not be null.
Return the scope name of this Envelope
object.
Scope names are used to restrict the communication between the Producer
and Consumer services. Only Envelopes
objects with a scope name
that is permitted for the Producer and the Consumer services must be
passed through a Wire
object.
the security scope for the status item, must not be null.
Return the value associated with this Envelope
object.
the value of the status item, or null
when no item is
associated with this object.
Data Consumer, a service that can receive updated values from Producer services.
Service objects registered under the Consumer
interface are expected
to consume values from a Producer service via a Wire
object. A
Consumer service may poll the Producer service by calling the
Wire.poll() method. The Consumer service will also receive an updated
value when called at it's updated(Wire, Object) method. The Producer
service should have coerced the value to be an instance of one of the types
specified by the Wire.getFlavors() method, or one of their
subclasses.
Consumer service objects must register with a service.pid
and a
WireConstants.WIREADMIN_CONSUMER_FLAVORS property. It is recommended
that Consumer service objects also register with a
service.description
property.
If an Exception
is thrown by any of the Consumer
methods, a
WireAdminEvent
of type WireAdminEvent.CONSUMER_EXCEPTION is
broadcast by the Wire Admin service.
Security Considerations - Data consuming bundles will require
ServicePermission[Consumer,REGISTER]
. In general, only the Wire Admin
service bundle should have this permission. Thus only the Wire Admin service
may directly call a Consumer service. Care must be taken in the sharing of
Wire
objects with other bundles.
Consumer services must be registered with their scope when they can receive
different types of objects from the Producer service. The Consumer service
should have WirePermission
for each of these scope names.
An array of the current and complete list of Wire
objects to which this Consumer service is connected. May be
null
if the Consumer service is not currently connected to
any Wire
objects.
Update the list of Wire
objects to which this Consumer service is
connected.
This method is called when the Consumer service is first registered and
subsequently whenever a Wire
associated with this Consumer
service becomes connected, is modified or becomes disconnected.
The Wire Admin service must call this method asynchronously. This implies that implementors of Consumer can be assured that the callback will not take place during registration when they execute the registration in a synchronized method.
The Wire
object which is delivering the updated
value.
The updated value. The value should be an instance of one of the types specified by the Wire.getFlavors() method.
Update the value. This Consumer service is called by the Wire
object with an updated value from the Producer service.
Note: This method may be called by a Wire
object prior to this
object being notified that it is connected to that Wire
object
(via the producersConnected(Wire[]) method).
When the Consumer service can receive Envelope
objects, it must
have registered all scope names together with the service object, and
each of those names must be permitted by the bundle's
WirePermission
. If an Envelope
object is delivered with
the updated
method, then the Consumer service should assume that
the security check has been performed.
Identifies a contained value.
An Envelope
object combines a status value, an identification object
and a scope name. The Envelope
object allows the use of standard Java
types when a Producer service can produce more than one kind of object. The
Envelope
object allows the Consumer service to recognize the kind of
object that is received. For example, a door lock could be represented by a
Boolean
object. If the Producer
service would send such a
Boolean
object, then the Consumer service would not know what door
the Boolean
object represented. The Envelope
object contains
an identification object so the Consumer service can discriminate between
different kinds of values. The identification object may be a simple
String
object, but it can also be a domain specific object that is
mutually agreed by the Producer and the Consumer service. This object can
then contain relevant information that makes the identification easier.
The scope name of the envelope is used for security. The Wire object must
verify that any Envelope
object send through the update
method or coming from the poll
method has a scope name that matches
the permissions of both the Producer service and the Consumer service
involved. The wireadmin package also contains a class BasicEnvelope
that implements the methods of this interface.
Return the identification of this Envelope
object.
An identification may be of any Java type. The type must be mutually
agreed between the Consumer and Producer services.
an object which identifies the status item in the address space of the composite producer, must not be null.
Return the scope name of this Envelope
object.
Scope names are used to restrict the communication between the Producer
and Consumer services. Only Envelopes
objects with a scope name
that is permitted for the Producer and the Consumer services must be
passed through a Wire
object.
the security scope for the status item, must not be null.
Data Producer, a service that can generate values to be used by Consumer services.
Service objects registered under the Producer interface are expected to
produce values (internally generated or from external sensors). The value can
be of different types. When delivering a value to a Wire
object, the
Producer service should coerce the value to be an instance of one of the
types specified by Wire.getFlavors(). The classes are specified in
order of preference.
When the data represented by the Producer object changes, this object should
send the updated value by calling the update
method on each of
Wire
objects passed in the most recent call to this object's
consumersConnected(Wire[]) method. These Wire
objects will
pass the value on to the associated Consumer
service object.
The Producer service may use the information in the Wire
object's
properties to schedule the delivery of values to the Wire
object.
Producer service objects must register with a service.pid
and a
WireConstants.WIREADMIN_PRODUCER_FLAVORS property. It is recommended
that a Producer service object also registers with a
service.description
property. Producer service objects must register
with a WireConstants.WIREADMIN_PRODUCER_FILTERS property if the
Producer service will be performing filtering instead of the Wire
object.
If an exception is thrown by a Producer object method, a
WireAdminEvent
of type WireAdminEvent.PRODUCER_EXCEPTION is
broadcast by the Wire Admin service.
Security Considerations. Data producing bundles will require
ServicePermission[Producer,REGISTER]
to register a Producer service.
In general, only the Wire Admin service should have
ServicePermission[Producer,GET]
. Thus only the Wire Admin service may
directly call a Producer service. Care must be taken in the sharing of
Wire
objects with other bundles.
Producer services must be registered with scope names when they can send
different types of objects (composite) to the Consumer service. The Producer
service should have WirePermission
for each of these scope names.
An array of the current and complete list of Wire
objects to which this Producer service is connected. May be
null
if the Producer is not currently connected to any
Wire
objects.
Update the list of Wire
objects to which this Producer
object is connected.
This method is called when the Producer service is first registered and
subsequently whenever a Wire
associated with this Producer
becomes connected, is modified or becomes disconnected.
The Wire Admin service must call this method asynchronously. This implies that implementors of a Producer service can be assured that the callback will not take place during registration when they execute the registration in a synchronized method.
The Wire
object which is polling this service.
Return the current value of this Producer
object.
This method is called by a Wire
object in response to the
Consumer service calling the Wire
object's poll
method.
The Producer should coerce the value to be an instance of one of the
types specified by Wire.getFlavors(). The types are specified in
order of preference. The returned value should be as new or newer than
the last value furnished by this object.
Note: This method may be called by a Wire
object prior to this
object being notified that it is connected to that Wire
object
(via the consumersConnected(Wire[]) method).
If the Producer service returns an Envelope
object that has an
impermissible scope name, then the Wire object must ignore (or remove)
the transfer.
If the Wire
object has a scope set, the return value must be an
array of Envelope
objects (Envelope[]
). The Wire
object must have removed any Envelope
objects that have a scope
name that is not in the Wire object's scope.
The current value of the Producer service or null
if the
value cannot be coerced into a compatible type. Or an array of
Envelope
objects.
A connection between a Producer service and a Consumer service.
A Wire
object connects a Producer service to a Consumer service. Both
the Producer and Consumer services are identified by their unique
service.pid
values. The Producer and Consumer services may
communicate with each other via Wire
objects that connect them. The
Producer service may send updated values to the Consumer service by calling
the update(Object) method. The Consumer service may request an
updated value from the Producer service by calling the poll()
method.
A Producer service and a Consumer service may be connected through multiple
Wire
objects.
Security Considerations. Wire
objects are available to Producer and
Consumer services connected to a given Wire
object and to bundles
which can access the WireAdmin
service. A bundle must have
ServicePermission[WireAdmin,GET]
to get the WireAdmin
service
to access all Wire
objects. A bundle registering a Producer service
or a Consumer service must have the appropriate
ServicePermission[Consumer|Producer,REGISTER]
to register the service
and will be passed Wire
objects when the service object's
consumersConnected
or producersConnected
method is called.
Scope. Each Wire object can have a scope set with the setScope
method. This method should be called by a Consumer service when it assumes a
Producer service that is composite (supports multiple information items). The
names in the scope must be verified by the Wire
object before it is
used in communication. The semantics of the names depend on the Producer
service and must not be interpreted by the Wire Admin service.
Consumers of this API must not implement this interface
Return the list of data types understood by the Consumer service
connected to this Wire
object. Note that subclasses of the
classes in this list are acceptable data types as well.
The list is the value of the
WireConstants.WIREADMIN_CONSUMER_FLAVORS service property of the
Consumer service object connected to this object. If no such property was
registered or the type of the property value is not Class[]
, this
method must return null
.
An array containing the list of classes understood by the
Consumer service or null
if the Wire
is not
connected, or the consumer did not register a
WireConstants.WIREADMIN_CONSUMER_FLAVORS property or the
value of the property is not of type Class[]
.
Return the last value sent through this Wire
object.
The returned value is the most recent, valid value passed to the
update(Object) method or returned by the poll() method
of this object. If filtering is performed by this Wire
object,
this methods returns the last value provided by the Producer service.
This value may be an Envelope[]
when the Producer service uses
scoping. If the return value is an Envelope object (or array), it must be
verified that the Consumer service has the proper WirePermission to see
it.
The last value passed though this Wire
object or
null
if no valid values have been passed or the Consumer
service has no permission.
Return the wire properties for this Wire
object.
The properties for this Wire
object. The returned
Dictionary
must be read only.
Return the calculated scope of this Wire
object.
The purpose of the Wire
object's scope is to allow a Producer
and/or Consumer service to produce/consume different types over a single
Wire
object (this was deemed necessary for efficiency reasons).
Both the Consumer service and the Producer service must set an array of
scope names (their scope) with the service registration property
WIREADMIN_PRODUCER_SCOPE
, or WIREADMIN_CONSUMER_SCOPE
when they can produce multiple types. If a Producer service can produce
different types, it should set this property to the array of scope names
it can produce, the Consumer service must set the array of scope names it
can consume. The scope of a Wire
object is defined as the
intersection of permitted scope names of the Producer service and
Consumer service.
If neither the Consumer, or the Producer service registers scope names
with its service registration, then the Wire
object's scope must
be null
.
The Wire
object's scope must not change when a Producer or
Consumer services modifies its scope.
A scope name is permitted for a Producer service when the registering
bundle has WirePermission[name,PRODUCE]
, and for a Consumer
service when the registering bundle has
WirePermission[name,CONSUME]
.
If either Consumer service or Producer service has not set a
WIREADMIN_*_SCOPE
property, then the returned value must be
null
.
If the scope is set, the Wire
object must enforce the scope names
when Envelope
objects are used as a parameter to update or
returned from the poll
method. The Wire
object must then
remove all Envelope
objects with a scope name that is not
permitted.
A list of permitted scope names or null if the Produce or Consumer service has set no scope names.
The scope name
Return true if the given name is in this Wire
object's scope.
true if the name is listed in the permitted scope names
Return the connection state of this Wire
object.
A Wire
is connected after the Wire Admin service receives
notification that the Producer service and the Consumer service for this
Wire
object are both registered. This method will return
true
prior to notifying the Producer and Consumer services via
calls to their respective consumersConnected
and
producersConnected
methods.
A WireAdminEvent
of type WireAdminEvent.WIRE_CONNECTED
must be broadcast by the Wire Admin service when the Wire
becomes
connected.
A Wire
object is disconnected when either the Consumer or
Producer service is unregistered or the Wire
object is deleted.
A WireAdminEvent
of type WireAdminEvent.WIRE_DISCONNECTED
must be broadcast by the Wire Admin service when the Wire
becomes
disconnected.
true
if both the Producer and Consumer for this
Wire
object are connected to the Wire
object;
false
otherwise.
Return the state of this Wire
object.
A connected Wire
must always be disconnected before becoming
invalid.
false
if this Wire
object is invalid because it
has been deleted via WireAdmin.deleteWire(Wire);
true
otherwise.
Poll for an updated value.
This methods is normally called by the Consumer service to request an
updated value from the Producer service connected to this Wire
object. This Wire
object will call the
Producer.polled(Wire) method to obtain an updated value. If this
Wire
object is not connected, then the Producer service must not
be called.
If this Wire
object has a scope, then this method must return an
array of Envelope
objects. The objects returned must match the
scope of this object. The Wire
object must remove all
Envelope
objects with a scope name that is not in the
Wire
object's scope. Thus, the list of objects returned must only
contain Envelope
objects with a permitted scope name. If the
array becomes empty, null
must be returned.
A WireAdminEvent
of type WireAdminEvent.WIRE_TRACE must
be broadcast by the Wire Admin service after the Producer service has
been successfully called.
A value whose type should be one of the types returned by
getFlavors(),Envelope[]
, or null
if the
Wire
object is not connected, the Producer service threw
an exception, or the Producer service returned a value which is
not an instance of one of the types returned by
getFlavors().
The updated value. The value should be an instance of one of the types returned by getFlavors().
Update the value.
This methods is called by the Producer service to notify the Consumer
service connected to this Wire
object of an updated value.
If the properties of this Wire
object contain a
WireConstants.WIREADMIN_FILTER property, then filtering is
performed. If the Producer service connected to this Wire
object
was registered with the service property
WireConstants.WIREADMIN_PRODUCER_FILTERS, the Producer service
will perform the filtering according to the rules specified for the
filter. Otherwise, this Wire
object will perform the filtering of
the value.
If no filtering is done, or the filter indicates the updated value should
be delivered to the Consumer service, then this Wire
object must
call the Consumer.updated(Wire, Object) method with the updated
value. If this Wire
object is not connected, then the Consumer
service must not be called and the value is ignored.
If the value is an Envelope
object, and the scope name is not
permitted, then the Wire
object must ignore this call and not
transfer the object to the Consumer service.
A WireAdminEvent
of type WireAdminEvent.WIRE_TRACE must
be broadcast by the Wire Admin service after the Consumer service has
been successfully called.
Wire Administration service.
This service can be used to create Wire
objects connecting a Producer
service and a Consumer service. Wire
objects also have wire
properties that may be specified when a Wire
object is created. The
Producer and Consumer services may use the Wire
object's properties
to manage or control their interaction. The use of Wire
object's
properties by a Producer or Consumer services is optional.
Security Considerations. A bundle must have
ServicePermission[WireAdmin,GET]
to get the Wire Admin service to
create, modify, find, and delete Wire
objects.
Consumers of this API must not implement this interface
The service.pid
of the Producer service to be
connected to the Wire
object.
The service.pid
of the Consumer service to be
connected to the Wire
object.
The Wire
object's properties. This argument may
be null
if the caller does not wish to define any
Wire
object's properties.
Create a new Wire
object that connects a Producer service to a
Consumer service.
The Producer service and Consumer service do not have to be registered
when the Wire
object is created.
The Wire
configuration data must be persistently stored. All
Wire
connections are reestablished when the WireAdmin
service is registered. A Wire
can be permanently removed by using
the deleteWire(Wire) method.
The Wire
object's properties must have case insensitive
String
objects as keys (like the Framework). However, the case of
the key must be preserved.
The WireAdmin
service must automatically add the following
Wire
properties:
-
WireConstants.WIREADMIN_PID set to the value of the
Wire
object's persistent identity (PID). This value is generated by the Wire Admin service when aWire
object is created. -
WireConstants.WIREADMIN_PRODUCER_PID set to the value of Producer service's PID.
-
WireConstants.WIREADMIN_CONSUMER_PID set to the value of Consumer service's PID.
If the properties
argument already contains any of these keys,
then the supplied values are replaced with the values assigned by the
Wire Admin service.
The Wire Admin service must broadcast a WireAdminEvent
of type
WireAdminEvent.WIRE_CREATED after the new Wire
object
becomes available from getWires(String).
The Wire
object for this connection.
IllegalArgumentException
– If properties
contains
invalid wire types or case variants of the same key name.
The Wire
object which is to be deleted.
Delete a Wire
object.
The Wire
object representing a connection between a Producer
service and a Consumer service must be removed. The persistently stored
configuration data for the Wire
object must destroyed. The
Wire
object's method Wire.isValid() will return
false
after it is deleted.
The Wire Admin service must broadcast a WireAdminEvent
of type
WireAdminEvent.WIRE_DELETED after the Wire
object becomes
invalid.
Filter string to select Wire
objects or
null
to select all Wire
objects.
Return the Wire
objects that match the given filter
.
The list of available Wire
objects is matched against the
specified filter
.Wire
objects which match the
filter
must be returned. These Wire
objects are not
necessarily connected. The Wire Admin service should not return invalid
Wire
objects, but it is possible that a Wire
object is
deleted after it was placed in the list.
The filter matches against the Wire
object's properties including
WireConstants.WIREADMIN_PRODUCER_PID,
WireConstants.WIREADMIN_CONSUMER_PID and
WireConstants.WIREADMIN_PID.
An array of Wire
objects which match the filter
or null
if no Wire
objects match the
filter
.
InvalidSyntaxException
– If the specified
filter
has an invalid syntax.
org.osgi.framework.Filter
The Wire
object which is to be updated.
The new Wire
object's properties or
null
if no properties are required.
Update the properties of a Wire
object.
The persistently stored configuration data for the Wire
object is
updated with the new properties and then the Consumer and Producer
services will be called at the respective
Consumer.producersConnected(Wire[]) and
Producer.consumersConnected(Wire[]) methods.
The Wire Admin service must broadcast a WireAdminEvent
of type
WireAdminEvent.WIRE_UPDATED after the updated properties are
available from the Wire
object.
IllegalArgumentException
– If properties
contains
invalid wire types or case variants of the same key name.
A Wire Admin Event.
WireAdminEvent
objects are delivered to all registered
WireAdminListener
service objects which specify an interest in the
WireAdminEvent
type. Events must be delivered in chronological order
with respect to each listener. For example, a WireAdminEvent
of type
WIRE_CONNECTED must be delivered before a WireAdminEvent
of
type WIRE_DISCONNECTED for a particular Wire
object.
A type code is used to identify the type of event. The following event types are defined:
Additional event types may be defined in the future.
Event type values must be unique and disjoint bit values. Event types must be defined as a bit in a 32 bit integer and can thus be bitwise ORed together.
Security Considerations. WireAdminEvent
objects contain Wire
objects. Care must be taken in the sharing of Wire
objects with other
bundles.
Immutable
A Consumer service method has thrown an exception.
This WireAdminEvent
type indicates that a Consumer service method
has thrown an exception. The WireAdminEvent.getThrowable() method
will return the exception that the Consumer service method raised.
The value of CONSUMER_EXCEPTION
is 0x00000002.
A Producer service method has thrown an exception.
This WireAdminEvent
type indicates that a Producer service method
has thrown an exception. The WireAdminEvent.getThrowable() method
will return the exception that the Producer service method raised.
The value of PRODUCER_EXCEPTION
is 0x00000001.
The WireAdminEvent
type that indicates that an existing
Wire
object has become connected.
The Consumer object and the Producer object that are associated with the
Wire
object have both been registered and the Wire
object
is connected. See Wire.isConnected() for a description of the
connected state. This event may come before the
producersConnected
and consumersConnected
method have
returned or called to allow synchronous delivery of the events. Both
methods can cause other WireAdminEvent
s to take place and
requiring this event to be send before these methods are returned would
mandate asynchronous delivery.
The value of WIRE_CONNECTED
is 0x00000020.
A Wire
has been created.
This WireAdminEvent
type that indicates that a new Wire
object has been created.
An event is broadcast when
WireAdmin.createWire(String, String, java.util.Dictionary) is
called. The WireAdminEvent.getWire() method will return the
Wire
object that has just been created.
The value of WIRE_CREATED
is 0x00000004.
A Wire
has been deleted.
This WireAdminEvent
type that indicates that an existing wire has
been deleted.
An event is broadcast when WireAdmin.deleteWire(Wire) is called
with a valid wire. WireAdminEvent.getWire() will return the
Wire
object that has just been deleted.
The value of WIRE_DELETED
is 0x00000010.
The WireAdminEvent
type that indicates that an existing
Wire
object has become disconnected.
The Consumer object or/and Producer object is/are unregistered breaking
the connection between the two. See Wire.isConnected for a
description of the connected state.
The value of WIRE_DISCONNECTED
is 0x00000040.
The WireAdminEvent
type that indicates that a new value is
transferred over the Wire
object.
This event is sent after the Consumer service has been notified by
calling the Consumer.updated(Wire, Object) method or the Consumer
service requested a new value with the Wire.poll() method. This
is an advisory event meaning that when this event is received, another
update may already have occurred and this the Wire.getLastValue()
method returns a newer value then the value that was communicated for
this event.
The value of WIRE_TRACE
is 0x00000080.
A Wire
has been updated.
This WireAdminEvent
type that indicates that an existing
Wire
object has been updated with new properties.
An event is broadcast when
WireAdmin.updateWire(Wire, java.util.Dictionary) is called with a
valid wire. The WireAdminEvent.getWire() method will return the
Wire
object that has just been updated.
The value of WIRE_UPDATED
is 0x00000008.
The ServiceReference
object of the Wire Admin
service that created this event.
The event type. See getType().
The Wire
object associated with this event.
An exception associated with this event. This may be
null
if no exception is associated with this event.
Constructs a WireAdminEvent
object from the given
ServiceReference
object, event type, Wire
object and
exception.
Return the ServiceReference
object of the Wire Admin service that
created this event.
The ServiceReference
object for the Wire Admin service
that created this event.
Returns the exception associated with the event, if any.
An exception or null
if no exception is associated with
this event.
Return the type of this event.
The type values are:
The type of this event.
Listener for Wire Admin Events.
WireAdminListener
objects are registered with the Framework service
registry and are notified with a WireAdminEvent
object when an event
is broadcast.
WireAdminListener
objects can inspect the received
WireAdminEvent
object to determine its type, the Wire
object
with which it is associated, and the Wire Admin service that broadcasts the
event.
WireAdminListener
objects must be registered with a service property
WireConstants.WIREADMIN_EVENTS whose value is a bitwise OR of all the
event types the listener is interested in receiving.
For example:
Integer mask = Integer.valueOf(WIRE_TRACE | WIRE_CONNECTED | WIRE_DISCONNECTED);
Hashtable ht = new Hashtable();
ht.put(WIREADMIN_EVENTS, mask);
context.registerService(WireAdminListener.class.getName(), this, ht);
If a WireAdminListener
object is registered without a service
property WireConstants.WIREADMIN_EVENTS, then the
WireAdminListener
will receive no events.
Security Considerations. Bundles wishing to monitor WireAdminEvent
objects will require ServicePermission[WireAdminListener,REGISTER]
to
register a WireAdminListener
service. Since WireAdminEvent
objects contain Wire
objects, care must be taken in assigning
permission to register a WireAdminListener
service.
The WireAdminEvent
object.
Receives notification of a broadcast WireAdminEvent
object.
The event object will be of an event type specified in this
WireAdminListener
service's
WireConstants.WIREADMIN_EVENTS service property.
Defines standard names for Wire
properties, wire filter attributes,
Consumer and Producer service properties.
Consumers of this API must not implement this interface
A service registration property for a Consumer service that is composite.
It contains the names of the composite Producer services it can cooperate
with. Interoperability exists when any name in this array matches any
name in the array set by the Producer service. The type of this property
must be String[]
.
Service Registration property (named wireadmin.consumer.flavors
)
specifying the list of data types understood by this Consumer service.
The Consumer service object must be registered with this service
property. The list must be in the order of preference with the first type
being the most preferred. The value of the property must be of type
Class[]
.
Wire
property key (named wireadmin.consumer.pid
)
specifying the service.pid
of the associated Consumer service.
This wire property is automatically set by the Wire Admin service. The
value of the property must be of type String
.
Service registration property key (named wireadmin.consumer.scope
) specifying a list of names that may be used to define the scope of this
Wire
object. A Consumer
service should set this service
property when it can produce more than one kind of value. This property
is only used during registration, modifying the property must not have
any effect of the Wire
object's scope. Each name in the given
list mist have WirePermission[name,CONSUME]
or else is ignored.
The type of this service registration property must be String[]
.
Service Registration property (named wireadmin.events
) specifying
the WireAdminEvent
type of interest to a Wire Admin Listener
service. The value of the property is a bitwise OR of all the
WireAdminEvent
types the Wire Admin Listener service wishes to
receive and must be of type Integer
.
Wire
property key (named wireadmin.filter
) specifying a
filter used to control the delivery rate of data between the Producer and
the Consumer service.
This property should contain a filter as described in the Filter
class. The filter can be used to specify when an updated value from the
Producer service should be delivered to the Consumer service. In many
cases the Consumer service does not need to receive the data with the
same rate that the Producer service can generate data. This property can
be used to control the delivery rate.
The filter can use a number of predefined attributes that can be used to control the delivery of new data values. If the filter produces a match upon the wire filter attributes, the Consumer service should be notified of the updated data value.
If the Producer service was registered with the
WIREADMIN_PRODUCER_FILTERS service property indicating that the
Producer service will perform the data filtering then the Wire
object will not perform data filtering. Otherwise, the Wire
object must perform basic filtering. Basic filtering includes supporting
the following standard wire filter attributes:
-
WIREVALUE_CURRENT - Current value
-
WIREVALUE_PREVIOUS - Previous value
-
WIREVALUE_DELTA_ABSOLUTE - Absolute delta
-
WIREVALUE_DELTA_RELATIVE - Relative delta
-
WIREVALUE_ELAPSED - Elapsed time
org.osgi.framework.Filter
Wire
property key (named wireadmin.pid
) specifying the
persistent identity (PID) of this Wire
object.
Each Wire
object has a PID to allow unique and persistent
identification of a specific Wire
object. The PID must be
generated by the WireAdmin service when the Wire
object
is created.
This wire property is automatically set by the Wire Admin service. The
value of the property must be of type String
.
A service registration property for a Producer service that is composite.
It contains the names of the composite Consumer services it can
interoperate with. Interoperability exists when any name in this array
matches any name in the array set by the Consumer service. The type of
this property must be String[]
.
Service Registration property (named wireadmin.producer.filters
).
A Producer
service registered with this property indicates to the
Wire Admin service that the Producer service implements at least the
filtering as described for the WIREADMIN_FILTER property. If the
Producer service is not registered with this property, the Wire
object must perform the basic filtering as described in
WIREADMIN_FILTER.
The type of the property value is not relevant. Only its presence is relevant.
Service Registration property (named wireadmin.producer.flavors
)
specifying the list of data types available from this Producer service.
The Producer service object should be registered with this service property.
The value of the property must be of type Class[]
.
Wire
property key (named wireadmin.producer.pid
)
specifying the service.pid
of the associated Producer service.
This wire property is automatically set by the WireAdmin service. The
value of the property must be of type String
.
Service registration property key (named wireadmin.producer.scope
) specifying a list of names that may be used to define the scope of this
Wire
object. A Producer service should set this service property
when it can produce more than one kind of value. This property is only
used during registration, modifying the property must not have any effect
of the Wire
object's scope. Each name in the given list mist have
WirePermission[name,PRODUCE]
or else is ignored. The type of this
service registration property must be String[]
.
Wire
object's filter attribute (named wirevalue.current
)
representing the current value.
Wire
object's filter attribute (named
wirevalue.delta.absolute
) representing the absolute delta. The
absolute (always positive) difference between the last update and the
current value (only when numeric). This attribute must not be used when
the values are not numeric.
Wire
object's filter attribute (named
wirevalue.delta.relative
) representing the relative delta. The
relative difference is |previous
-current
|/|
current
| (only when numeric). This attribute must not be used
when the values are not numeric.
Wire
object's filter attribute (named wirevalue.elapsed
)
representing the elapsed time, in ms, between this filter evaluation and
the last update of the Consumer
service.
Permission for the scope of a Wire
object. When a Envelope
object is used for communication with the poll
or update
method, and the scope is set, then the Wire
object must verify that
the Consumer service has WirePermission[name,CONSUME]
and the
Producer service has WirePermission[name,PRODUCE]
for all names in
the scope.
The names are compared with the normal rules for permission names. This means
that they may end with a "*" to indicate wildcards. E.g. Door.* indicates all
scope names starting with the string "Door". The last period is required due
to the implementations of the BasicPermission
class.
Thread-safe
The action string for the consume
action.
The action string for the produce
action.
Wire name.
produce
, consume
(canonical order).
Create a new WirePermission with the given name (may be wildcard) and actions.
The object to test for equality.
Determines the equality of two WirePermission
objects.
Checks that specified object has the same name and actions as this
WirePermission
object.
true if obj
is a WirePermission
, and has the same
name and actions as this WirePermission
object;
false
otherwise.
Returns the canonical string representation of the actions. Always
returns present actions in the following order: produce
,
consume
.
The canonical string representation of the actions.
Returns the hash code value for this object.
Hash code value for this object.
The permission to check against.
Checks if this WirePermission
object implies
the
specified permission.
More specifically, this method returns true
if:
-
p is an instanceof the
WirePermission
class, -
p's actions are a proper subset of this object's actions, and
-
p's name is implied by this object's name. For example,
java.*
impliesjava.home
.
true
if the specified permission is implied by this
object; false
otherwise.
Returns a new PermissionCollection
object for storing
WirePermission
objects.
A new PermissionCollection
object suitable for storing
WirePermission
objects.