Amigo ANS tutorial - v2.0 - Gforge

advertisement
IST Amigo Project
Amigo Training Document:
ANS
Version 2.0
IST-2004-004182
Public
June 2007
Confidential
Project Number
:
IST-004182
Project Title
:
Amigo
Deliverable Type
:
Tutorial
Deliverable Number
:
Title of Deliverable
:
Amigo Training Document: ANS
Nature of Deliverable
:
Public
Internal Document Number
:
Contractual Delivery Date
:
Actual Delivery Date
:
Contributing WPs
:
Author(s)
:
Todor Dimitrov, Edwin Naroska, Jörg Schmalenstroer,
Volker Leutnant
Abstract
This document is a tutorial about using the Awareness and Notification System (ANS) of Amigo. ANS is
part of the intelligent user services and provides an easy way to get access to changes in the context of
the home environment. ANS provides functionality to allow people/applications to stay aware of context
changes. This tutorial briefly introduces how to use ANS, i.e. how to write and ANS client.
Keyword list
Awareness and Notification System, ANS, ANS client, context
Amigo IST-2004-004182
1/22
June 2007
Confidential
Table of Contents
Table of Contents................................................................................................... 2
1
2
Introduction ..................................................................................................... 3
1.1
Prerequisites..............................................................................................................................3
1.2
How to use this document ........................................................................................................3
System and software requirements ............................................................... 5
2.1
Installing and configuring Oscar ............................................................................................5
2.1.1
Installation ..........................................................................................................................5
2.1.2
GUI.....................................................................................................................................5
2.1.3
Installing bundles ...............................................................................................................6
2.1.4
Repositories ........................................................................................................................7
2.1.5
Stopping Oscar ...................................................................................................................7
3
Using the Awareness and Notification System ............................................. 8
3.1
Writing an ANS client ...........................................................................................................8
3.1.1
Looking up the ANS service ..............................................................................................8
3.1.2
The main component ........................................................................................................10
3.1.3
Service activator ...............................................................................................................14
3.1.4
Client notification.............................................................................................................14
3.1.5
Providing rules to ANS ....................................................................................................15
3.1.6
Service bundle metadata...................................................................................................16
3.1.7
Client bundle manifest......................................................................................................16
3.2
4
Writing a context source for testing...............................................................................17
Recommended next steps.............................................................................. 22
Amigo IST-2004-004182
2/22
June 2007
Confidential
1 Introduction
This document is a tutorial about using the Awareness and Notification System (ANS) of
Amigo. ANS is part of the intelligent user services and provides an easy way to get access to
changes in the context of the home environment. ANS provides functionality to allow
people/applications to stay aware of context changes. For example, it can inform applications
about changes of the current location of a specific user. As a result, the application does not
have to query all the various context sources that may provide appropriate location
information. Instead, it subscribes to ANS and inject an appropriate rule that is automatically
checked by ANS each time context information changes
This tutorial briefly introduces how to use ANS, i.e. how to write and ANS client.
1.1 Prerequisites
Amigo training blocks typically requires some Amigo related as well as non Amigo related
skills or knowledge. These are given in the following:
Non Amigo related prerequisites:
o
The reader should be familiar with either Java or C# to easily follow the
explanations.
o
The reader should be familiar with an integrated development environment
(IDE) for the programming language that shall be used. It is suggested to use
either Eclipse 3.2 (or higher) for Java or Visual Studio 2005 for C#.
Amigo related prerequisites:
o
The reader should be familiar with the Amigo Deployment Framework. To learn
about this framework the Using Web Services can be used. The Tutorial can be
downloaded from https://gforge.inria.fr/frs/?group_id=160.
o
The reader should also be familiar with using and developing Context Sources.
Please
read
with
the
CMS
Tutorial
available
from
https://gforge.inria.fr/frs/?group_id=160.
For some general information on the Amigo project please refer to the Amigo project web site
at http://www.hitech-projects.com/euprojects/amigo/index.htm.
1.2 How to use this document
This document aims at providing the reader with valuable information about how to use the
Amigo middleware. To this end it gives a step by step introduction where explanations are
accompanied with short programming assignments. Please proceed to the document section
by section and step by step and try to do the assignments. In order to save some typing, an
appropriate set of template files is given that can be used to fulfill the assignments. These
template files already include a programming frame that must be extend by you in order to
complete the assignment. For information on how where to obtain these template files please
refer to Chapter 0.
The example below shows how a piece of source code is printed. Note that code blocks are
embedded in a box in order to easily separate them from normal text:
using (Service service = new AddService(securedService)) {
WebServer.AddWebService(serviceLocation, service);
Console.WriteLine("Sample service 2 running." +
Environment.NewLine +
"Press <return> to quit");
Amigo IST-2004-004182
3/22
June 2007
Confidential
Console.ReadLine();
}
If code is printed in normal text, it is shown in italic.
Amigo IST-2004-004182
4/22
June 2007
Confidential
2 System and software requirements
For the Java parts of the tutorial you need an installed version of the Java Development Kit,
including the javac compiler and the jar tools (Java Version 1.5.x).
If your are using Java, then the following additional software is needed:
Java Software Development Kit. This is a general package needed for Java software
development. The package is available from http://java.sun.com.
Oscar. Oscar is a open source OSGi framework. This software is also available from
http://amigo.gforge.inria.fr/obr/tools/.
Please note that it may be required to de-activated the firewall on the computer that shall run
the test server.
A set of template files have been prepared in order to help you running the practical parts of
this tutorial. It is recommended that you use this templates. A package that includes this
template
along
with
some
other
files
an
be
downloaded
from
https://gforge.inria.fr/frs/?group_id=160.
2.1 Installing and configuring Oscar
Oscar is an open source implementation of the Open Services Gateway Initiative (OSGi)
framework specification, which is used by many Amigo services. The main components of the
CMS system are based on Oscar bundles, which are available through the Online Bundle
Repository (OBR) of Amigo.
2.1.1 Installation
Oscar does not have a special installation routine, so the full software package is available as
a zip-file (e.g. http://amigo.gforge.inria.fr/obr/tools/oscar_j2se.zip) and has to be extracted
to a directory of your choice. If you are connected to the Internet through a proxy server, you’ll
have to add the appropriate proxy settings to the “system.properties” file located in the “lib”
sub-directory. You’ll find the start scripts “oscar.bat” (Windows) and “oscar.sh” (Linux1) in the
main directory. After calling the start script you are asked for a profile name (enter
CMSTutorial, for example), which defines the name of the current Oscar profile. You can use
profile names for separating different configurations.
2.1.2 GUI
Below you see a screenshot of a running version of Oscar. On the left side you find the three
items:
Bundle List: A list of all installed bundles, showing Id , State and Location;
additionally, local URLs can be entered for installing bundles
(e.g.:
file:///home/user/amigo_bundle.jar)
Shell: Command shell
OBR: A list of all bundles available from the repositories, this can be online or
offline repositories as defined in /lib/bundle.properties.
1
If “oscar.sh” is not executable use “chmod u+x oscar.sh” to change the file attribute.
Amigo IST-2004-004182
5/22
June 2007
Confidential
Use the OBR item to install bundles from the repository and the Bundle List item for starting
and stopping installed bundles.
2.1.3 Installing bundles
Now start installing bundles to the Oscar platform:
1. Click on the item “OBR”
2. Select “amigo_core” and press “Start All”
Installed dependencies:
log4j
Service Binder
3. Select “amigo_ksoap_binding” and press “Start All”
4. Select “amigo_ksoap_export” and press “Start All”
Installed dependencies:
Servlet
HTTP Service (+ Amigo mods)
5. Select “amigo_wsdiscovery” and press “Start All”
6. Using the same procedure as describes above start the following bundles:
“context_broker”, “context_source_manger” and “context_helper”
All bundles that start with “ANS_...”
Now click on the “Bundle list” to check if all bundles are installed. You should get the following
list:
Amigo IST-2004-004182
6/22
June 2007
Confidential
If during the bundle installation the above listed dependencies are not installed (an error will
occur and pop up), please install the dependencies prior to the bundles by hand.
In the “OBR” list you also find several other software bundles, which you can use for your
services. Now we should start with compiling bundles and installing them.
2.1.4 Repositories
The URL of the repositories is defined in “lib/bundle.properties”. The standard Amigo
repositories are defined by the following copy of the “bundle.properties” file. You also find the
address of the actual repositories on the item OBR.
# all known repositories
oscar.repository.url=\
http://amigo.gforge.inria.fr/obr/tools/oscar-repository.xml \
http://amigo.gforge.inria.fr/obr/v2/repository.xml
# the port on which the http server will listen
# if you have several OSGi platforms on the same machines change the port number
org.osgi.service.http.port=8080
2.1.5 Stopping Oscar
You can stop Oscar by typing “shutdown” in the Oscar shell. If nothing happens you can press
“Ctrl+c” for killing Oscar, but try to shutdown Oscar gently through the “shutdown”-command
beforehand.
Amigo IST-2004-004182
7/22
June 2007
Confidential
3 Using the Awareness and Notification System
ANS is part of the intelligent user services and provides an easy way to get access to changes
in the context of the home environment. ANS provides functionality to allow
people/applications to stay aware of context changes. For example, it can inform applications
about changes of the current location of a specific user. As a result, the application does not
have to query all the various context sources that may provide appropriate location
information. Instead, it subscribes to ANS and inject an appropriate rule that is automatically
checked by ANS each time context information changes. Whenever the rule matches, an
appropriate notification is send to the appropriate client.
ANS has implemented in Java. However, it communicates with clients using SOAP which
makes the client part independent of the actual server implementation. Communication
between ANS and clients that make use of it happens in two directions: Client application
searches for ANS and uses its interface to manage rules (subscribe, start, update etc.).
Further, when a rule evaluates to true, ANS calls the client and uses its interface to notify it.
3.1 Writing an ANS client
In the following, it is shown how to write an ANS client. The template files are located in
“Code\Java\tutorial_ansclient\src\de\ims\fraunhofer\amigo\tutorial\ans_client”. The complete
solutions can be found in the subdirectories starting with “Code_Solution”.
3.1.1 Looking up the ANS service
First, we write a class named ANSWrapper that discovers the Amigo ANS service and
encapsulates it. It provides the functionality of the IManageRules interface to an application
that wants to use ANS. The unique instance of this class is provided by the getInstance.
method. After retrieving an ANSWrapper object in this way, simply invoke the connect method
and the wrapper will search automatically for available ANS services. Note that the class
provides the same methods of the IManageRule interface. Hence, invocations are simply
delegated to ANS.
First, import the packages that are needed by the wrapper. Further, define some members that
are internally used by the wrapper:
package de.ims.fraunhofer.amigo.tutorial.ans_client;
import java.rmi.RemoteException;
import amigo.ans.api.IManageRule;
import amigo.ans.api.Rule;
import amigo.ans.api.RuleFormatException;
import com.francetelecom.amigo.core.AmigoException;
import com.francetelecom.amigo.core.AmigoLdapLookup;
import com.francetelecom.amigo.core.AmigoService;
public class ANSWrapper {
/** ANS web service object */
private IManageRule ans = null;
/** service objects */
private AmigoService[] services;
/** lookup service */
private AmigoLdapLookup lookup = null;
...
Amigo IST-2004-004182
8/22
June 2007
Confidential
ANSWrapper is build according to the singleton pattern:
/** singleton */
private static ANSWrapper instance = null;
/**
* Return the ANSWrapper instance
* @return The unique instance
*/
public static ANSWrapper getInstance() {
if (instance == null) {
instance = new ANSWrapper();
}
return instance;
}
/** private constructor to match singleton pattern */
private ANSWrapper() {}
...
The connect method now looks up the Amigo ANS service on the network. To this end a
service with service type “Amigo_ANS” is searched. Moreover, the service URL must contain
the string “IManageRule” in order to use it. Here, we just use the first service that matches this
specific pattern. In case of an success, true is returned. Otherwise, if no appropriate ANS
service could be found the return value is false:
/**
* Searches for the ANS via service discovery and connects to it if a
* service object is found.
*/
public boolean connect() {
try {
//reset connection...
ans = null;
services = lookup.lookup("(ServiceType=Amigo_ANS)");
//no service discoveres --> no connection
if (services.length == 0) {
return false;
} else {
// we use the first service with "IManageRule"
// in its name that is found
for (int i = 0; i < services.length; i++) {
if (services[i].getReference().
getUrl().toLowerCase()
.contains("imanagerule")) {
ans = (IManageRule) services[i]
.getSpecificStub(
IManageRule.class);
return true;
}
}
}
} catch (AmigoException ex) {
ex.printStackTrace();
}
Amigo IST-2004-004182
9/22
June 2007
Confidential
//something has gone wrong or no ANS found --> return false
return false;
}
...
The remainder of the class is dedicated to forwarding various method calls to the actual ANS
service that has been found:
/**
* Return whether or not the application is connected to ANS.
*
* @return true if application is connected
*/
public boolean isConnected() {
return (ans != null);
}
public int subscribe(Rule rule, String appID) throws
RuleFormatException, RemoteException {
return ans.subscribe(rule, appID);
}
public boolean unsubscribe(int ruleID) throws RemoteException {
return ans.unsubscribe(ruleID);
}
public boolean updateRule(int ruleID, Rule rule) throws
RemoteException {
return ans.updateRule(ruleID, rule);
}
public Rule queryRule(int ruleID) throws RemoteException {
return ans.queryRule(ruleID);
}
public boolean startRule(int ruleID) throws RemoteException {
return ans.startRule(ruleID);
}
public boolean stopRule(int ruleID) throws RemoteException {
return ans.stopRule(ruleID);
}
public void bindLookupService(AmigoLdapLookup lookup) {
this.lookup = lookup;
}
public void unbindLookupService(AmigoLdapLookup lookup) {
if (this.lookup == lookup) {
this.lookup = null;
}
}
}
3.1.2 The main component
The code below shows the main component of the client application. Note that this class
implements the Lifeycle interface in order to provide the appropriate functionality to work as a
Web service within OSGi. Note further, that the client works as an Web Service within OSGi.
Amigo IST-2004-004182
10/22
June 2007
Confidential
package de.ims.fraunhofer.amigo.tutorial.ans_client;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.rmi.RemoteException;
import org.apache.log4j.Logger;
import org.ungoverned.gravity.servicebinder.Lifecycle;
import amigo.ans.api.INotifyApplication;
import amigo.ans.api.Rule;
import
import
import
import
import
com.francetelecom.amigo.core.AmigoException;
com.francetelecom.amigo.core.AmigoExportedService;
com.francetelecom.amigo.core.AmigoLdapLookup;
com.francetelecom.amigo.core.AmigoReference;
com.francetelecom.amigo.core.AmigoServiceExporter;
/**
* Exports the ANS Client as a webservice for Oscar.
*/
public class MainComponent implements Lifecycle {
private
private
private
private
Logger logger = Logger.getRootLogger();
AmigoServiceExporter serviceExporter;
AmigoExportedService ansclient_not;
AmigoLdapLookup lookup;
/** The id of the subscribed rule */
private int m_ruleId;
/**
* Called by the service binder when a service exporter is available.
*
* @param serviceExporter
*
The service exporter that was just registered
*/
public void bindServiceExporter(AmigoServiceExporter serviceExporter)
{
this.serviceExporter = serviceExporter;
}
/**
* Called by the service binder when a service exporter is no more
* available.
*
* @param serviceExporter
*
The service exporter that was just unregistered
*/
public void unbindServiceExporter(
AmigoServiceExporter serviceExporter) {
if (this.serviceExporter == serviceExporter) {
this.serviceExporter = null;
}
}
…
The activate method is called by OSGi when the component is activated. Within the method
the service object is created. This object will finally receive the notifications issued by ANS.
Amigo IST-2004-004182
11/22
June 2007
Confidential
Hence, we need to make a Web service from it. Please mind to provide an unique identifier for
the client in order to distinguish it from other clients.
/**
* Called when the component is ativated. Creates an ANS client
* and exports it as a webservice.
*/
public void activate() {
logger.info("\n> ANS client :: activated\n");
// create a service object out of our own application,
// change this line to use your own
ClientNotify service = new ClientNotify();
ansclient_not = serviceExporter.createService(service);
try {
// add service id for discovery and export interface
// as web service
ansclient_not.addProperty("oid", "Client_notify");
ansclient_not.exportInterface(AmigoReference.DEFAULT,
INotifyApplication.class);
logger.info("> exported service with reference "
+ ansclient_not.getReference());
} catch (AmigoException e) {
e.printStackTrace();
}
// publish the services for discovery
ansclient_not.addProperty("ServiceType", "ANS_Client");
// register service at lookup for wsdiscovery
try {
lookup.registerService(ansclient_not);
} catch (AmigoException e) {
e.printStackTrace();
}
...
Now that the client has been registered as an Web Service, contact the ANS wrapper and load
the rule into the wrapper. Note that the wrapper will forward these requests to the actual ANS
service running on the network. The major objective of the next code sequence is to load the
rule (note that loadRule is a method of the current class) and subscribe with ANS. ANS will
reply with an rule ID that can be used to identify the rule.
if (ANSWrapper.getInstance().connect()) {
logger.info("Successfully connected to ANS!");
final Rule rule;
try {
rule = loadRule();
} catch (Exception ex) {
logger.error("Unable to load test rule!", ex);
throw new RuntimeException(ex);
}
try {
m_ruleId = ANSWrapper.getInstance().subscribe(rule,
"ANS_Client");
ANSWrapper.getInstance().startRule(m_ruleId);
} catch (Exception ex) {
logger.error("Unable to subscribe rule", ex);
throw new RuntimeException(ex);
Amigo IST-2004-004182
12/22
June 2007
Confidential
}
logger.info("Successfully subscribed rule with id: " +
m_ruleId);
} else {
logger.error("Unable to connect to ANS!");
}
}
…
Next, define the method that is used to load the rule. Here, read out a file and convert the
stream into a string buffer. The buffer can then be used to create a instance of class Rule from
it:
/**
* Loads the test rule
*
* @return the non-null loaded rule
* @throws Exception
*
if an error occurs
*/
private Rule loadRule() throws Exception {
final InputStream ruleStream = getClass().getResourceAsStream(
"ReviewRules_Peter1.xml");
final StringBuffer buf = new StringBuffer();
String line = null;
final BufferedReader reader = new BufferedReader(
new InputStreamReader(ruleStream));
while ((line = reader.readLine()) != null) {
buf.append(line).append("\n");
}
return new Rule(buf.toString());
}
The deactivate method is called by OSGi when the component is deactivated. Within this
method the client Web service is unregistered and shut down.
/**
* Called when the component is deactivated. Unregisters the
* service from the lookup.
*/
public void deactivate() {
if (ANSWrapper.getInstance().isConnected()) {
try {
if (ANSWrapper.getInstance().unsubscribe(m_ruleId))
{
logger.info("Successfully unsubscribed" +
" rule with id: " + m_ruleId);
} else {
logger.error("Unable to unsubscribe rule" +
" with id: " + m_ruleId);
}
} catch (RemoteException ex) {
logger.error("Error while trying to unsibscribe" +
" rule with id: " + m_ruleId, ex);
}
}
if (ansclient_not != null) {
try {
lookup.unregisterService(ansclient_not);
} catch (AmigoException e) {
e.printStackTrace();
Amigo IST-2004-004182
13/22
June 2007
Confidential
}
}
logger.info("\n> ANS client :: stopped\n");
}
…
Finally, code is needed to react on the availability of an lookup service.
/**
* Binds the lookup service
*
* @param lookup
*
The lookup service that was just registered
*/
public void bindLookupService(AmigoLdapLookup lookup) {
this.lookup = lookup;
ANSWrapper.getInstance().bindLookupService(lookup);
}
/**
* Unbinds the lookup service
*
* @param lookup
*
The lookup service that was just unregistered
*/
public void unbindLookupService(AmigoLdapLookup lookup) {
if (this.lookup == lookup) {
this.lookup = null;
ANSWrapper.getInstance().unbindLookupService(lookup);
}
}
}
3.1.3 Service activator
To start a service as an OSGi bundle an activator class is needed. This class will be used by
OSGi
to
start
the
service.
Here
it
is
located
in
Tutorials\Web
Services\Code\Java\tutorial_server\src\de\ims\fraunhofer\amigo\tutorial\server\AmigoCoreActi
vator.java.
package de.ims.fraunhofer.amigo.tutorial.ans_client;
import org.ungoverned.gravity.servicebinder.GenericActivator;
/**
* @see GenericActivator
*
* @author Todor Dimitrov (todor.dimitrov@ims.fraunhofer.de)
* @version 08.10.2007 22:32:10
*/
public class Activator extends GenericActivator {
}
3.1.4 Client notification
Notification by ANS is done by calling an corresponding method of a class that implement the
INotifyApplication interface. In this example, the ANS Client just shows sends a simple
message to the log screen in case of an event is received. If you are developing an own
application, you can either extend this class or replace it with an own component. If you do
this, you have to implement the amigo.ans.api.INotifyApplication interface and create a service
out of your own component in MainComponent.java. Note that notify takes three arguments: a
Amigo IST-2004-004182
14/22
June 2007
Confidential
string message that contains the description of the event, a user ID and an intensity level
(which is a number between 0 (lowest intensity) and 10):
package de.ims.fraunhofer.amigo.tutorial.ans_client;
import org.apache.log4j.Logger;
import amigo.ans.api.INotifyApplication;
public class ClientNotify implements INotifyApplication {
private final Logger m_logger = Logger.getLogger(ClientNotify.class);
/**
* @see INotifyApplication#notify(String, String, int)
*/
public void notify(String message, String userID, int intensity) {
switch (intensity) {
case 10:
case 9:
case 8:
showAlertNotification(userID, message);
break;
case 7:
case 6:
case 5:
case 4:
showMediumNotification(userID, message);
break;
case 3:
case 2:
case 1:
showLowNotification(userID, message);
break;
case 0:
}
}
private void showMediumNotification(String userID, String message) {
m_logger.info("Medium notification :: Message to " + userID +
": \n " + message);
}
private void showLowNotification(String userID, String message) {
m_logger.info("Low notification :: Message to " + userID +
": \n " + message);
}
private void showAlertNotification(String userID, String message) {
m_logger.info("Alert notification :: Message to " + userID +
": \n " + message);
}
}
3.1.5 Providing rules to ANS
In order to operate properly, ANS need rules that need to be checked. In the example, the
rules is read out from a file. The rule defined blow will fire an event whenever user John enters
the kitchen. In detail, ANS will then send the message “John has entered the kitchen”:
Amigo IST-2004-004182
15/22
June 2007
Confidential
<?xml version="1.0" encoding="UTF-8"?>
<ECARule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ECAXML.xsd">
<upon>
<event name="isLocatedIn" state_transition="EnterTrue">
<param>
<literal value="User.John"/>
</param>
<param>
<literal value="Kitchen"/>
</param>
</event>
</upon>
<do>
<notification name="Notify">
<param>
<literal value="ANS_Client"/>
</param>
<param>
<literal value="John has entered the kitchen."/>
</param>
</notification>
</do>
<lifetime value="testing"/>
</ECARule>
For the rule syntax please read with the ANS documentation.
3.1.6 Service bundle metadata
In order to run this software as an OSGi bundle, some information is needed that describes
some dependencies of the software:
<?xml version="1.0" encoding="UTF-8" ?>
<bundle>
<component
class="de.ims.fraunhofer.amigo.tutorial.ans.tests.ExampleContextSource">
<requires
service="nl.telin.amigo.contextmanagement.csmw.ContextSourceManager"
filter="" cardinality="1..n" policy="dynamic" bind
method="bindContextSourceManager" unbindmethod="unbindContextSourceManager" />
</component>
<component
class="de.ims.fraunhofer.amigo.tutorial.ans_client.MainComponent">
<requires service="com.francetelecom.amigo.core.AmigoServiceExporter"
filter="" cardinality="1..n" policy="dynamic"
bind-method="bindServiceExporter"
unbind-method="unbindServiceExporter" />
<requires service="com.francetelecom.amigo.core.AmigoLdapLookup"
filter="" cardinality="1..1" policy="dynamic"
bind-method="bindLookupService"
unbind-method="unbindLookupService" />
</component>
</bundle>
3.1.7 Client bundle manifest
Each OSGi bundle requires a “manifest”. This a plain text file that stores some general
information about the bundle. For example, it also includes the name of the metadata file:
Amigo IST-2004-004182
16/22
June 2007
Confidential
Manifest-Version: 1.0
Bundle-Description: Bundle demonstrates the use of the ANS IUS
Bundle-Name: Tutorial-ANS-Client
Bundle-Activator: de.ims.fraunhofer.amigo.tutorial.ans_client.Activator
Bundle-Vendor: Fraunhofer IMS
Import-Package: com.francetelecom.amigo.core,
org.ungoverned.gravity.servicebinder,
org.apache.log4j,
amigo.ans.api,
nl.telin.amigo.contextmanagement.csmw,
com.hp.hpl.jena.ontology,
com.hp.hpl.jena.rdf.model,
com.hp.hpl.jena.vocabulary,
com.hp.hpl.jena.graph,
com.hp.hpl.jena.query,
org.amigo.context
Bundle-Version: 1.0.0
Bundle-Copyright: Less General Public License
Bundle-ClassPath: .
Metadata-location: metadata.xml
This manifest (named manifest.mf) is stored in the same directory as the metadata file.
3.2 Writing a context source for testing
In order to test the application, an appropriate context source is needed. The source code for
the
context
source
is
in
“Code\Java\tutorial_ansclient\src\de\ims\fraunhofer\amigo\tutorial\ans\tests”:
package de.ims.fraunhofer.amigo.tutorial.ans.tests;
import
import
import
import
java.text.SimpleDateFormat;
java.util.Calendar;
java.util.Enumeration;
java.util.Hashtable;
import nl.telin.amigo.contextmanagement.csmw.ContextSourceFront;
import nl.telin.amigo.contextmanagement.csmw.ContextSourceManager;
import
import
import
import
org.amigo.context.AmigoICCS;
org.amigo.context.ContextTransport;
org.apache.log4j.Logger;
org.ungoverned.gravity.servicebinder.Lifecycle;
import com.hp.hpl.jena.ontology.Individual;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.shared.LockMRSW;
/**
* A context source that provides information about the user location
*
*/
public class ExampleContextSource implements Lifecycle {
private Logger logger = Logger.getLogger(this.getClass().getName());
private ContextSourceManager manager = null;
private ContextSourceFront csf = null;
/** The GUI client for setting the position of the user */
private ManualLocationUI mlu = null;
Amigo IST-2004-004182
17/22
June 2007
Confidential
/** The current model of the source */
private OntModel model = null;
/** The RDF capabilities of the context source provided during
registration */
private String rdfCaps = ""
+ "<?xml version=\"1.0\"?>"
+ "<rdf:RDF"
+ "
xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\""
+ "
xmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\""
+ "
xmlns:owl=\"http://www.w3.org/2002/07/owl#\""
+ "
xmlns:j.0=\"http://amigo.gforge.inria.fr/owl/AmigoICCS.owl#\""
+ "
xmlns:daml=\"http://www.daml.org/2001/03/daml+oil#\""
+ "
xmlns:j.1=\"http://amigo.gforge.inria.fr/owl/ContextTransport.owl#\">"
+ " <j.1:ContextSourceRegistration>"
+ "
<j.1:accuracy>5</j.1:accuracy>"
+ "
<j.1:timeliness>current</j.1:timeliness>"
+ "
<j.1:contextType>UserLocation</j.1:contextType>"
+ " </j.1:ContextSourceRegistration>" + "</rdf:RDF>";
public void bindContextSourceManager(ContextSourceManager manager) {
logger.debug("bindContextSourceManager()");
this.manager = manager;
}
public void unbindContextSourceManager(ContextSourceManager manager) {
logger.debug("unbindContextSourceManager()");
if (this.manager == manager) {
this.manager = null;
}
}
public void activate() {
logger.debug("activate");
csf = manager.registerContextSource(rdfCaps);
logger.debug("My CS at URL: " +
csf.getAmigoReference().getUrl());
model = csf.getOntModel();
mlu = new ManualLocationUI(this);
}
public void deactivate() {
logger.debug("deactivate");
if (mlu != null) {
mlu.deactivate();
mlu = null;
}
if (csf != null) {
csf.deregisterContextSource();
}
}
/**
* Called by the GUI to indicate that new model parameters are
* available
*/
void contextChanged(Hashtable<String, String> ht) {
Enumeration<String> en = ht.keys();
// Build a new model based on this context
Amigo IST-2004-004182
18/22
June 2007
Confidential
//
//
//
//
We will exchange the model in one go after building,
since the model can be accessed by different threads
Note that we re-use the model by emptying it just before
rebuilding.
model.enterCriticalSection(LockMRSW.WRITE);
model.removeAll();
while (en.hasMoreElements()) {
String newPerson = (String) en.nextElement();
/**
* Create the user whose location is specified and add it
* as an object property
*/
Individual newUser =
model.createIndividual(AmigoICCS.User);
/**
* We shouldn't use identifier for this but another
* property, but it will have to do for the moment...
*/
newUser.addProperty(
ContextTransport.identifier, newPerson);
/**
* Create the location where the user is, and add it as
* an object property
*/
Individual newRoom =
model.createIndividual(AmigoICCS.Room);
newRoom.addProperty(ContextTransport.identifier,
(String) ht.get(newPerson));
Individual newUserLocation = model
.createIndividual(ContextTransport.UserLocation);
newUserLocation.addProperty(ContextTransport.probability,
"0.9");
newUserLocation.addProperty(ContextTransport.isLocationOf,
newUser);
newUserLocation.addProperty(ContextTransport.isLocatedIn,
newRoom);
// Add the timestamp
Calendar now = Calendar.getInstance();
SimpleDateFormat df = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss.SSSZ");
newUserLocation.addProperty(ContextTransport.timestamp, df
.format(now.getTime()));
}
model.leaveCriticalSection();
System.out.println("---------------------------------------");
System.out.println("Current model:");
model.write(System.out, "RDF/XML-ABBREV");
System.out.println("---------------------------------------");
System.out.println();
/**
* (Re)setting the model will trigger processing of
* subscriptions
*/
Amigo IST-2004-004182
19/22
June 2007
Confidential
csf.setModel(model);
}
}
The code to implement a simple GUI for the context source, which allows to manually control
the location a user is currently in is:
package de.ims.fraunhofer.amigo.tutorial.ans.tests;
import
import
import
import
import
import
java.awt.Component;
java.awt.Frame;
java.awt.GridLayout;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
java.util.Hashtable;
import
import
import
import
import
javax.swing.BorderFactory;
javax.swing.JButton;
javax.swing.JLabel;
javax.swing.JPanel;
javax.swing.JTextField;
/**
* GUI for setting the location of the user
*
*/
class ManualLocationUI {
/** The frame to be displayed */
private Frame frame = null;
/** The context source to be notified when location of the
* user changes */
private ExampleContextSource m_parent = null;
public ManualLocationUI(ExampleContextSource parent) {
m_parent = parent;
// Create the top-level container and add contents to it.
frame = new Frame("User Location");
Component contents = this.createComponents();
// frame.getContentPane().add(contents, BorderLayout.CENTER);
frame.add(contents);
// Finish setting up the frame, and show it.
frame.pack();
frame.setVisible(true);
}
public void deactivate() {
if (frame != null) {
frame.dispose();
frame = null;
}
}
private Component createComponents() {
final JLabel labelPerson = new JLabel("Person:");
final JLabel labelRoom = new JLabel("Room:");
final JTextField person = new JTextField("John");
Amigo IST-2004-004182
20/22
June 2007
Confidential
final JTextField room = new JTextField("Kitchen");
JButton button = new JButton("Send Update");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Hashtable<String, String> ht =
new Hashtable<String, String>();
ht.put(person.getText(), room.getText());
m_parent.contextChanged(ht);
}
});
labelPerson.setLabelFor(person);
labelRoom.setLabelFor(room);
/**
* An easy way to put space between a top-level container and
* its contents is to put the contents in a JPanel that has an
* "empty" border.
*/
JPanel pane = new JPanel();
pane.setBorder(BorderFactory.createEmptyBorder(5, // top
5, // left
5, // bottom
5) // right
);
pane.setLayout(new GridLayout(0, 2));
pane.add(labelPerson);
pane.add(person);
pane.add(labelRoom);
pane.add(room);
pane.add(button);
pane.add(button);
return pane;
}
}
When the example context source is started, the following GUI will show up:
Amigo IST-2004-004182
21/22
June 2007
Confidential
4 Recommended next steps
Now that you have learned about ANS you may be interested in how to continue in the most
efficient way in order to become more familiar with the Amigo middleware. To this end this
document gives some recommended training documents you should consider to read:
o
Using Amigo Security Services: This document is a tutorial about gives an introduction
on how to use the Amigo Security Services in order to setup secure communication
channels between client and services. The tutorial will show how to write a secured
service, how to write a client that makes use of a secured service. Further, it will
explain how to authenticate a user/device within the Amigo network.
o
User Modeling and Profiling Services: As the name suggests, you will learn how to
describe and manage the preferences of the different users in the Amigo middleware.
Amigo IST-2004-004182
22/22
Download