added Clock and BinaryLight UPnP examples
git-svn-id: https://svn.apache.org/repos/asf/incubator/felix/trunk@399191 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/org.apache.felix.upnp.sample.binaryLight/pom.xml b/org.apache.felix.upnp.sample.binaryLight/pom.xml
new file mode 100644
index 0000000..d72af42
--- /dev/null
+++ b/org.apache.felix.upnp.sample.binaryLight/pom.xml
@@ -0,0 +1,60 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>felix</artifactId>
+ <version>0.8.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>osgi-bundle</packaging>
+ <groupId>org.apache.felix</groupId>
+ <name>Apache Felix UPnP Sample Binary-Light</name>
+ <artifactId>org.apache.felix.upnp.sample.binaryLight</artifactId>
+ <version>0.1.0-SNAPSHOT</version>
+ <!-- <url>http://maven.apache.org</url> -->
+ <dependencies>
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <version>0.8.0-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <version>0.8.0-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix.plugins</groupId>
+ <artifactId>maven-osgi-plugin</artifactId>
+ <!-- <version>${pom.version}</version> -->
+ <extensions>true</extensions>
+ <configuration>
+ <osgiManifest>
+ <bundleName>UPnPBinaryLight</bundleName>
+ <bundleVendor>Apache Software Foundation</bundleVendor>
+ <bundleVersion>0.1.0</bundleVersion>
+ <bundleDescription>
+ Standardized BinaryLight DCPs to test UPnP Base Driver
+ </bundleDescription>
+ <bundleSymbolicName>org.apache.felix.upnp.sample.binaryLight</bundleSymbolicName>
+ <bundleActivator>org.apache.felix.upnp.sample.binaryLight.Activator</bundleActivator>
+ <importPackage>
+ javax.swing,javax.imageio,org.osgi.framework;specification-version=1.3,org.osgi.service.upnp;specification-version=1.1
+ </importPackage>
+ </osgiManifest>
+ <manifestFile>src/main/resources/META-INF/Manifest.mf</manifestFile>
+ </configuration>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ </resource>
+ </resources>
+ </build>
+</project>
diff --git a/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/Activator.java b/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/Activator.java
new file mode 100644
index 0000000..52fb38b
--- /dev/null
+++ b/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/Activator.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.binaryLight;
+
+import java.util.Dictionary;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.upnp.UPnPDevice;
+
+
+/*
+* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+*/
+
+public class Activator implements BundleActivator {
+
+ static BundleContext context;
+ private ServiceRegistration serviceRegistration;
+ private LightDevice light;
+
+ /**
+ * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ Activator.context = context;
+ doServiceRegistration();
+ }
+
+ private void doServiceRegistration() {
+ light = new LightDevice(context);
+ Dictionary dict = light.getDescriptions(null);
+
+ serviceRegistration = context.registerService(
+ UPnPDevice.class.getName(),
+ light,
+ dict
+ );
+ }
+
+ /**
+ * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ serviceRegistration.unregister();
+ light.close();
+ }
+}
diff --git a/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/EventSource.java b/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/EventSource.java
new file mode 100644
index 0000000..c0c56de
--- /dev/null
+++ b/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/EventSource.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.binaryLight;
+
+import java.beans.PropertyChangeListener;
+
+/*
+* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+*/
+
+public interface EventSource {
+ void addPropertyChangeListener(PropertyChangeListener listener);
+ void addPropertyChangeListener(String propertyName, PropertyChangeListener listener);
+ void removePropertyChangeListener(PropertyChangeListener listener);
+ void removePropertyChangeListener(String propertyName, PropertyChangeListener listener);
+}
+
diff --git a/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/GetStatusAction.java b/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/GetStatusAction.java
new file mode 100644
index 0000000..746662b
--- /dev/null
+++ b/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/GetStatusAction.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.binaryLight;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.osgi.service.upnp.UPnPAction;
+import org.osgi.service.upnp.UPnPStateVariable;
+
+/*
+* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+*/
+
+public class GetStatusAction implements UPnPAction {
+
+ final private String NAME = "GetStatus";
+ final private String RESULT_STATUS = "ResultStatus";
+ final private String[] OUT_ARG_NAMES = new String[]{RESULT_STATUS};
+ private UPnPStateVariable state;
+ private LightModel model;
+
+
+ public GetStatusAction(LightModel model,UPnPStateVariable state){
+ this.state = state;
+ this.model=model;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getName()
+ */
+ public String getName() {
+ return NAME;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getReturnArgumentName()
+ */
+ public String getReturnArgumentName() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getInputArgumentNames()
+ */
+ public String[] getInputArgumentNames() {
+
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getOutputArgumentNames()
+ */
+ public String[] getOutputArgumentNames() {
+ return OUT_ARG_NAMES;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getStateVariable(java.lang.String)
+ */
+ public UPnPStateVariable getStateVariable(String argumentName) {
+ return state;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#invoke(java.util.Dictionary)
+ */
+ public Dictionary invoke(Dictionary args) throws Exception {
+ boolean status = model.getStatus();
+ Hashtable result = new Hashtable();
+ result.put(RESULT_STATUS,new Boolean(status));
+ return result;
+ }
+}
diff --git a/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/GetTargetAction.java b/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/GetTargetAction.java
new file mode 100644
index 0000000..eb55c06
--- /dev/null
+++ b/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/GetTargetAction.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.binaryLight;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.osgi.service.upnp.UPnPAction;
+import org.osgi.service.upnp.UPnPStateVariable;
+
+/*
+* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+*/
+
+public class GetTargetAction implements UPnPAction {
+
+ final private String NAME = "GetTarget";
+ final private String RET_TARGET_VALUE = "RetTargetValue";
+ final private String[] OUT_ARG_NAMES = new String[]{RET_TARGET_VALUE};
+ private UPnPStateVariable state;
+ private LightModel model;
+
+
+ public GetTargetAction(LightModel model,UPnPStateVariable state){
+ this.state = state;
+ this.model=model;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getName()
+ */
+ public String getName() {
+ return NAME;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getReturnArgumentName()
+ */
+ public String getReturnArgumentName() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getInputArgumentNames()
+ */
+ public String[] getInputArgumentNames() {
+
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getOutputArgumentNames()
+ */
+ public String[] getOutputArgumentNames() {
+ return OUT_ARG_NAMES;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getStateVariable(java.lang.String)
+ */
+ public UPnPStateVariable getStateVariable(String argumentName) {
+ return state;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#invoke(java.util.Dictionary)
+ */
+ public Dictionary invoke(Dictionary args) throws Exception {
+ boolean target = model.getTarget();
+ Hashtable result = new Hashtable();
+ result.put(RET_TARGET_VALUE,new Boolean(target));
+ return result;
+ }
+}
diff --git a/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/LightDevice.java b/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/LightDevice.java
new file mode 100644
index 0000000..1157a05
--- /dev/null
+++ b/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/LightDevice.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.binaryLight;
+
+import java.util.Dictionary;
+import java.util.Properties;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.service.upnp.UPnPDevice;
+import org.osgi.service.upnp.UPnPIcon;
+import org.osgi.service.upnp.UPnPService;
+
+/*
+* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+*/
+
+public class LightDevice implements UPnPDevice {
+
+ final private String DEVICE_ID = "uuid:Felix-BinaryLight";
+ private BundleContext context;
+ private LightModel model;
+ private LightUI ui;
+ private PowerSwitchService powerSwitch;
+ private UPnPService[] services;
+ private Dictionary dictionary;
+ private UPnPEventNotifier notifier;
+
+ public LightDevice(BundleContext context) {
+ this.context=context;
+ model = new LightModel();
+ ui = new LightUI(model);
+ powerSwitch = new PowerSwitchService(model);
+ services = new UPnPService[]{powerSwitch};
+ setupDeviceProperties();
+ buildEventNotifyer();
+ }
+
+ /**
+ *
+ */
+ private void buildEventNotifyer() {
+ notifier = new UPnPEventNotifier(context,DEVICE_ID,powerSwitch,model);
+ }
+
+ private void setupDeviceProperties(){
+ dictionary = new Properties();
+ dictionary.put(UPnPDevice.UPNP_EXPORT,"");
+ dictionary.put(
+ org.osgi.service
+ .device.Constants.DEVICE_CATEGORY,
+ new String[]{UPnPDevice.DEVICE_CATEGORY}
+ );
+ //dictionary.put(UPnPDevice.DEVICE_CATEGORY,new String[]{UPnPDevice.DEVICE_CATEGORY});
+ dictionary.put(UPnPDevice.FRIENDLY_NAME,"Felix OSGi-UPnP BinaryLight");
+ dictionary.put(UPnPDevice.MANUFACTURER,"Apache Software Foundation");
+ dictionary.put(UPnPDevice.MANUFACTURER_URL,"http://incubator.apache.org/felix/");
+ dictionary.put(UPnPDevice.MODEL_DESCRIPTION,"A BinaryLight device to test OSGi to UPnP service export");
+ dictionary.put(UPnPDevice.MODEL_NAME,"Lucciola");
+ dictionary.put(UPnPDevice.MODEL_NUMBER,"1.0");
+ dictionary.put(UPnPDevice.MODEL_URL,"http://incubator.apache.org/felix/lucciola");
+ dictionary.put(UPnPDevice.PRESENTATION_URL,"http://incubator.apache.org/felix/lucciola/presentation");
+ dictionary.put(UPnPDevice.SERIAL_NUMBER,"123456789");
+ dictionary.put(UPnPDevice.TYPE,"urn:schemas-upnp-org:device:BinaryLight:1");
+ dictionary.put(UPnPDevice.UDN,DEVICE_ID);
+ //dictionary.put(UPnPDevice.ID,dictionary.get(UPnPDevice.UDN));
+ dictionary.put(UPnPDevice.UPC,"1213456789");
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPDevice#getService(java.lang.String)
+ */
+ public UPnPService getService(String serviceId) {
+ if (serviceId.equals(powerSwitch.getId())) return powerSwitch;
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPDevice#getServices()
+ */
+ public UPnPService[] getServices() {
+ return services;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPDevice#getIcons(java.lang.String)
+ */
+ public UPnPIcon[] getIcons(String locale) {
+ UPnPIcon icon = new LightIcon();
+ return new UPnPIcon[]{icon} ;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPDevice#getDescriptions(java.lang.String)
+ */
+ public Dictionary getDescriptions(String locale) {
+ return dictionary;
+ }
+
+ /**
+ *
+ */
+ public void close() {
+ ui.dispose();
+ notifier.destroy();
+ }
+
+}
diff --git a/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/LightIcon.java b/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/LightIcon.java
new file mode 100644
index 0000000..cef3a36
--- /dev/null
+++ b/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/LightIcon.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.binaryLight;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.osgi.service.upnp.UPnPIcon;
+
+/*
+* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+*/
+
+public class LightIcon implements UPnPIcon {
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPIcon#getMimeType()
+ */
+ public String getMimeType() {
+ return "image/gif";
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPIcon#getWidth()
+ */
+ public int getWidth() {
+ return 32;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPIcon#getHeight()
+ */
+ public int getHeight() {
+ return 32;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPIcon#getSize()
+ */
+ public int getSize() {
+ return 0;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPIcon#getDepth()
+ */
+ public int getDepth() {
+ return 16;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPIcon#getInputStream()
+ */
+ public InputStream getInputStream() throws IOException {
+ return LightIcon.class.getResourceAsStream("images/LightOn.gif");
+ }
+}
diff --git a/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/LightModel.java b/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/LightModel.java
new file mode 100644
index 0000000..4e512ca
--- /dev/null
+++ b/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/LightModel.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.binaryLight;
+
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+
+/*
+* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+*/
+
+public class LightModel implements EventSource{
+
+ private boolean status = false;
+ private boolean target = false;
+ private boolean failure = false;
+ private PropertyChangeSupport propertySupport = new PropertyChangeSupport(this);
+
+ public LightModel(){
+ }
+
+ public void addPropertyChangeListener(PropertyChangeListener listener){
+ propertySupport.addPropertyChangeListener(listener);
+ }
+
+ public void removePropertyChangeListener(PropertyChangeListener listener){
+ propertySupport.removePropertyChangeListener(listener);
+ }
+ public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
+ propertySupport.addPropertyChangeListener(propertyName,listener);
+ }
+
+ public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
+ propertySupport.removePropertyChangeListener(propertyName,listener);
+ }
+
+ public void doSwitch(boolean value){
+ if (value) switchOn();
+ else switchOff();
+ }
+
+ public void switchOn(){
+ target = true;
+ if(! failure) {
+ boolean oldStatus = status;
+ status = true;
+ propertySupport.firePropertyChange("Status",oldStatus,status);
+ }
+ }
+
+ public void switchOff(){
+ target = false;
+ if(! failure) {
+ boolean oldStatus = status;
+ status = false;
+ propertySupport.firePropertyChange("Status",oldStatus,status);
+ }
+ }
+
+ public void setFailure(boolean value){
+ boolean oldFailure = failure;
+ boolean oldStatus = status;
+ failure = value;
+ if (failure){
+ status = false;
+ }
+ else if (target){
+ status = true;
+ }
+ propertySupport.firePropertyChange("Status",oldStatus,status);
+ propertySupport.firePropertyChange("Failure",oldFailure,failure);
+ }
+
+
+ /**
+ * @return
+ */
+ public boolean getTarget() {
+ return target;
+ }
+
+ /**
+ * @return
+ */
+ public boolean getStatus() {
+ return status;
+ }
+
+
+
+}
diff --git a/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/LightUI.java b/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/LightUI.java
new file mode 100644
index 0000000..5f67ba7
--- /dev/null
+++ b/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/LightUI.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.binaryLight;
+
+import java.awt.BorderLayout;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.net.URL;
+
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+
+import org.osgi.framework.BundleException;
+
+/*
+* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+*/
+
+public class LightUI extends JFrame implements PropertyChangeListener {
+ private final static ImageIcon LIGHT_ON = LightUI.loadIcon("LightOn.gif","ON");
+ private final static ImageIcon LIGHT_OFF = LightUI.loadIcon("LightOff.gif","OFF");
+ private final static ImageIcon LIGHT_FAIL = LightUI.loadIcon("LightFail.gif","FAILURE");
+ private final JLabel label = new JLabel();
+ private LightModel model;
+
+ public LightUI(LightModel model) {
+ super("Felix UPnP BinaryLight");
+ this.model = model;
+ setSize(150,150);
+ JPanel panel = new JPanel(new BorderLayout());
+ panel.add(doMainPanel(),BorderLayout.CENTER);
+ panel.add(doControlPanel(),BorderLayout.SOUTH);
+ getContentPane().add(panel);
+ model.addPropertyChangeListener(this);
+
+ addWindowListener(new WindowAdapter(){
+ public void windowClosing(WindowEvent e)
+ {
+ try {
+ Activator.context.getBundle().stop();
+ } catch (BundleException ex) {
+ ex.printStackTrace();
+ }
+ }
+ });
+ try {
+ URL eventIconUrl = LightUI.class.getResource("images/logo.gif");
+ ImageIcon icon= new ImageIcon(eventIconUrl,"logo");
+ setIconImage(icon.getImage());
+ }
+ catch (Exception ex){
+ System.out.println("Resource: IMAGES/logo.gif not found : " + ex.toString());
+ }
+
+ pack();
+ show();
+ }
+
+ private JPanel doMainPanel(){
+ JPanel panel = new JPanel();
+ label.setIcon(LIGHT_OFF);
+ //label.setSize(new Dimension(32,32));
+ label.addMouseListener(new MouseAdapter(){
+ public void mouseClicked(MouseEvent e){
+ if (SwingUtilities.isLeftMouseButton(e)){
+ if (e.getClickCount()==1){
+ Icon icon = label.getIcon();
+ if (icon == LIGHT_ON)
+ model.switchOff();
+ else
+ model.switchOn();
+ }
+ }
+ }
+ });
+ panel.add(label);
+ return panel;
+ }
+
+ private JPanel doControlPanel(){
+ JPanel panel = new JPanel();
+ JButton btnSwitch = new JButton("On");
+ JButton btnFailure = new JButton("Failure");
+ panel.add(btnSwitch);
+ panel.add(btnFailure);
+ return panel;
+ }
+
+ public static ImageIcon loadIcon(String path,String title)
+ {
+ try {
+ URL eventIconUrl = LightUI.class.getResource("images/" + path);
+ return new ImageIcon(eventIconUrl,title);
+ }
+ catch (Exception ex){
+ System.out.println("Resource:" + path + " not found : " + ex.toString());
+ return null;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
+ */
+ public void propertyChange(PropertyChangeEvent evt) {
+ String property = evt.getPropertyName();
+ System.out.println("Light changed property::"+property);
+ boolean value = ((Boolean) evt.getNewValue()).booleanValue();
+ if (property.equals("Status")){
+ if (value)
+ label.setIcon(LIGHT_ON);
+ else
+ label.setIcon(LIGHT_OFF);
+ }
+ else if (property.equals("Failure")){
+ if (value)
+ label.setIcon(LIGHT_FAIL);
+ else
+ label.setIcon(LIGHT_OFF);
+ }
+ getContentPane().validate();
+ repaint();
+
+ }
+
+
+}
diff --git a/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/PowerSwitchService.java b/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/PowerSwitchService.java
new file mode 100644
index 0000000..1d0989f
--- /dev/null
+++ b/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/PowerSwitchService.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+
+package org.apache.felix.upnp.sample.binaryLight;
+
+import java.util.HashMap;
+
+import org.osgi.service.upnp.UPnPAction;
+import org.osgi.service.upnp.UPnPService;
+import org.osgi.service.upnp.UPnPStateVariable;
+
+/*
+* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+*/
+
+public class PowerSwitchService implements UPnPService{
+
+ final private String SERVICE_ID = "urn:upnp-org:serviceId:SwitchPower:1";
+ final private String SERVICE_TYPE = "urn:schemas-upnp-org:service:SwitchPower:1";
+ final private String VERSION ="1";
+
+ private LightModel model;
+ private UPnPStateVariable status,target;
+ private UPnPStateVariable[] states;
+ private HashMap actions = new HashMap();
+
+
+ public PowerSwitchService(LightModel model){
+ this.model = model;
+ status = new StatusStateVariable();
+ target = new TargetStateVariable();
+ this.states = new UPnPStateVariable[]{status,target};
+
+ UPnPAction setTarget = new SetTargetAction(model,target);
+ UPnPAction getTarget = new GetTargetAction(model,target);
+ UPnPAction getStatus = new GetStatusAction(model,status);
+ actions.put(setTarget.getName(),setTarget);
+ actions.put(getTarget.getName(),getTarget);
+ actions.put(getStatus.getName(),getStatus);
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPService#getId()
+ */
+ public String getId() {
+ return SERVICE_ID;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPService#getType()
+ */
+ public String getType() {
+ return SERVICE_TYPE;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPService#getVersion()
+ */
+ public String getVersion() {
+ return VERSION;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPService#getAction(java.lang.String)
+ */
+ public UPnPAction getAction(String name) {
+ return (UPnPAction)actions.get(name);
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPService#getActions()
+ */
+ public UPnPAction[] getActions() {
+ return (UPnPAction[])(actions.values()).toArray(new UPnPAction[]{});
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPService#getStateVariables()
+ */
+ public UPnPStateVariable[] getStateVariables() {
+ return states;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPService#getStateVariable(java.lang.String)
+ */
+ public UPnPStateVariable getStateVariable(String name) {
+ if (name.equals("Status"))
+ return status;
+ else if (name.equals("Target"))
+ return target;
+ else return null;
+ }
+}
diff --git a/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/SetTargetAction.java b/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/SetTargetAction.java
new file mode 100644
index 0000000..42fb290
--- /dev/null
+++ b/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/SetTargetAction.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.binaryLight;
+
+import java.util.Dictionary;
+
+import org.osgi.service.upnp.UPnPAction;
+import org.osgi.service.upnp.UPnPStateVariable;
+
+/*
+* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+*/
+
+public class SetTargetAction implements UPnPAction {
+
+ final private String NAME = "SetTarget";
+ final private String NEW_TARGET_VALUE = "NewTargetValue";
+ final private String[] IN_ARG_NAMES = new String[]{NEW_TARGET_VALUE};
+ private UPnPStateVariable state;
+ private LightModel model;
+
+
+ public SetTargetAction(LightModel model,UPnPStateVariable state){
+ this.state = state;
+ this.model=model;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getName()
+ */
+ public String getName() {
+ return NAME;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getReturnArgumentName()
+ */
+ public String getReturnArgumentName() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getInputArgumentNames()
+ */
+ public String[] getInputArgumentNames() {
+ return IN_ARG_NAMES;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getOutputArgumentNames()
+ */
+ public String[] getOutputArgumentNames() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getStateVariable(java.lang.String)
+ */
+ public UPnPStateVariable getStateVariable(String argumentName) {
+ return state;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#invoke(java.util.Dictionary)
+ */
+ public Dictionary invoke(Dictionary args) throws Exception {
+ Boolean value = (Boolean) args.get(NEW_TARGET_VALUE);
+ model.doSwitch(value.booleanValue());
+ return null;
+ }
+}
diff --git a/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/StatusStateVariable.java b/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/StatusStateVariable.java
new file mode 100644
index 0000000..bf64539
--- /dev/null
+++ b/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/StatusStateVariable.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.binaryLight;
+import org.osgi.service.upnp.UPnPStateVariable;
+/*
+* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+*/
+
+public class StatusStateVariable implements UPnPStateVariable{
+
+ final private String NAME = "Status";
+ final private Boolean DEFAULT_VALUE = Boolean.FALSE;
+
+
+ public StatusStateVariable(){
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getName()
+ */
+ public String getName() {
+ return NAME;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getJavaDataType()
+ */
+ public Class getJavaDataType() {
+ return Boolean.class;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getUPnPDataType()
+ */
+ public String getUPnPDataType() {
+ return TYPE_BOOLEAN;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getDefaultValue()
+ */
+ public Object getDefaultValue() {
+ return DEFAULT_VALUE;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getAllowedValues()
+ */
+ public String[] getAllowedValues() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getMinimum()
+ */
+ public Number getMinimum() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getMaximum()
+ */
+ public Number getMaximum() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getStep()
+ */
+ public Number getStep() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#sendsEvents()
+ */
+ public boolean sendsEvents() {
+ return true;
+ }
+}
diff --git a/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/TargetStateVariable.java b/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/TargetStateVariable.java
new file mode 100644
index 0000000..7b792fd
--- /dev/null
+++ b/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/TargetStateVariable.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.binaryLight;
+import org.osgi.service.upnp.UPnPStateVariable;
+/*
+* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+*/
+
+public class TargetStateVariable implements UPnPStateVariable{
+
+ final private String NAME = "Target";
+ final private Boolean DEFAULT_VALUE = Boolean.FALSE;
+
+
+ public TargetStateVariable(){
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getName()
+ */
+ public String getName() {
+ return NAME;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getJavaDataType()
+ */
+ public Class getJavaDataType() {
+ return Boolean.class;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getUPnPDataType()
+ */
+ public String getUPnPDataType() {
+ return TYPE_BOOLEAN;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getDefaultValue()
+ */
+ public Object getDefaultValue() {
+ return DEFAULT_VALUE;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getAllowedValues()
+ */
+ public String[] getAllowedValues() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getMinimum()
+ */
+ public Number getMinimum() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getMaximum()
+ */
+ public Number getMaximum() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getStep()
+ */
+ public Number getStep() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#sendsEvents()
+ */
+ public boolean sendsEvents() {
+ return false;
+ }
+}
diff --git a/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/UPnPEventNotifier.java b/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/UPnPEventNotifier.java
new file mode 100644
index 0000000..65c771e
--- /dev/null
+++ b/org.apache.felix.upnp.sample.binaryLight/src/main/java/org/apache/felix/upnp/sample/binaryLight/UPnPEventNotifier.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.binaryLight;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Vector;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.upnp.UPnPDevice;
+import org.osgi.service.upnp.UPnPEventListener;
+import org.osgi.service.upnp.UPnPService;
+import org.osgi.service.upnp.UPnPStateVariable;
+
+/*
+* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+*/
+
+public class UPnPEventNotifier implements PropertyChangeListener,ServiceListener {
+ BundleContext context;
+ String deviceId;
+ UPnPService service;
+ EventSource source;
+
+ Properties UPnPTargetListener;
+ String serviceId;
+ Vector upnpListeners = new Vector();
+
+ public UPnPEventNotifier(BundleContext context,String deviceId,UPnPService service,EventSource source){
+ this.context=context;
+ this.deviceId=deviceId;
+ this.service=service;
+ this.source=source;
+ this.serviceId=service.getId();
+ setupUPnPListenerHouseKeeping(deviceId);
+ }
+
+ /**
+ * @param deviceId
+ */
+ private void setupUPnPListenerHouseKeeping(String deviceId) {
+ UPnPTargetListener = new Properties();
+ UPnPTargetListener.put(UPnPDevice.ID,deviceId);
+ UPnPTargetListener.put(UPnPService.ID,serviceId);
+ String ANY_UPnPEventListener = "("+Constants.OBJECTCLASS+"="+UPnPEventListener.class.getName()+")";
+
+ ServiceReference[] listeners = null;
+ try {
+ listeners = context.getServiceReferences(UPnPEventListener.class.getName(),null);
+ if (listeners != null){
+ for (int i = 0;i<listeners.length;i++){
+ ServiceReference sr = listeners[i];
+ Filter filter = (Filter) sr.getProperty(UPnPEventListener.UPNP_FILTER);
+ if (filter == null) upnpListeners.add(sr);
+ else {
+ if (filter.match(UPnPTargetListener))
+ addNewListener(sr);
+ }
+ }
+ }
+ } catch (Exception ex) {
+ System.out.println(ex);
+ }
+
+ try {
+ //String filter = "(&" + ANY_UPnPEventListener + deviceId_Filter + ")";
+ String filter = ANY_UPnPEventListener;
+ context.addServiceListener(this,filter);
+ } catch (Exception ex) {
+ System.out.println(ex);
+ }
+
+ if (source!=null){
+ UPnPStateVariable[] vars = service.getStateVariables();
+ if (vars != null){
+ for (int i=0;i<vars.length;i++)
+ if(vars[i].sendsEvents())
+ source.addPropertyChangeListener(vars[i].getName(),this);
+ }
+ }
+
+
+ }
+
+ /* (non-Javadoc)
+ * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
+ */
+ public void propertyChange(PropertyChangeEvent evt) {
+ Iterator list = upnpListeners.iterator();
+ String property = evt.getPropertyName();
+ Object value = evt.getNewValue();
+ String valueString = value.toString();
+ final Properties events = new Properties();
+ events.put(property,valueString);
+ while (list.hasNext()){
+ final ServiceReference sr = (ServiceReference)list.next();
+ String[] props =sr.getPropertyKeys();
+ new Thread(null,null,"Notifier"){
+ public void run(){
+ try {
+ UPnPEventListener listener = (UPnPEventListener) context.getService(sr);
+ listener.notifyUPnPEvent(deviceId,serviceId,events);
+ context.ungetService(sr);
+ } catch (Exception ex){
+ System.out.println("UPnPEventNotifier Err: " +ex);
+ }
+ }
+ }.start();
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent)
+ */
+ public void serviceChanged(ServiceEvent e) {
+ switch(e.getType()){
+ case ServiceEvent.REGISTERED:{
+ System.out.println();
+ ServiceReference sr = e.getServiceReference();
+ System.out.println(sr);
+ Filter filter = (Filter) sr.getProperty(UPnPEventListener.UPNP_FILTER);
+ System.out.println(filter);
+ if (filter == null) addNewListener(sr);
+ else {
+ if (filter.match(UPnPTargetListener))
+ addNewListener(sr);
+ }
+ };break;
+
+ case ServiceEvent.MODIFIED:{
+ };break;
+
+ case ServiceEvent.UNREGISTERING:{
+ removeListener(e.getServiceReference());
+ };break;
+
+ }
+
+ }
+
+ /**
+ * @param reference
+ */
+ private void removeListener(ServiceReference reference) {
+ upnpListeners.remove(reference);
+ }
+
+ /**
+ * @param reference
+ */
+ private void addNewListener(ServiceReference reference) {
+ upnpListeners.add(reference);
+ }
+
+ public void destroy(){
+ context.removeServiceListener(this);
+ upnpListeners.removeAllElements();
+ }
+}
diff --git a/org.apache.felix.upnp.sample.binaryLight/src/main/resources/META-INF/MANIFEST.MF b/org.apache.felix.upnp.sample.binaryLight/src/main/resources/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..da39e56
--- /dev/null
+++ b/org.apache.felix.upnp.sample.binaryLight/src/main/resources/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Bundle-Author: Matteo Demuru <demuru@apache.org>,Francesco Furfari <furfari@apache.org>,Stefano "Kismet" Lenzi <lenzi@apache.org>
+Bundle-ClassPath: .
+
diff --git a/org.apache.felix.upnp.sample.binaryLight/src/main/resources/org/apache/felix/upnp/sample/binaryLight/images/LightFail.gif b/org.apache.felix.upnp.sample.binaryLight/src/main/resources/org/apache/felix/upnp/sample/binaryLight/images/LightFail.gif
new file mode 100644
index 0000000..974194b
--- /dev/null
+++ b/org.apache.felix.upnp.sample.binaryLight/src/main/resources/org/apache/felix/upnp/sample/binaryLight/images/LightFail.gif
Binary files differ
diff --git a/org.apache.felix.upnp.sample.binaryLight/src/main/resources/org/apache/felix/upnp/sample/binaryLight/images/LightOff.gif b/org.apache.felix.upnp.sample.binaryLight/src/main/resources/org/apache/felix/upnp/sample/binaryLight/images/LightOff.gif
new file mode 100644
index 0000000..b93b2ec
--- /dev/null
+++ b/org.apache.felix.upnp.sample.binaryLight/src/main/resources/org/apache/felix/upnp/sample/binaryLight/images/LightOff.gif
Binary files differ
diff --git a/org.apache.felix.upnp.sample.binaryLight/src/main/resources/org/apache/felix/upnp/sample/binaryLight/images/LightOn.gif b/org.apache.felix.upnp.sample.binaryLight/src/main/resources/org/apache/felix/upnp/sample/binaryLight/images/LightOn.gif
new file mode 100644
index 0000000..7024922
--- /dev/null
+++ b/org.apache.felix.upnp.sample.binaryLight/src/main/resources/org/apache/felix/upnp/sample/binaryLight/images/LightOn.gif
Binary files differ
diff --git a/org.apache.felix.upnp.sample.binaryLight/src/main/resources/org/apache/felix/upnp/sample/binaryLight/images/logo.gif b/org.apache.felix.upnp.sample.binaryLight/src/main/resources/org/apache/felix/upnp/sample/binaryLight/images/logo.gif
new file mode 100644
index 0000000..ef39d61
--- /dev/null
+++ b/org.apache.felix.upnp.sample.binaryLight/src/main/resources/org/apache/felix/upnp/sample/binaryLight/images/logo.gif
Binary files differ
diff --git a/org.apache.felix.upnp.sample.clock/pom.xml b/org.apache.felix.upnp.sample.clock/pom.xml
new file mode 100644
index 0000000..952b71f
--- /dev/null
+++ b/org.apache.felix.upnp.sample.clock/pom.xml
@@ -0,0 +1,60 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>felix</artifactId>
+ <version>0.8.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>osgi-bundle</packaging>
+ <groupId>org.apache.felix</groupId>
+ <name>Apache Felix UPnP Sample Clock</name>
+ <artifactId>org.apache.felix.upnp.sample.clock</artifactId>
+ <version>0.1.0-SNAPSHOT</version>
+ <!-- <url>http://maven.apache.org</url> -->
+ <dependencies>
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <version>0.8.0-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <version>0.8.0-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix.plugins</groupId>
+ <artifactId>maven-osgi-plugin</artifactId>
+ <!-- <version>${pom.version}</version> -->
+ <extensions>true</extensions>
+ <configuration>
+ <osgiManifest>
+ <bundleName>UPnPClock</bundleName>
+ <bundleVendor>Apache Software Foundation</bundleVendor>
+ <bundleVersion>0.1.0</bundleVersion>
+ <bundleDescription>
+ CyberLink Clock clone to test UPnPBase driver
+ </bundleDescription>
+ <bundleSymbolicName>org.apache.felix.upnp.sample.clock</bundleSymbolicName>
+ <bundleActivator>org.apache.felix.upnp.sample.clock.Activator</bundleActivator>
+ <importPackage>
+ javax.swing,javax.imageio,org.osgi.framework;specification-version=1.3,org.osgi.service.upnp;specification-version=1.1
+ </importPackage>
+ </osgiManifest>
+ <manifestFile>src/main/resources/META-INF/Manifest.mf</manifestFile>
+ </configuration>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ </resource>
+ </resources>
+ </build>
+</project>
diff --git a/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/Activator.java b/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/Activator.java
new file mode 100644
index 0000000..5b92db7
--- /dev/null
+++ b/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/Activator.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.clock;
+
+import java.util.Dictionary;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.upnp.UPnPDevice;
+
+/*
+* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+*/
+public class Activator implements BundleActivator {
+
+ private ServiceRegistration serviceRegistration;
+ private BundleContext context;
+ private ClockFrame clockFrame;
+
+ /**
+ * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ this.context = context;
+ doServiceRegistration();
+ }
+
+ private void doServiceRegistration() {
+ clockFrame = new ClockFrame(context);
+ Dictionary dict = clockFrame.getClockDevice().getDescriptions(null);
+
+ serviceRegistration = context.registerService(
+ UPnPDevice.class.getName(),
+ clockFrame.getClockDevice(),
+ dict
+ );
+
+ clockFrame.start();
+
+ }
+
+ /**
+ * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ serviceRegistration.unregister();
+ clockFrame.stop();
+ }
+}
diff --git a/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/Clock.java b/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/Clock.java
new file mode 100644
index 0000000..294e637
--- /dev/null
+++ b/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/Clock.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.felix.upnp.sample.clock;
+
+import java.util.Calendar;
+/*
+* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+*/
+
+public class Clock
+{
+ private Calendar cal;
+
+ public Clock(Calendar cal)
+ {
+ this.cal = cal;
+ }
+
+ public Calendar getCalendar()
+ {
+ return cal;
+ }
+
+ ////////////////////////////////////////////////
+ // Time
+ ////////////////////////////////////////////////
+
+ public int getHour()
+ {
+ return getCalendar().get(Calendar.HOUR);
+ }
+
+ public int getMinute()
+ {
+ return getCalendar().get(Calendar.MINUTE);
+ }
+
+ public int getSecond()
+ {
+ return getCalendar().get(Calendar.SECOND);
+ }
+
+ ////////////////////////////////////////////////
+ // paint
+ ////////////////////////////////////////////////
+
+ public final static Clock getInstance()
+ {
+ return new Clock(Calendar.getInstance());
+ }
+
+ ////////////////////////////////////////////////
+ // getDateString
+ ////////////////////////////////////////////////
+
+ public final static String toClockString(int value)
+ {
+ if (value < 10)
+ return "0" + Integer.toString(value);
+ return Integer.toString(value);
+ }
+
+ private final static String MONTH_STRING[] = {
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec",
+ };
+
+ public final static String toMonthString(int value)
+ {
+ value -= Calendar.JANUARY;
+ if (0 <= value && value < 12)
+ return MONTH_STRING[value];
+ return "";
+ }
+
+ private final static String WEEK_STRING[] = {
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat",
+ };
+
+ public final static String toWeekString(int value)
+ {
+ value -= Calendar.SUNDAY;
+ if (0 <= value && value < 7)
+ return WEEK_STRING[value];
+ return "";
+ }
+
+ public String getDateString()
+ {
+ Calendar cal = getCalendar();
+ return
+ toWeekString(cal.get(Calendar.DAY_OF_WEEK)) +", " +
+ toMonthString(cal.get(Calendar.MONTH)) + " " +
+ Integer.toString(cal.get(Calendar.DATE)) + ", " +
+ toClockString(cal.get(Calendar.YEAR) % 100);
+ }
+
+ ////////////////////////////////////////////////
+ // getTimeString
+ ////////////////////////////////////////////////
+
+ public String getTimeString()
+ {
+ Calendar cal = getCalendar();
+ return
+ toClockString(cal.get(Calendar.HOUR)) +
+ (((cal.get(Calendar.SECOND) % 2) == 0) ? ":" : " ") +
+ toClockString(cal.get(Calendar.MINUTE));
+ }
+
+ ////////////////////////////////////////////////
+ // toString
+ ////////////////////////////////////////////////
+
+ public String toString()
+ {
+ Calendar cal = getCalendar();
+ return
+ getDateString() + ", " +
+ toClockString(cal.get(Calendar.HOUR)) + ":" +
+ toClockString(cal.get(Calendar.MINUTE)) + ":" +
+ toClockString(cal.get(Calendar.SECOND));
+ }
+
+}
+
diff --git a/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/ClockDevice.java b/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/ClockDevice.java
new file mode 100644
index 0000000..677975b
--- /dev/null
+++ b/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/ClockDevice.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.felix.upnp.sample.clock;
+
+
+import java.beans.PropertyChangeEvent;
+import java.util.Dictionary;
+import java.util.Properties;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.service.upnp.UPnPDevice;
+import org.osgi.service.upnp.UPnPIcon;
+import org.osgi.service.upnp.UPnPService;
+/*
+* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+*/
+
+public class ClockDevice implements UPnPDevice {
+
+ final private String DEVICE_ID = "uuid:Felix-Clock";
+ private BundleContext context;
+ private TimerService timerService;
+ private UPnPService[] services;
+ private Dictionary dictionary;
+ UPnPEventNotifier notifier;
+
+ public ClockDevice(BundleContext context) {
+ this.context=context;
+ timerService = new TimerService();
+ services = new UPnPService[]{timerService};
+ setupDeviceProperties();
+ buildEventNotifyer();
+ }
+
+ /**
+ *
+ */
+ private void buildEventNotifyer() {
+ notifier = new UPnPEventNotifier(context,this,timerService,null);
+ }
+
+ private void setupDeviceProperties(){
+ dictionary = new Properties();
+ dictionary.put(UPnPDevice.UPNP_EXPORT,"");
+ dictionary.put(
+ org.osgi.service
+ .device.Constants.DEVICE_CATEGORY,
+ new String[]{UPnPDevice.DEVICE_CATEGORY}
+ );
+ //dictionary.put(UPnPDevice.DEVICE_CATEGORY,new String[]{UPnPDevice.DEVICE_CATEGORY});
+ dictionary.put(UPnPDevice.FRIENDLY_NAME,"Felix OSGi-UPnP Clock");
+ dictionary.put(UPnPDevice.MANUFACTURER,"Apache Software Foundation");
+ dictionary.put(UPnPDevice.MANUFACTURER_URL,"http://incubator.apache.org/felix/");
+ dictionary.put(UPnPDevice.MODEL_DESCRIPTION,"A CyberLink Clock device clone to test OSGi to UPnP service export");
+ dictionary.put(UPnPDevice.MODEL_NAME,"DolceDormire");
+ dictionary.put(UPnPDevice.MODEL_NUMBER,"1.0");
+ dictionary.put(UPnPDevice.MODEL_URL,"http://incubator.apache.org/felix/DolceDormire");
+ dictionary.put(UPnPDevice.PRESENTATION_URL,"http://incubator.apache.org/felix/dolceDormire/presentation");
+ dictionary.put(UPnPDevice.SERIAL_NUMBER,"123456789");
+ dictionary.put(UPnPDevice.TYPE,"urn:schemas-upnp-org:device:clock:1");
+ dictionary.put(UPnPDevice.UDN,DEVICE_ID);
+ //dictionary.put(UPnPDevice.ID,dictionary.get(UPnPDevice.UDN));
+ dictionary.put(UPnPDevice.UPC,"1213456789");
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPDevice#getService(java.lang.String)
+ */
+ public UPnPService getService(String serviceId) {
+ if (serviceId.equals(timerService.getId())) return timerService;
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPDevice#getServices()
+ */
+ public UPnPService[] getServices() {
+ return services;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPDevice#getIcons(java.lang.String)
+ */
+ public UPnPIcon[] getIcons(String locale) {
+ UPnPIcon icon = new ClockIcon();
+ return new UPnPIcon[]{icon} ;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPDevice#getDescriptions(java.lang.String)
+ */
+ public Dictionary getDescriptions(String locale) {
+ return dictionary;
+ }
+
+ /**
+ *
+ */
+ public void start() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ *
+ */
+ public void stop() {
+ notifier.destroy();
+ }
+
+ /**
+ *
+ */
+ public void update() {
+ Clock clock = Clock.getInstance();
+ String timeStr = clock.toString();
+ notifier.propertyChange(new PropertyChangeEvent(this,"Time","",timeStr));
+ }
+
+}
diff --git a/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/ClockFrame.java b/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/ClockFrame.java
new file mode 100644
index 0000000..a35dc38
--- /dev/null
+++ b/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/ClockFrame.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.felix.upnp.sample.clock;
+
+import java.awt.BorderLayout;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.net.URL;
+
+import javax.swing.ImageIcon;
+import javax.swing.JFrame;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+/*
+* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+*/
+
+public class ClockFrame extends JFrame implements Runnable
+{
+ private final static String TITLE = "Felix UPnP Clock";
+ private ClockDevice clockDev;
+ private ClockPane clockPane;
+
+ public ClockFrame(final BundleContext context)
+ {
+ super(TITLE);
+ try {
+ clockDev = new ClockDevice( context);
+ }
+ catch (Exception e) {
+ System.out.println(e);
+ }
+
+ getContentPane().setLayout(new BorderLayout());
+
+ clockPane = new ClockPane();
+ getContentPane().add(clockPane, BorderLayout.CENTER);
+
+ addWindowListener(new WindowAdapter(){
+ public void windowClosing(WindowEvent e)
+ {
+ try {
+ context.getBundle().stop();
+ } catch (BundleException ex) {
+ ex.printStackTrace();
+ }
+ }
+ });
+ try {
+ URL eventIconUrl = ClockFrame.class.getResource("images/logo.gif");
+ ImageIcon icon= new ImageIcon(eventIconUrl,"logo");
+ setIconImage(icon.getImage());
+ }
+ catch (Exception ex){
+ System.out.println("Resource: IMAGES/logo.gif not found : " + ex.toString());
+ }
+
+ pack();
+ setVisible(true);
+ }
+
+ public ClockPane getClockPanel()
+ {
+ return clockPane;
+ }
+
+ public ClockDevice getClockDevice()
+ {
+ return clockDev;
+ }
+
+ ////////////////////////////////////////////////
+ // run
+ ////////////////////////////////////////////////
+
+ private Thread timerThread = null;
+
+ public void run()
+ {
+ Thread thisThread = Thread.currentThread();
+
+ while (timerThread == thisThread) {
+ getClockDevice().update();
+ getClockPanel().repaint();
+ try {
+ Thread.sleep(1000);
+ }
+ catch(InterruptedException e) {}
+ }
+ }
+
+ public void start()
+ {
+ clockDev.start();
+
+ timerThread = new Thread(this);
+ timerThread.start();
+ }
+
+ public void stop()
+ {
+ clockDev.stop();
+ timerThread = null;
+ dispose();
+ }
+
+}
+
diff --git a/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/ClockIcon.java b/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/ClockIcon.java
new file mode 100644
index 0000000..53586be
--- /dev/null
+++ b/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/ClockIcon.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.felix.upnp.sample.clock;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.osgi.service.upnp.UPnPIcon;
+/*
+* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+*/
+
+public class ClockIcon implements UPnPIcon {
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPIcon#getMimeType()
+ */
+ public String getMimeType() {
+ return "image/gif";
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPIcon#getWidth()
+ */
+ public int getWidth() {
+ return 32;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPIcon#getHeight()
+ */
+ public int getHeight() {
+ return 32;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPIcon#getSize()
+ */
+ public int getSize() {
+ return 0;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPIcon#getDepth()
+ */
+ public int getDepth() {
+ return 16;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPIcon#getInputStream()
+ */
+ public InputStream getInputStream() throws IOException {
+ return ClockIcon.class.getResourceAsStream("images/clock.gif");
+ }
+}
diff --git a/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/ClockPane.java b/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/ClockPane.java
new file mode 100644
index 0000000..3a9e232
--- /dev/null
+++ b/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/ClockPane.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.felix.upnp.sample.clock;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+
+import javax.imageio.ImageIO;
+import javax.swing.JPanel;
+
+/*
+* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+*/
+
+public class ClockPane extends JPanel // MouseListener
+{
+ public ClockPane()
+ {
+ loadImage();
+ initPanel();
+ }
+
+ ////////////////////////////////////////////////
+ // Background
+ ////////////////////////////////////////////////
+
+
+ private BufferedImage panelmage;
+
+ private void loadImage()
+ {
+
+ try {
+ panelmage = ImageIO.read(ClockPane.class.getResourceAsStream("images/clock.jpg"));
+ }
+ catch (Exception e) {
+ System.out.println(e);
+ }
+ }
+
+ private BufferedImage getPaneImage()
+ {
+ return panelmage;
+ }
+
+ ////////////////////////////////////////////////
+ // Background
+ ////////////////////////////////////////////////
+
+ private void initPanel()
+ {
+ BufferedImage panelmage = getPaneImage();
+ setPreferredSize(new Dimension(panelmage.getWidth(), panelmage.getHeight()));
+ }
+
+ ////////////////////////////////////////////////
+ // Font
+ ////////////////////////////////////////////////
+
+ private final static String DEFAULT_FONT_NAME = "Lucida Console";
+ private final static int DEFAULT_TIME_FONT_SIZE = 60;
+ private final static int DEFAULT_DATE_FONT_SIZE = 18;
+ private final static int DEFAULT_SECOND_BLOCK_HEIGHT = 8;
+ private final static int DEFAULT_SECOND_BLOCK_FONT_SIZE = 10;
+
+ private Font timeFont = null;
+ private Font dateFont = null;
+ private Font secondFont = null;
+
+ private Font getFont(Graphics g, int size)
+ {
+ Font font = new Font(DEFAULT_FONT_NAME, Font.PLAIN, size);
+ if (font != null)
+ return font;
+ return g.getFont();
+ }
+
+ private Font getTimeFont(Graphics g)
+ {
+ if (timeFont == null)
+ timeFont = getFont(g, DEFAULT_TIME_FONT_SIZE);
+ return timeFont;
+ }
+
+ private Font getDateFont(Graphics g)
+ {
+ if (dateFont == null)
+ dateFont = getFont(g, DEFAULT_DATE_FONT_SIZE);
+ return dateFont;
+ }
+
+ private Font getSecondFont(Graphics g)
+ {
+ if (secondFont == null)
+ secondFont = getFont(g, DEFAULT_SECOND_BLOCK_FONT_SIZE);
+ return secondFont;
+ }
+
+ ////////////////////////////////////////////////
+ // paint
+ ////////////////////////////////////////////////
+
+ private void drawClockInfo(Graphics g)
+ {
+ Clock clock = Clock.getInstance();
+
+ int winWidth = getWidth();
+ int winHeight = getHeight();
+
+ g.setColor(Color.BLACK);
+
+ //// Time String ////
+
+ String timeStr = clock.getTimeString();
+
+ Font timeFont = getTimeFont(g);
+ g.setFont(timeFont);
+
+ FontMetrics timeFontMetric = g.getFontMetrics();
+ Rectangle2D timeStrBounds = timeFontMetric.getStringBounds(timeStr, g);
+
+ int timeStrWidth = (int)timeStrBounds.getWidth();
+ int timeStrHeight = (int)timeStrBounds.getHeight();
+ int timeStrX = (winWidth-timeStrWidth)/2;
+ int timeStrY = (winHeight+timeStrHeight)/2;
+ int timeStrOffset = timeStrHeight/8/2;
+ g.drawString(
+ timeStr,
+ timeStrX,
+ timeStrY);
+
+ //// Date String ////
+
+ String dateStr = clock.getDateString();
+
+ Font dateFont = getDateFont(g);
+ g.setFont(dateFont);
+
+ FontMetrics dateFontMetric = g.getFontMetrics();
+ Rectangle2D dateStrBounds = dateFontMetric.getStringBounds(dateStr, g);
+
+ g.drawString(
+ dateStr,
+ (winWidth-(int)dateStrBounds.getWidth())/2,
+ timeStrY-timeStrHeight-timeStrOffset);
+
+ //// Second Bar ////
+
+ Font secFont = getSecondFont(g);
+ g.setFont(secFont);
+ int sec = clock.getSecond();
+ int secBarBlockSize = timeStrWidth / 60;
+ int secBarBlockY = timeStrY + timeStrOffset;
+ for (int n=0; n<sec; n++) {
+ int x = timeStrX + (secBarBlockSize*n);
+ g.fillRect(
+ x,
+ secBarBlockY,
+ secBarBlockSize-1,
+ DEFAULT_SECOND_BLOCK_HEIGHT);
+ }
+ if (sec != 0 && (sec % 10) == 0) {
+ int x = timeStrX + (secBarBlockSize*sec);
+ g.drawString(
+ Integer.toString(sec),
+ x + secBarBlockSize,
+ secBarBlockY + DEFAULT_SECOND_BLOCK_HEIGHT);
+ }
+ }
+
+ private void clear(Graphics g)
+ {
+ g.setColor(Color.GRAY);
+ g.clearRect(0, 0, getWidth(), getHeight());
+ }
+
+
+ private void drawPanelImage(Graphics g)
+ {
+ g.drawImage(getPaneImage(), 0, 0, null);
+ }
+
+ public void paint(Graphics g)
+ {
+ clear(g);
+ drawPanelImage(g);
+ drawClockInfo(g);
+ }
+}
+
diff --git a/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/EventSource.java b/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/EventSource.java
new file mode 100644
index 0000000..62fd7b1
--- /dev/null
+++ b/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/EventSource.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.felix.upnp.sample.clock;
+
+import java.beans.PropertyChangeListener;
+/*
+* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+*/
+
+public interface EventSource {
+ void addPropertyChangeListener(PropertyChangeListener listener);
+ void addPropertyChangeListener(String propertyName, PropertyChangeListener listener);
+ void removePropertyChangeListener(PropertyChangeListener listener);
+ void removePropertyChangeListener(String propertyName, PropertyChangeListener listener);
+}
+
diff --git a/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/GetTimeAction.java b/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/GetTimeAction.java
new file mode 100644
index 0000000..d3d8728
--- /dev/null
+++ b/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/GetTimeAction.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.felix.upnp.sample.clock;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.osgi.service.upnp.UPnPAction;
+import org.osgi.service.upnp.UPnPStateVariable;
+
+/*
+* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+*/
+
+public class GetTimeAction implements UPnPAction {
+
+ final private String NAME = "GetTime";
+ final private String RESULT_STATUS = "CurrentTime";
+ final private String[] OUT_ARG_NAMES = new String[]{RESULT_STATUS};
+ private TimeStateVariable time;
+
+
+ public GetTimeAction(TimeStateVariable time){
+ this.time = time;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getName()
+ */
+ public String getName() {
+ return NAME;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getReturnArgumentName()
+ */
+ public String getReturnArgumentName() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getInputArgumentNames()
+ */
+ public String[] getInputArgumentNames() {
+
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getOutputArgumentNames()
+ */
+ public String[] getOutputArgumentNames() {
+ return OUT_ARG_NAMES;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getStateVariable(java.lang.String)
+ */
+ public UPnPStateVariable getStateVariable(String argumentName) {
+ return time;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#invoke(java.util.Dictionary)
+ */
+ public Dictionary invoke(Dictionary args) throws Exception {
+ String value = time.getCurrentTime();
+ Hashtable result = new Hashtable();
+ result.put(RESULT_STATUS,value);
+ return result;
+ }
+}
diff --git a/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/ResultStateVariable.java b/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/ResultStateVariable.java
new file mode 100644
index 0000000..45983b8
--- /dev/null
+++ b/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/ResultStateVariable.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.felix.upnp.sample.clock;
+import org.osgi.service.upnp.UPnPStateVariable;
+/*
+* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+*/
+
+public class ResultStateVariable implements UPnPStateVariable{
+
+ final private String NAME = "Result";
+ final private String DEFAULT_VALUE = "";
+ private Clock clock;
+
+
+ public ResultStateVariable(){
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getName()
+ */
+ public String getName() {
+ return NAME;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getJavaDataType()
+ */
+ public Class getJavaDataType() {
+ return String.class;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getUPnPDataType()
+ */
+ public String getUPnPDataType() {
+ return TYPE_STRING;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getDefaultValue()
+ */
+ public Object getDefaultValue() {
+ return DEFAULT_VALUE;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getAllowedValues()
+ */
+ public String[] getAllowedValues() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getMinimum()
+ */
+ public Number getMinimum() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getMaximum()
+ */
+ public Number getMaximum() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getStep()
+ */
+ public Number getStep() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#sendsEvents()
+ */
+ public boolean sendsEvents() {
+ return false;
+ }
+
+}
diff --git a/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/SetTimeAction.java b/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/SetTimeAction.java
new file mode 100644
index 0000000..6312e02
--- /dev/null
+++ b/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/SetTimeAction.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.felix.upnp.sample.clock;
+
+import java.util.Dictionary;
+
+import org.osgi.service.upnp.UPnPAction;
+import org.osgi.service.upnp.UPnPStateVariable;
+
+/*
+* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+*/
+
+public class SetTimeAction implements UPnPAction {
+
+ final private String NAME = "SetTime";
+ final private String NEW_TIME_VALUE = "NewTime";
+ final private String NEW_RESULT_VALUE = "Result";
+ final private String[] IN_ARG_NAMES = new String[]{NEW_TIME_VALUE};
+ final private String[] OUT_ARG_NAMES = new String[]{NEW_RESULT_VALUE};
+ private UPnPStateVariable time,result;
+
+
+ public SetTimeAction(UPnPStateVariable time,UPnPStateVariable result){
+ this.time = time;
+ this.result=result;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getName()
+ */
+ public String getName() {
+ return NAME;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getReturnArgumentName()
+ */
+ public String getReturnArgumentName() {
+ return "Result";
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getInputArgumentNames()
+ */
+ public String[] getInputArgumentNames() {
+ return IN_ARG_NAMES;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getOutputArgumentNames()
+ */
+ public String[] getOutputArgumentNames() {
+ return OUT_ARG_NAMES;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getStateVariable(java.lang.String)
+ */
+ public UPnPStateVariable getStateVariable(String argumentName) {
+ if (argumentName.equals("NewTime")) return time;
+ else if (argumentName.equals("Result")) return result;
+ else return null;
+ }
+
+ /* (non-Javadoc)
+ *
+ * @see org.osgi.service.upnp.UPnPAction#invoke(java.util.Dictionary)
+ */
+ public Dictionary invoke(Dictionary args) throws Exception {
+ //Date value = (Date) args.get(NEW_TIME_VALUE);
+ long l = ((Long) args.get(NEW_TIME_VALUE)).longValue();
+ ((TimeStateVariable) time).setCurrentTime(l);
+ args.remove(NEW_TIME_VALUE);
+ args.put(NEW_RESULT_VALUE,((TimeStateVariable) time).getCurrentTime());
+ return args;
+ }
+}
diff --git a/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/TimeStateVariable.java b/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/TimeStateVariable.java
new file mode 100644
index 0000000..8ee30b5
--- /dev/null
+++ b/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/TimeStateVariable.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.felix.upnp.sample.clock;
+import org.osgi.service.upnp.UPnPStateVariable;
+/*
+* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+*/
+
+public class TimeStateVariable implements UPnPStateVariable{
+
+ final private String NAME = "Time";
+ final private String DEFAULT_VALUE = "";
+ private Clock clock;
+
+
+ public TimeStateVariable(){
+ clock = Clock.getInstance();
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getName()
+ */
+ public String getName() {
+ return NAME;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getJavaDataType()
+ */
+ public Class getJavaDataType() {
+ return Long.class;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getUPnPDataType()
+ */
+ public String getUPnPDataType() {
+ return TYPE_TIME;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getDefaultValue()
+ */
+ public Object getDefaultValue() {
+ return DEFAULT_VALUE;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getAllowedValues()
+ */
+ public String[] getAllowedValues() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getMinimum()
+ */
+ public Number getMinimum() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getMaximum()
+ */
+ public Number getMaximum() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getStep()
+ */
+ public Number getStep() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#sendsEvents()
+ */
+ public boolean sendsEvents() {
+ return true;
+ }
+
+ public String getCurrentTime(){
+ return clock.getTimeString();
+ }
+
+ public void setCurrentTime(long milliseconds){
+ clock.getCalendar().setTimeInMillis(milliseconds);
+ }
+}
diff --git a/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/TimerService.java b/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/TimerService.java
new file mode 100644
index 0000000..57927cf
--- /dev/null
+++ b/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/TimerService.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.felix.upnp.sample.clock;
+
+import java.util.HashMap;
+
+import org.osgi.service.upnp.UPnPAction;
+import org.osgi.service.upnp.UPnPService;
+import org.osgi.service.upnp.UPnPStateVariable;
+
+/*
+* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+*/
+
+public class TimerService implements UPnPService {
+ final private String SERVICE_ID = "urn:schemas-upnp-org:serviceId:timer:1";
+ final private String SERVICE_TYPE = "urn:schemas-upnp-org:service:timer:1";
+ final private String VERSION ="1";
+
+ private UPnPStateVariable time,result;
+ private UPnPStateVariable[] states;
+ private HashMap actions = new HashMap();
+
+
+ public TimerService(){
+ time = new TimeStateVariable();
+ result = new ResultStateVariable();
+ this.states = new UPnPStateVariable[]{time,result};
+
+ UPnPAction setTime= new SetTimeAction(time,result);
+ UPnPAction getTime = new GetTimeAction((TimeStateVariable)time);
+ actions.put(setTime.getName(),setTime);
+ actions.put(getTime.getName(),getTime);
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPService#getId()
+ */
+ public String getId() {
+ return SERVICE_ID;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPService#getType()
+ */
+ public String getType() {
+ return SERVICE_TYPE;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPService#getVersion()
+ */
+ public String getVersion() {
+ return VERSION;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPService#getAction(java.lang.String)
+ */
+ public UPnPAction getAction(String name) {
+ return (UPnPAction)actions.get(name);
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPService#getActions()
+ */
+ public UPnPAction[] getActions() {
+ return (UPnPAction[])(actions.values()).toArray(new UPnPAction[]{});
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPService#getStateVariables()
+ */
+ public UPnPStateVariable[] getStateVariables() {
+ return states;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPService#getStateVariable(java.lang.String)
+ */
+ public UPnPStateVariable getStateVariable(String name) {
+ if (name.equals("Time"))
+ return time;
+ else if (name.equals("Result"))
+ return result;
+ else return null;
+ }
+}
diff --git a/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/UPnPEventNotifier.java b/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/UPnPEventNotifier.java
new file mode 100644
index 0000000..b7c41df
--- /dev/null
+++ b/org.apache.felix.upnp.sample.clock/src/main/java/org/apache/felix/upnp/sample/clock/UPnPEventNotifier.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.felix.upnp.sample.clock;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Dictionary;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Vector;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.upnp.UPnPDevice;
+import org.osgi.service.upnp.UPnPEventListener;
+import org.osgi.service.upnp.UPnPService;
+import org.osgi.service.upnp.UPnPStateVariable;
+
+/*
+* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+*/
+
+public class UPnPEventNotifier implements PropertyChangeListener,ServiceListener {
+ BundleContext context;
+ UPnPDevice device;
+ UPnPService service;
+ EventSource source;
+
+ Properties UPnPTargetListener;
+ String deviceId;
+ String serviceId;
+ Vector upnpListeners = new Vector();
+
+ public UPnPEventNotifier(BundleContext context,UPnPDevice device,UPnPService service,EventSource source){
+ this.context=context;
+ this.device=device;
+ this.service=service;
+ this.source=source;
+ this.serviceId=service.getId();
+ setupUPnPListenerHouseKeeping(device);
+ }
+
+ /**
+ * @param deviceId
+ */
+ private void setupUPnPListenerHouseKeeping(UPnPDevice device) {
+ UPnPTargetListener = new Properties();
+ Dictionary dict = device.getDescriptions(null);
+ deviceId = (String) dict.get(UPnPDevice.ID);
+ UPnPTargetListener.put(UPnPDevice.ID,deviceId);
+ UPnPTargetListener.put(UPnPService.ID,serviceId);
+ UPnPTargetListener.put(UPnPDevice.TYPE,dict.get(UPnPDevice.TYPE));
+ UPnPTargetListener.put(UPnPService.TYPE,service.getType());
+ String ANY_UPnPEventListener = "("+Constants.OBJECTCLASS+"="+UPnPEventListener.class.getName()+")";
+
+ ServiceReference[] listeners = null;
+ try {
+ listeners = context.getServiceReferences(UPnPEventListener.class.getName(),null);
+ if (listeners != null){
+ for (int i = 0;i<listeners.length;i++){
+ ServiceReference sr = listeners[i];
+ Filter filter = (Filter) sr.getProperty(UPnPEventListener.UPNP_FILTER);
+ if (filter == null) upnpListeners.add(sr);
+ else {
+ if (filter.match(UPnPTargetListener))
+ addNewListener(sr);
+ }
+ }
+ }
+ } catch (Exception ex) {
+ System.out.println(ex);
+ }
+
+ try {
+ //String filter = "(&" + ANY_UPnPEventListener + deviceId_Filter + ")";
+ String filter = ANY_UPnPEventListener;
+ context.addServiceListener(this,filter);
+ } catch (Exception ex) {
+ System.out.println(ex);
+ }
+
+ if (source!=null){
+ UPnPStateVariable[] vars = service.getStateVariables();
+ if (vars != null){
+ for (int i=0;i<vars.length;i++)
+ if(vars[i].sendsEvents())
+ source.addPropertyChangeListener(vars[i].getName(),this);
+ }
+ }
+
+
+ }
+
+ /* (non-Javadoc)
+ * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
+ */
+ public void propertyChange(PropertyChangeEvent evt) {
+ Iterator list = upnpListeners.iterator();
+ String property = evt.getPropertyName();
+ Object value = evt.getNewValue();
+ String valueString = value.toString();
+ final Properties events = new Properties();
+ events.put(property,valueString);
+ while (list.hasNext()){
+ final ServiceReference sr = (ServiceReference)list.next();
+ String[] props =sr.getPropertyKeys();
+ new Thread(){
+ public void run(){
+ try {
+ UPnPEventListener listener = (UPnPEventListener) context.getService(sr);
+ listener.notifyUPnPEvent(deviceId,serviceId,events);
+ context.ungetService(sr);
+ } catch (Exception ex){
+ System.out.println("Clock UPnPEventNotifier Err: " +ex);
+ System.out.println("context: " +context);
+ System.out.println("listener: " +context.getService(sr));
+ System.out.println("sr: " +sr);
+ System.out.println();
+ }
+ }
+ }.start();
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent)
+ */
+ public void serviceChanged(ServiceEvent e) {
+ switch(e.getType()){
+ case ServiceEvent.REGISTERED:{
+ ServiceReference sr = e.getServiceReference();
+ Filter filter = (Filter) sr.getProperty(UPnPEventListener.UPNP_FILTER);
+ if (filter == null) addNewListener(sr);
+ else {
+ if (filter.match(UPnPTargetListener))
+ addNewListener(sr);
+ }
+ };break;
+
+ case ServiceEvent.MODIFIED:{
+ };break;
+
+ case ServiceEvent.UNREGISTERING:{
+ removeListener(e.getServiceReference());
+ };break;
+
+ }
+
+ }
+
+ /**
+ * @param reference
+ */
+ private void removeListener(ServiceReference reference) {
+ upnpListeners.remove(reference);
+ }
+
+ /**
+ * @param reference
+ */
+ private void addNewListener(ServiceReference reference) {
+ upnpListeners.add(reference);
+ }
+
+ public void destroy(){
+ context.removeServiceListener(this);
+ upnpListeners.removeAllElements();
+ }
+}
diff --git a/org.apache.felix.upnp.sample.clock/src/main/resources/META-INF/Manifest.mf b/org.apache.felix.upnp.sample.clock/src/main/resources/META-INF/Manifest.mf
new file mode 100644
index 0000000..69ff757
--- /dev/null
+++ b/org.apache.felix.upnp.sample.clock/src/main/resources/META-INF/Manifest.mf
@@ -0,0 +1,4 @@
+Bundle-Author: Matteo Demuru <demuru@apache.org>,Francesco Furfari <furfari@apache.org>,Satoshi Konno <konno@users.sourceforge.
+ net>,Stefano "Kismet" Lenzi <lenzi@apache.org>
+Bundle-ClassPath: .
+
diff --git a/org.apache.felix.upnp.sample.clock/src/main/resources/org/apache/felix/upnp/sample/clock/images/clock.gif b/org.apache.felix.upnp.sample.clock/src/main/resources/org/apache/felix/upnp/sample/clock/images/clock.gif
new file mode 100644
index 0000000..21327fc
--- /dev/null
+++ b/org.apache.felix.upnp.sample.clock/src/main/resources/org/apache/felix/upnp/sample/clock/images/clock.gif
Binary files differ
diff --git a/org.apache.felix.upnp.sample.clock/src/main/resources/org/apache/felix/upnp/sample/clock/images/clock.jpg b/org.apache.felix.upnp.sample.clock/src/main/resources/org/apache/felix/upnp/sample/clock/images/clock.jpg
new file mode 100644
index 0000000..f7fcea0
--- /dev/null
+++ b/org.apache.felix.upnp.sample.clock/src/main/resources/org/apache/felix/upnp/sample/clock/images/clock.jpg
Binary files differ
diff --git a/org.apache.felix.upnp.sample.clock/src/main/resources/org/apache/felix/upnp/sample/clock/images/logo.gif b/org.apache.felix.upnp.sample.clock/src/main/resources/org/apache/felix/upnp/sample/clock/images/logo.gif
new file mode 100644
index 0000000..ef39d61
--- /dev/null
+++ b/org.apache.felix.upnp.sample.clock/src/main/resources/org/apache/felix/upnp/sample/clock/images/logo.gif
Binary files differ