| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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.basedriver.export; |
| |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Iterator; |
| |
| import org.osgi.framework.Constants; |
| import org.osgi.framework.InvalidSyntaxException; |
| import org.osgi.framework.ServiceEvent; |
| import org.osgi.framework.ServiceListener; |
| import org.osgi.framework.ServiceReference; |
| import org.osgi.service.upnp.UPnPDevice; |
| |
| import org.apache.felix.upnp.basedriver.Activator; |
| |
| /* |
| * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a> |
| */ |
| public class RootDeviceListener implements ServiceListener { |
| |
| private RootDeviceExportingQueue queue; |
| |
| private ArrayList devices; |
| |
| public RootDeviceListener(RootDeviceExportingQueue queue) { |
| this.queue = queue; |
| devices = new ArrayList(); |
| } |
| |
| public synchronized void addDevice(ServiceReference sr) { |
| DeviceNode node = new DeviceNode(sr); |
| |
| if(node.isRoot() && node.isLeaf()){ |
| //Obiovsly |
| queue.addRootDevice(node); |
| return; |
| } |
| |
| if(!node.isLeaf()){ |
| //I look if there is some partial tree that is child |
| //of my new node. This operation may complete the tree |
| Iterator list = devices.iterator(); |
| DeviceNode handle = null; |
| while(list.hasNext()){ |
| DeviceNode tree = (DeviceNode) list.next(); |
| if((handle = node.isAttachable(tree)) != null){ |
| handle.attach(tree); |
| list.remove(); |
| if(node.isRoot() && node.isComplete()){ |
| queue.addRootDevice(node); |
| return; |
| } |
| } |
| } |
| } |
| |
| if(!node.isRoot()){ |
| //I look if there is some partial tree that should own |
| //my new node. This operation may complete the tree |
| Iterator list = devices.iterator(); |
| DeviceNode handle = null; |
| while(list.hasNext()){ |
| DeviceNode tree = (DeviceNode) list.next(); |
| if((handle = tree.isAttachable(node)) != null){ |
| handle.attach(node); |
| if(tree.isRoot() && tree.isComplete()){ |
| list.remove(); |
| queue.addRootDevice(tree); |
| } |
| return; |
| } |
| } |
| } |
| |
| devices.add(node); |
| |
| } |
| |
| /** |
| * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent) |
| */ |
| public void serviceChanged(ServiceEvent e) { |
| switch (e.getType()) { |
| case ServiceEvent.REGISTERED: { |
| addDevice(e.getServiceReference()); |
| }break; |
| |
| case ServiceEvent.MODIFIED: |
| break; |
| |
| case ServiceEvent.UNREGISTERING: { |
| removeDevice(e.getServiceReference()); |
| }break; |
| } |
| } |
| |
| /** |
| * @param serviceReference |
| */ |
| public synchronized void removeDevice(ServiceReference sr) { |
| String udn = (String) sr.getProperty(UPnPDevice.UDN); |
| DeviceNode removeNode = null; |
| /* |
| * I look in the queue of complete device that will be exported |
| */ |
| |
| DeviceNode root=this.queue.removeRootDevice(udn); |
| if(root!=null) removeNode=root.dethatch(udn); |
| |
| /* |
| * I look in the list that conatin unqueue,so no-complete Device |
| */ |
| Iterator i = this.devices.iterator(); |
| while (i.hasNext()) { |
| root = (DeviceNode) i.next(); |
| removeNode = root.dethatch(udn); |
| } |
| |
| /* |
| * if I found the device removeNode != null |
| */ |
| if(removeNode==null) return; |
| /* |
| * I get all the already attached subdevice and add to |
| * unttached device list |
| */ |
| Collection c=removeNode.getChildren(); |
| if(c==null) return; |
| this.devices.addAll(c); |
| } |
| |
| /** |
| * Register this object to listen to all "well registered" UPnPDevice <br> |
| * that should be Exported <br> |
| * And look for all the already registered UPnPDevice to be exported |
| * |
| */ |
| public void activate() { |
| /* |
| * I listen for the UPnPDevice service that are Root that should be |
| * exported to UPnP Network. |
| * |
| * Please Note: The following filter disable listining for bad registerd |
| * UPnPDevice |
| */ |
| try { |
| Activator.bc.addServiceListener(this, |
| "(&" + |
| "(" + Constants.OBJECTCLASS + "=" + UPnPDevice.class.getName() + ")" + |
| "(" + UPnPDevice.UPNP_EXPORT + "=*)" + |
| "(DEVICE_CATEGORY=UPnP)" + |
| "(" + UPnPDevice.UDN + "=*)" + |
| "(" + UPnPDevice.FRIENDLY_NAME + "=*)" + |
| "(" + UPnPDevice.MANUFACTURER + "=*)" + |
| "(" + UPnPDevice.MODEL_NAME + "=*)" + |
| "(" + UPnPDevice.TYPE + "=*)" + |
| ")"); |
| } catch (InvalidSyntaxException e) { |
| e.printStackTrace(); |
| } |
| ServiceReference[] roots = null; |
| try { |
| roots = Activator.bc.getServiceReferences(UPnPDevice.class.getName(), |
| "(&" + "(" + UPnPDevice.UPNP_EXPORT + "=*)" + |
| "(DEVICE_CATEGORY=UPnP)" + |
| "(" + UPnPDevice.UDN + "=*)" + |
| "(" + UPnPDevice.FRIENDLY_NAME + "=*)" + |
| "(" + UPnPDevice.MANUFACTURER + "=*)" + |
| "(" + UPnPDevice.MODEL_NAME + "=*)" + |
| "(" + UPnPDevice.TYPE + "=*)" + |
| "(!("+ UPnPDevice.PARENT_UDN + "=*))" + |
| ")"); |
| } catch (InvalidSyntaxException e) { |
| e.printStackTrace(); |
| } |
| if (roots != null) { |
| for (int i = 0; i < roots.length; i++) { |
| addDevice(roots[i]); |
| } |
| } |
| } |
| |
| /** |
| * |
| */ |
| public void deactive() { |
| Activator.bc.removeServiceListener(this); |
| } |
| |
| } |