blob: 1e93656ebe9f8a232a07b7d40326cf167f4940d8 [file] [log] [blame]
Francesco Furfariec7e1752006-10-02 13:37:04 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
Francesco Furfarid8bdb642006-04-04 23:33:40 +00009 *
Francesco Furfariec7e1752006-10-02 13:37:04 +000010 * http://www.apache.org/licenses/LICENSE-2.0
Francesco Furfarid8bdb642006-04-04 23:33:40 +000011 *
Francesco Furfariec7e1752006-10-02 13:37:04 +000012 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
Francesco Furfarid8bdb642006-04-04 23:33:40 +000018 */
19
20package org.apache.felix.upnp.basedriver.importer.core;
21
22
23import java.util.ArrayList;
24import java.util.Dictionary;
25import java.util.Enumeration;
26import java.util.Hashtable;
27import java.util.Iterator;
28import java.util.Vector;
29
30import org.cybergarage.http.HTTPRequest;
31import org.cybergarage.upnp.ControlPoint;
32import org.cybergarage.upnp.Device;
33import org.cybergarage.upnp.DeviceList;
34import org.cybergarage.upnp.Service;
35import org.cybergarage.upnp.ServiceList;
36import org.cybergarage.upnp.ServiceStateTable;
37import org.cybergarage.upnp.StateVariable;
38import org.cybergarage.upnp.device.NotifyListener;
39import org.cybergarage.upnp.device.SearchResponseListener;
40import org.cybergarage.upnp.event.NotifyRequest;
41import org.cybergarage.upnp.event.Property;
42import org.cybergarage.upnp.event.PropertyList;
43import org.cybergarage.upnp.ssdp.SSDPPacket;
44
45import org.osgi.framework.BundleContext;
46import org.osgi.framework.Constants;
47import org.osgi.framework.Filter;
48import org.osgi.framework.InvalidSyntaxException;
49import org.osgi.framework.ServiceEvent;
50import org.osgi.framework.ServiceListener;
51import org.osgi.framework.ServiceReference;
52import org.osgi.framework.ServiceRegistration;
53import org.osgi.service.upnp.UPnPDevice;
54import org.osgi.service.upnp.UPnPEventListener;
55import org.osgi.service.upnp.UPnPService;
56import org.osgi.service.upnp.UPnPStateVariable;
57
58import org.apache.felix.upnp.basedriver.Activator;
59import org.apache.felix.upnp.basedriver.importer.core.event.message.FirstMessage;
60import org.apache.felix.upnp.basedriver.importer.core.event.message.ListenerModified;
61import org.apache.felix.upnp.basedriver.importer.core.event.message.ListenerUnRegistration;
62import org.apache.felix.upnp.basedriver.importer.core.event.message.StateChanged;
63import org.apache.felix.upnp.basedriver.importer.core.event.structs.NotifierQueue;
64import org.apache.felix.upnp.basedriver.importer.core.event.structs.SubscriptionQueue;
65import org.apache.felix.upnp.basedriver.importer.core.upnp.UPnPDeviceImpl;
66import org.apache.felix.upnp.basedriver.importer.core.upnp.UPnPServiceImpl;
Francesco Furfarid8bdb642006-04-04 23:33:40 +000067import org.apache.felix.upnp.basedriver.importer.util.ParseUSN;
68import org.apache.felix.upnp.extra.util.Converter;
69
Francesco Furfarif2a67912006-07-17 17:08:02 +000070/*
71* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
72*/
Francesco Furfarid8bdb642006-04-04 23:33:40 +000073public class MyCtrlPoint extends ControlPoint
74 implements
75 NotifyListener,
76 SearchResponseListener,
77 ServiceListener
78{
79 private BundleContext context;
80 private Hashtable devices;//key UDN value OsgideviceInfo(Osgi)
81 private SubscriptionQueue subQueue;
82 private NotifierQueue notifierQueue;
83
84 private final String UPNP_EVENT_LISTENER_FLTR =
85 "(" + Constants.OBJECTCLASS + "=" + UPnPEventListener.class.getName() + ")";
86 private final String UPNP_DEVICE_FLTR =
87 "(" + Constants.OBJECTCLASS + "=" + UPnPDevice.class.getName() + ")";
88 private final String EXPORT_FLTR =
89 "(" + UPnPDevice.UPNP_EXPORT + "=*" + ")";
90 private final String IMPORT_FLTR =
91 "(" + org.apache.felix.upnp.extra.util.Constants.UPNP_IMPORT + "=*" + ")";
92
93
94 public MyCtrlPoint(BundleContext context, SubscriptionQueue subQueue,
95 NotifierQueue notifierQueue) {
96 super();
97 this.context = context;
98 devices = new Hashtable();
99 addNotifyListener(this);
100 addSearchResponseListener(this);
101 try {
102 context.addServiceListener(this, UPNP_EVENT_LISTENER_FLTR);
103 } catch (InvalidSyntaxException e) {
104 e.printStackTrace();
105 }
106 this.subQueue = subQueue;
107 this.notifierQueue = notifierQueue;
108 }
109
110 public void httpRequestRecieved(HTTPRequest httpReq) {
111 Activator.logger.DEBUG("[Importer] httpRequestRecieved event");
112 Activator.logger.PACKET(httpReq.toString());
113
114 if (httpReq.isNotifyRequest() == true) {
115 Activator.logger.DEBUG("[Importer] Notify Request");
116 NotifyRequest notifyReq = new NotifyRequest(httpReq);
117 String uuid = notifyReq.getSID();
118 long seq = notifyReq.getSEQ();
119 PropertyList props = notifyReq.getPropertyList();
120// int propCnt = props.size();
121// Hashtable hash = new Hashtable();
122// for (int n = 0; n < propCnt; n++) {
123// Property prop = props.getProperty(n);
124// String varName = prop.getName();
125// String varValue = prop.getValue();
126// hash.put(varName, varValue);
127// }
128 newEventArrived(uuid, seq, props);
129 httpReq.returnOK();
130 return;
131 }
132
133 Activator.logger.DEBUG("BAD Request");
134 httpReq.returnBadRequest();
135
136 }
137
138
139 /*
140 * (non-Javadoc)
141 *
142 * @see org.cybergarage.upnp.ControlPoint#removeExpiredDevices()
143 *
144 */
145 public void removeExpiredDevices() {
146 DeviceList devList = getDeviceList();
147 int devCnt = devList.size();
148 for (int n = 0; n < devCnt; n++) {
149 Device dev = devList.getDevice(n);
150 if (dev.isExpired() == true) {
151 Activator.logger.DEBUG("[Importer] Expired device:"+ dev.getFriendlyName());
152 removeDevice(dev);
153 removeOSGiExpireDevice(dev);
154 }
155 }
156 }
157
158 /*
159 * (non-Javadoc)
160 *
161 * @see org.cybergarage.upnp.device.NotifyListener#deviceNotifyReceived(org.cybergarage.upnp.ssdp.SSDPPacket)
162 */
163 public void deviceNotifyReceived(SSDPPacket ssdpPacket) {
164 Activator.logger.DEBUG("[Importer] deviceNotifyReceived");
165 Activator.logger.PACKET(ssdpPacket.toString());
166 /*
Francesco Furfarid8bdb642006-04-04 23:33:40 +0000167 * if the packet is
168 * NOTIFY or ISALIVE or *new* ROOT then create and register the UPnPDevice and
169 * all the embeeded device too
170 * DEVICE or SERVICE then if they already exist in OSGi do nothing otherwise I'll create and
171 * register all the UPnPDevice need starting from the root device
172 * *root* BYEBYE then I'll unregister it and all its children from OSGi Framework
173 * *service* BYEBYE then I'll re-register the UPnPDevice that contain the service with the updated
174 * properties
175 * *device* BYEBYE then I'll re-register the UPnPDevice that contain the device with the updated
176 * properties and also unregister the UPnPDevice that has left
177 */
178 String usn = ssdpPacket.getUSN();
179 ParseUSN parseUSN = new ParseUSN(usn);
180 String udn = parseUSN.getUDN();
181
182 ServiceReference[] refs = null;
183 String filter = "(&" + UPNP_DEVICE_FLTR + EXPORT_FLTR+ ")";
184 try {
185 refs = context.getServiceReferences(UPnPDevice.class.getName(), filter);
186 } catch (InvalidSyntaxException e) {
187 e.printStackTrace();
188 }
189 if (refs != null) {
190 for (int i = 0; i < refs.length; i++) {
191 UPnPDevice dev = (UPnPDevice) context.getService(refs[i]);
192 Dictionary dic = dev.getDescriptions(null);
193 if (((String) dic.get(UPnPDevice.UDN)).equals(udn)) {
194 return;
195 }
196 }
197 }
198
199 if (ssdpPacket.isAlive()) {
200
201 Activator.logger.DEBUG("[Importer] ssdpPacket.isAlive");
202 if (devices.containsKey(udn)) {
203 Activator.logger.DEBUG("[Importer] Device already discovered");
204 if (parseUSN.isService()) {
205 doServiceUpdating(udn,parseUSN.getServiceType());
206 }
207 } else {
208 doDeviceRegistration(udn);
209 }
210
211 } else if (ssdpPacket.isByeBye()) {
212 Activator.logger.DEBUG("[Importer] ssdpPacket.isByeBye");
213
214 if (devices.containsKey(udn)) {
215 if (parseUSN.isDevice()) {
216 Activator.logger.DEBUG("[Importer] parseUSN.isDevice ...unregistering all the children devices ");
217
218 //unregistering all the children devices
219 UPnPDeviceImpl dev = ((OSGiDeviceInfo) devices.get(udn)).getOSGiDevice();
220 removeOSGiandUPnPDeviceHierarchy(dev);
221
222 } else if (parseUSN.isService()) {
223 Activator.logger.DEBUG("[Importer] parseUSN.isService ...registering modified device again ");
224 /*
225 * I have to unregister the UPnPDevice and register it again
226 * with the updated properties
227 */
228 UPnPDeviceImpl device =
229 ((OSGiDeviceInfo) devices.get(udn)).getOSGiDevice();
230 ServiceRegistration registar =
231 ((OSGiDeviceInfo) devices.get(udn)).getRegistration();
232 String[] oldServicesID =
233 (String[]) (device.getDescriptions(null).get(UPnPService.ID));
234 String[] oldServiceType =
235 (String[]) (device.getDescriptions(null).get(UPnPService.TYPE));
236
237 Device cyberDevice = findDeviceCtrl(this, udn);
238 Vector vec = new Vector();
239 for (int i = 0; i < oldServiceType.length; i++) {
240 Service ser = cyberDevice.getService(oldServicesID[i]);
241 if (!(ser.getServiceType().equals(parseUSN.getServiceType())))
242 {
243 vec.add(oldServicesID[i]);
244 }
245 }
246
247 //new serviceID
248 String[] actualServicesID = new String[vec.size()];
249 actualServicesID = (String[]) vec.toArray(new String[]{});
250
251 //new serviceType
252 String[] actualServiceType = new String[oldServiceType.length - 1];
253 vec.clear();
254 for (int i = 0; i < oldServiceType.length; i++) {
255 if (!(oldServiceType[i].equals(parseUSN.getServiceType())))
256 {
257 vec.add(oldServiceType[i]);
258 }
259 }
260 actualServiceType = (String[]) vec.toArray(new String[]{});
261
262 //unrigistering and registering again with the new properties
263 unregisterUPnPDevice(registar);
264 device.setProperty(UPnPService.ID, actualServicesID);
265 device.setProperty(UPnPService.TYPE, actualServiceType);
266 registerUPnPDevice(null, device, device.getDescriptions(null));
267 searchForListener(cyberDevice);
268 }
269 }
270 } else {
271 /*
272 * if it is a service means that it is beend delete when the
273 * owner was unregister so I can skip this bye-bye
274 */
275 }
276 }
277
278 public synchronized void removeOSGiandUPnPDeviceHierarchy(UPnPDeviceImpl dev)
279 {
280 /*
281 * remove all the UPnPDevice from the struct of local device recursively
282 */
283 String[] childrenUDN = (String[]) dev.getDescriptions(null).get(
284 UPnPDevice.CHILDREN_UDN);
285 if (childrenUDN == null) {
Francesco Furfarid8bdb642006-04-04 23:33:40 +0000286 //no children
287 unregisterUPnPDevice(((OSGiDeviceInfo) devices.get(dev
288 .getDescriptions(null).get(UPnPDevice.UDN)))
289 .getRegistration());
290 devices.remove(dev.getDescriptions(null).get(UPnPDevice.UDN));
291 return;
292 }
293 for (int i = 0; i < childrenUDN.length; i++) {
294 if (devices.get(childrenUDN[i]) == null) {
295 continue;
296 } else {
297 removeOSGiandUPnPDeviceHierarchy(((OSGiDeviceInfo) devices
298 .get(childrenUDN[i])).getOSGiDevice());
299 }
300 }
301 unregisterUPnPDevice(((OSGiDeviceInfo) devices.get(dev.getDescriptions(
302 null).get(UPnPDevice.UDN))).getRegistration());
303 devices.remove(dev.getDescriptions(null).get(UPnPDevice.UDN));
304 }
305
306 public synchronized void removeOSGiExpireDevice(Device dev) {
307 /*
308 * unregistering root device with all its children device from OSGi
309 * deleting root device and all its children from struct that conatin
310 * a list of local device
311 */
312 removeOSGiandUPnPDeviceHierarchy(((OSGiDeviceInfo) devices.get(dev
313 .getUDN())).getOSGiDevice());
314 }
315
316 public void registerUPnPDevice(Device dev, UPnPDeviceImpl upnpDev,
317 Dictionary prop) {
318 /*
319 * registering the new Device as OSGi UPnPDevice and then add
320 * ServiceRegistration and UPnPDevice reference to the hashtable
321 * that contains local devices
322 */
323 if (prop == null && upnpDev == null) {
324 UPnPDeviceImpl newDevice = new UPnPDeviceImpl(dev, context);
325 ServiceRegistration registration =
326 context.registerService(UPnPDevice.class.getName(),
327 newDevice,
328 newDevice.getDescriptions(null));
329 OSGiDeviceInfo deviceInfo =
330 new OSGiDeviceInfo(newDevice,registration);
331
332 String udn = (String) ((newDevice.getDescriptions(null)).get(UPnPDevice.UDN));
333 devices.put(udn, deviceInfo);
334 } else {
335 ServiceRegistration registration =
336 context.registerService(UPnPDevice.class.getName(), upnpDev, prop);
337 OSGiDeviceInfo deviceInfo =
338 new OSGiDeviceInfo(upnpDev, registration);
339 devices.put(upnpDev.getDescriptions(null).get(UPnPDevice.UDN),deviceInfo);
340 }
341 }
342
343
Francesco Furfarid8bdb642006-04-04 23:33:40 +0000344 public void unregisterUPnPDevice(ServiceRegistration registration) {
345 registration.unregister();
346
347 }
348
349 public Device findDeviceCtrl(ControlPoint ctrl, String udn) {
350 /*
351 * this return the device looking in all the struct
352 */
353
354 DeviceList devList = getDeviceList();
355 Device dev = null;
356 int i = 0;
357 while (i < devList.size() && (dev == null)) {
358 if (devList.getDevice(i).getUDN().equals(udn)) {
359 dev = devList.getDevice(i);
360 return dev;
361 }
362 dev = findDevice(udn, devList.getDevice(i));
363 i++;
364 }
365 return dev;
366 }
367
368 public Device findDevice(String udn, Device dev) {
369 /*
370 * look for the device if it exist, starting from the root on
371 * cyberlink struct
372 */
373 DeviceList devList = dev.getDeviceList();
374 Device aux = null;
375 for (int i = 0; i < devList.size(); i++) {
376 if (devList.getDevice(i).getUDN().equals(udn)) {
377 return devList.getDevice(i);
378 } else {
379 if((aux = findDevice(udn, devList.getDevice(i))) != null)
380 return aux;
381 }
382 }
383 return null;
384 }
385
386 /*
387 * (non-Javadoc)
388 *
389 * @see org.cybergarage.upnp.device.SearchResponseListener#deviceSearchResponseReceived(org.cybergarage.upnp.ssdp.SSDPPacket)
390 */
391 public void deviceSearchResponseReceived(SSDPPacket ssdpPacket) {
392 Activator.logger.DEBUG("[Importer] deviceSearchResponseReceived");
393 Activator.logger.PACKET(ssdpPacket.toString());
394
395 String usn = ssdpPacket.getUSN();
396 ParseUSN parseUSN = new ParseUSN(usn);
397 String udn = parseUSN.getUDN();
398
399 ServiceReference[] refs = null;
400
401 String filter = "(&" + UPNP_DEVICE_FLTR + EXPORT_FLTR + ")";
402
403 try {
404 refs = context.getServiceReferences(UPnPDevice.class.getName(),
405 filter);
406 } catch (InvalidSyntaxException e) {
407 e.printStackTrace();
408 }
409
410 if (refs != null) {
411 for (int i = 0; i < refs.length; i++) {
412 UPnPDevice dev = (UPnPDevice) context.getService(refs[i]);
413 Dictionary dic = dev.getDescriptions(null);
414 if (((String) dic.get(UPnPDevice.UDN)).equals(udn)) {
415 return;
416 }
417 }
418 }
419
420 if (devices.containsKey(udn)) {
421 Activator.logger.DEBUG("[Importer] Device already discovered");
422 /*
423 * Exist the registered device either in OSGi and
424 * hashtable of local device
425 */
426 if (parseUSN.isService()) {
427 doServiceUpdating(udn,parseUSN.getServiceType());
428 }
429 } else {
430 doDeviceRegistration(udn);
431 }
432
433 }
434 /*
435 * (non-Javadoc)
436 *
437 * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent)
438 */
439 public void serviceChanged(ServiceEvent event) {
440 Activator.logger.DEBUG("[Importer] serviceChanged");
441 Activator.logger.DEBUG("Event::"+event.toString());
442
443 if (event.getType() == ServiceEvent.REGISTERED) {
444 /* check new listener registration */
445 ServiceReference serRef = event.getServiceReference();
446 Object obj = serRef.getProperty(UPnPEventListener.UPNP_FILTER);
447 /* obtain interested devices for the listener */
448 ServiceReference[] devicesRefs = null;
449 if (obj != null) {
450 Filter filter = (Filter) obj;
451 String filtra = filter.toString();
452 /*
453 * Avoid to implement the notification for device
454 * that are not been created by BaseDriver
455 */
456 String newfilter = "(&" + filtra + IMPORT_FLTR + ")";
457 //String newfilter = "(&" + filtra + "(!" + EXPORT_FLTR + ")" + ")";
458 //System.out.println(newfilter);
459 try {
460 devicesRefs = context.getServiceReferences(UPnPDevice.class
461 .getName(), newfilter);
462 } catch (InvalidSyntaxException e) {
463 e.printStackTrace();
464 }
465
466 if (devicesRefs != null) {/*
Francesco Furfarid8bdb642006-04-04 23:33:40 +0000467 *
468 * only if there is a compatibile device
469 */
Francesco Furfaria4e09972006-11-05 02:12:29 +0000470 Dictionary dic = new Hashtable();
Francesco Furfarid8bdb642006-04-04 23:33:40 +0000471 for (int i = 0; i < devicesRefs.length; i++) {
472 UPnPDevice device = (UPnPDevice) context.getService(devicesRefs[i]);
473 dic.put(UPnPDevice.ID, device.getDescriptions(null).get(UPnPDevice.UDN));
474 dic.put(UPnPDevice.TYPE, device.getDescriptions(null).get(UPnPDevice.TYPE));
475 UPnPService[] services = device.getServices();
Francesco Furfarid8bdb642006-04-04 23:33:40 +0000476 //TODO do I have to do the unget of UPnPDevice??
477 if (services != null) {
478 for (int j = 0; j < services.length; j++) {
479 dic.put(UPnPService.ID, services[j].getId());
480 dic.put(UPnPService.TYPE, services[j].getType());
481 //TODO add method boolean serviceEvented() so we can remove the below cycle
482 UPnPStateVariable[] stateVars = services[j].getStateVariables();
483 boolean hasEventedVars = false;
484 for (int k = 0; k < stateVars.length && ! hasEventedVars; k++) {
485 hasEventedVars = stateVars[k].sendsEvents();
486 if (hasEventedVars) {
487 if(filter.match(dic)){
488 UPnPEventListener listener =
489 (UPnPEventListener) context.getService(serRef);
490 FirstMessage msg = new FirstMessage(
491 ((UPnPServiceImpl) services[j]).getCyberService(),
492 listener);
493 subQueue.enqueue(msg);
494 }
495 }
496 }
497 }
498 }
499 }
500 }
501 } else {/* obj==null (interested in all devices) */
502 try {
Francesco Furfarif9aba132006-06-02 18:25:02 +0000503 String newfilter = "(!" + EXPORT_FLTR+ ")";
Francesco Furfarid8bdb642006-04-04 23:33:40 +0000504 devicesRefs = context.getServiceReferences(UPnPDevice.class.getName(), newfilter);
505 } catch (InvalidSyntaxException e) {
506 e.printStackTrace();
507 }
508 if (devicesRefs != null) {/*
Francesco Furfarid8bdb642006-04-04 23:33:40 +0000509 *
510 * only if there is a device
511 */
512
513 for (int i = 0; i < devicesRefs.length; i++) {
514 UPnPDevice device = (UPnPDevice) context
515 .getService(devicesRefs[i]);
516 UPnPService[] services = device.getServices();
Francesco Furfarid8bdb642006-04-04 23:33:40 +0000517 //do I have to do the unget of UPnPDevice??
518 if (services != null) {
519 for (int j = 0; j < services.length; j++) {
520 UPnPStateVariable[] stateVars = services[j]
521 .getStateVariables();
522 boolean bool = false;
523 for (int k = 0; k < stateVars.length; k++) {
524 bool = stateVars[k].sendsEvents();
525 if (bool) {
526 break;
527 }
528 }
529 if (bool) {
530 UPnPEventListener listener =
531 (UPnPEventListener) context.getService(serRef);
532 FirstMessage msg = new FirstMessage(
533 ((UPnPServiceImpl) services[j]).getCyberService(),
534 listener);
535 subQueue.enqueue(msg);
536 }
537 }
538 }
539 }
540 }
541 }
542
543 } else if (event.getType() == ServiceEvent.MODIFIED) {
544 Vector newServices = new Vector();
545 ServiceReference serRef = event.getServiceReference();
546 Filter filter = (Filter) serRef.getProperty(UPnPEventListener.UPNP_FILTER);
547 UPnPEventListener listener = (UPnPEventListener) context.getService(serRef);
548 ServiceReference[] devicesRefs = null;
549
550 if (filter != null) {
551 try {
552 String filtra = filter.toString();
553 String newfilter = "(&" + filtra + "(!" + EXPORT_FLTR + ")" + ")";
554 devicesRefs = context.getServiceReferences(UPnPDevice.class.getName(), newfilter);
555 } catch (InvalidSyntaxException e) {
556 e.printStackTrace();
557 }
558 if (devicesRefs != null) {/*
Francesco Furfarid8bdb642006-04-04 23:33:40 +0000559 *
560 * only if there is a compatibile device
561 */
Francesco Furfaria4e09972006-11-05 02:12:29 +0000562 Dictionary dic = new Hashtable();
Francesco Furfarid8bdb642006-04-04 23:33:40 +0000563 /*
Francesco Furfarid8bdb642006-04-04 23:33:40 +0000564 * look for the service that match
565 */
566 for (int i = 0; i < devicesRefs.length; i++) {
567 UPnPDevice device = (UPnPDevice) context
568 .getService(devicesRefs[i]);
569 dic.put(UPnPDevice.ID, device.getDescriptions(null)
570 .get(UPnPDevice.UDN));
571 dic.put(UPnPDevice.TYPE, device.getDescriptions(null)
572 .get(UPnPDevice.TYPE));
573 UPnPService[] services = device.getServices();
574
Francesco Furfarid8bdb642006-04-04 23:33:40 +0000575 //do I have to do the unget of UPnPDevice??
576 if (services != null) {
577 for (int j = 0; j < services.length; j++) {
578 dic.put(UPnPService.ID, services[j].getId());
Francesco Furfaria4e09972006-11-05 02:12:29 +0000579 dic.put(UPnPService.TYPE, services[j].getType());
Francesco Furfarid8bdb642006-04-04 23:33:40 +0000580
581 UPnPStateVariable[] stateVars = services[j]
582 .getStateVariables();
583 boolean hasEventedVars = false;
584 for (int k = 0; k < stateVars.length; k++) {
585 hasEventedVars = stateVars[k].sendsEvents();
586 if (hasEventedVars) {
587 break;
588 }
589 }
590 if (!hasEventedVars) {
591 continue;
592 }
593
594 boolean bool = filter.match(dic);
595 if (bool) {
596 newServices
597 .add(((UPnPServiceImpl) services[j])
598 .getCyberService());
599 }
600 }//for services
601 }//services ==null
602 }//for devicesRefs
603 ListenerModified msg = new ListenerModified(newServices,
604 listener);
605 subQueue.enqueue(msg);
606 }//devicesrefs !=null
607 } else {//interrested in all devices
608 try {
609
610 String newfilter = "(!(" + UPnPDevice.UPNP_EXPORT + "=*"
611 + ")" + ")";
612 devicesRefs = context.getServiceReferences(UPnPDevice.class
613 .getName(), newfilter);
614 } catch (InvalidSyntaxException e) {
615 e.printStackTrace();
616 }
617 if (devicesRefs != null) {/*
Francesco Furfarid8bdb642006-04-04 23:33:40 +0000618 * only if there is a device
619 */
620
621 for (int i = 0; i < devicesRefs.length; i++) {
622 UPnPDevice device = (UPnPDevice) context
623 .getService(devicesRefs[i]);
624 UPnPService[] services = device.getServices();
Francesco Furfarid8bdb642006-04-04 23:33:40 +0000625 //do I have to do the unget of UPnPDevice??
626 if (services != null) {
627 for (int j = 0; j < services.length; j++) {
628 UPnPStateVariable[] stateVars = services[j]
629 .getStateVariables();
630 boolean hasEventedVars = false;
631 for (int k = 0; k < stateVars.length; k++) {
632 hasEventedVars = stateVars[k].sendsEvents();
633 if (hasEventedVars) {
634 break;
635 }
636 }
637 if (hasEventedVars) {
638 newServices
639 .add(((UPnPServiceImpl) services[j])
640 .getCyberService());
641 }//hasEventedvars
642 }//for services
643 }//services !=null
644 }//for devicesRefs
645 subQueue
646 .enqueue(new ListenerModified(newServices, listener));
647 }//devicesRefs !=null
648
649 }
650
651 } else if (event.getType() == ServiceEvent.UNREGISTERING) {
652 UPnPEventListener listener = (UPnPEventListener) context
653 .getService(event.getServiceReference());
654 if (listener != null) {
655 ListenerUnRegistration msg = new ListenerUnRegistration(
656 listener);
657 subQueue.enqueue(msg);
658 }
659 context.ungetService(event.getServiceReference());
660 }
661 } /*
662 * (non-Javadoc)
663 *
664 * @see org.cybergarage.upnp.event.EventListener#eventNotifyReceived(java.lang.String,
665 * long, java.lang.String, java.lang.String)
666 */
667 /*
668 * public void eventNotifyReceived(String uuid, long seq, String varName,
669 * String value) { // TODO Auto-generated method stub StateChanged msg = new
670 * StateChanged(uuid, varName, value,seq);,serviceFromSid(uuid)
671 * notifierQueue.enqueue(msg); }
672 */
673
674 public Service serviceFromSid(String sid) {
675 Enumeration e = devices.elements();
676 Service cyberService = null;
677 while (e.hasMoreElements()) {
678 OSGiDeviceInfo deviceinfo = (OSGiDeviceInfo) e.nextElement();
679 UPnPDevice device = deviceinfo.getOSGiDevice();
680 UPnPService[] services = (UPnPService[]) device.getServices();
681 UPnPServiceImpl[] servicesImpl = new UPnPServiceImpl[services.length];
682 for (int i = 0; i < servicesImpl.length; i++) {
683 servicesImpl[i] = (UPnPServiceImpl) services[i];
684 }
685 for (int i = 0; i < servicesImpl.length; i++) {
686 cyberService = servicesImpl[i].getCyberService();
687 boolean bool = cyberService.isSubscribed();
688 if (bool) {
689 if (cyberService.getSID().equals(sid)) {
690 return cyberService;
691 }
692 }
693 }
694 }
695 return null;
696 }
697
698 /*
699 * (non-Javadoc)
700 *
701 * @see org.apache.felix.upnpbase.importer.MyEventListener#newEventArrived(java.lang.String,
702 * long, java.util.Dictionary)
703 */
704 public void newEventArrived(String uuid, long seq, PropertyList props) {
705 Activator.logger.DEBUG("[Importer] newEventArrived");
706 Service service = serviceFromSid(uuid);
707 if (service != null) {
708 int size = props.size();
709 Hashtable hash = new Hashtable();
710 for (int i = 0; i < size; i++) {
711 Property prop = props.getProperty(i);
712 String varName = prop.getName();
713 String varValue = prop.getValue();
714 String upnpType = service.getStateVariable(varName).getDataType();
715 Object valueObj;
716 try {
717 valueObj = Converter.parseString(varValue,upnpType);
718 } catch (Exception e) {
719 Activator.logger.ERROR("[Importer] Bad data value in Notify event: "
720 +"var name="+varName +" value="+varValue +" type="+upnpType + "\n"+e);
721 return;
722 }
723 hash.put(varName, valueObj);
724 }
725
726 Device device = service.getDevice();
727 StateChanged msg = new StateChanged(uuid, seq, hash, device, service);
728 notifierQueue.enqueue(msg);
729 }
730 }
731
732 public void doServiceUpdating(String udn,String serviceType){
733 Activator.logger.DEBUG("[Importer] check for service updating");
734 OSGiDeviceInfo deviceinfo = (OSGiDeviceInfo) devices.get(udn);
735 UPnPDeviceImpl device = deviceinfo.getOSGiDevice();
736 boolean isSerPresent = device.existServiceType(serviceType);
737 if (!isSerPresent) {
738 /*
739 * The serivice doesn't exist so it's new.
740 * Find the udn of owner device and re-register the owner
741 */
742 ServiceRegistration registar =
743 ((OSGiDeviceInfo) devices.remove(udn)).getRegistration();
744 String[] oldServicesID =
745 (String[]) device.getDescriptions(null).get(UPnPServiceImpl.ID);
746 String[] oldServicesType =
747 (String[]) device.getDescriptions(null).get(UPnPServiceImpl.TYPE);
748
Francesco Furfarid8bdb642006-04-04 23:33:40 +0000749 //to handle multiple instance of a serivice of the same type
750 Device cyberDevice = findDeviceCtrl(this, udn);
751 ServiceList serviceList = cyberDevice.getServiceList();
752 ArrayList newServicesID = new ArrayList();
753
754 for (int i = 0; i < serviceList.size(); i++) {
755 if (serviceList.getService(i).getServiceType()
756 .equals(serviceType))
757 {
758 newServicesID.add(serviceList.getService(i).getServiceID());
759 }
760 }
761
762 //adding the new servicesID
763 String[] currentServicesID =
764 new String[(oldServicesID.length + newServicesID.size())];
765 int endOld = 1;
766 for (int i = 0; i < oldServicesID.length; i++) {
767 currentServicesID[i] = oldServicesID[i];
768 endOld++;
769 }
770 int j = 0;
771 for (; endOld < currentServicesID.length; endOld++) {
772 currentServicesID[endOld] = (String) newServicesID.get(j);
773 j++;
774 }
775
776 //adding the new ServiceType
777 String[] currentServicesType = new String[oldServicesType.length + 1];
778 for (int i = 0; i < oldServicesType.length; i++) {
779 currentServicesType[i] = oldServicesType[i];
780 }
781 currentServicesType[currentServicesType.length - 1] = serviceType;
782
783
784 // unregistring the OSGi Device
785 // and setting new properties
786 unregisterUPnPDevice(registar);
787 device.setProperty(UPnPService.ID, currentServicesID);
788 device.setProperty(UPnPServiceImpl.TYPE,currentServicesType);
789
790 //registering the service with the updated properties
791 registerUPnPDevice(null, device, device.getDescriptions(null));
792 searchForListener(cyberDevice);
793 }
794 }
795
796 public void doDeviceRegistration(String udn,boolean checkDouble){
797 if(checkDouble){
798 try {
799 ServiceReference[] refs =
800 Activator.bc.getServiceReferences(
801 UPnPDevice.class.getName(),
802 "(" + UPnPDevice.UDN + "=" + udn + ")"
803 );
804 if(refs!=null)
805 return;
806 } catch (InvalidSyntaxException ignored) {
807 }
808 }
809 doDeviceRegistration(udn);
810 }
811
812 public void doDeviceRegistration(String udn){
813 /*
814 * registering the new device even if it is new root device or
815 * a new embedded device
816 */
817 Device dev = findDeviceCtrl(this, udn);
818 if (dev == null) {
819 Activator.logger.WARNING("Cyberlink notified packet from UDN:" +udn+ ", but Device instance doesn't exist in Cyberlink structs !");
820 }
821 if (dev != null) {
822 Activator.logger.INFO("[Importer] registering UPnPDevice UDN:"+dev.getFriendlyName());
823 registerUPnPDevice(dev, null, null);
824 searchForListener(dev);
825 /*
826 * now we can register all the device embedded device and service without
827 * recieving the NOTIFY
828 */
829 //XXX Think about this choice
830 for (Iterator i = dev.getDeviceList().iterator(); i.hasNext();) {
831 Device d = (Device) i.next();
832 doDeviceRegistration(d.getUDN(),true);
833 }
834 }
835 }
836
837 public void searchForListener(Device device) {
838 Activator.logger.DEBUG("[Importer] searching for UPnPEventListener");
839 ServiceReference[] listeners = null;
840 try {
841 listeners = context.getServiceReferences(UPnPEventListener.class.getName(), null);
842 } catch (InvalidSyntaxException e) {
843 // TODO Auto-generated catch block
844 e.printStackTrace();
845 }
846 if (listeners != null) {
847 String deviceID = device.getUDN();
848 String serviceID;
849 String deviceType = device.getDeviceType();
850 String serviceType;
851 Hashtable hash = new Hashtable();
852 hash.put(UPnPDevice.ID, deviceID);
853 hash.put(UPnPDevice.TYPE, deviceType);
854 ServiceList services = device.getServiceList();
855 Vector eventedSers = new Vector();
856
857 for (int i = 0; i < services.size(); i++) {
858 Service service = (Service) services.elementAt(i);
859 ServiceStateTable vars = service.getServiceStateTable();
860 for (int j = 0; j < vars.size(); j++) {
861 StateVariable var = (StateVariable) vars.elementAt(j);
862 if (var.isSendEvents()) {
863 eventedSers.add(service);
864 break;
865 }
866 }
867 }
868
869 for (int i = 0; i < listeners.length; i++) {
870 UPnPEventListener listener = (UPnPEventListener) context
871 .getService(listeners[i]);
872 Filter filter = (Filter) listeners[i]
873 .getProperty(UPnPEventListener.UPNP_FILTER);
874 if (filter == null) {
875 for (int j = 0; j < eventedSers.size(); j++) {
876 Service ser = (Service) eventedSers.elementAt(j);
877 subQueue.enqueue(new FirstMessage(ser, listener));
878 }
879 } else {
880 for (int j = 0; j < eventedSers.size(); j++) {
881 Service ser = (Service) eventedSers.elementAt(j);
882 serviceID = ser.getServiceID();
883 serviceType = ser.getServiceType();
884 hash.put(UPnPService.ID, serviceID);
885 hash.put(UPnPService.TYPE, serviceType);
886 boolean bool = filter.match(hash);
887 if (bool) {
888 subQueue.enqueue(new FirstMessage(ser, listener));
889 }
890
891 }
892 }
893
894 }
895
896 }
897 }
898}