Package org.apache.felix.upnp.basedriver.export

Source Code of org.apache.felix.upnp.basedriver.export.ThreadExporter

/*
* 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.io.File;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;
import java.util.Vector;

import org.apache.felix.upnp.basedriver.Activator;
import org.cybergarage.upnp.Device;
import org.cybergarage.upnp.DeviceList;
import org.cybergarage.upnp.ServiceList;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.upnp.UPnPDevice;
import org.osgi.service.upnp.UPnPEventListener;

/*
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class ThreadExporter implements Runnable,ServiceListener {

  private boolean end;

  private RootDeviceExportingQueue queueRootDevice;

//  private String basePath; twa: redundant

//  private File baseFile; twa: redundant

  private Hashtable exportedDevices;
 
  private boolean listening;
 
  private class ExportedDeviceInfo{
    private Device device;
    private ServiceRegistration serviceRegistration;
    //private DeviceNode deviceNode;
   
     
    /**
     * @param device
     * @param serviceRegistration
     * @param deviceNode
     */
    private ExportedDeviceInfo(Device device,
        ServiceRegistration serviceRegistration,
        DeviceNode deviceNode) {
      super();
      this.device = device;
      this.serviceRegistration = serviceRegistration;
      //this.deviceNode = deviceNode;
    }
   
   
    private Device getDevice() {
      return this.device;
    }
    private ServiceRegistration getServiceRegistration() {
      return this.serviceRegistration;
    }
    /*private DeviceNode getDeviceNode(){
      return this.deviceNode;
    }*/
       
   
  }
 
  /**
   * 
   */
  public ThreadExporter(RootDeviceExportingQueue queue) throws InvalidSyntaxException {
      end=false;
      queueRootDevice=queue;
    this.exportedDevices=new Hashtable();
    setListening(false);
  }
   
  public void run() {
   
    File osgiRoot = Activator.bc.getDataFile("");
    if (osgiRoot == null) {
      Activator.logger.ERROR("Unable to use filesystem");
      while (true) {
        try {
          Activator.bc.getBundle().stop();
          break;
        } catch (BundleException e) {
          e.printStackTrace();
          try {
            Thread.sleep(1000);
          } catch (InterruptedException ex) {
            ex.printStackTrace();
          }
        }
      }
      return;
    }
   
    ServiceReference rootDevice = null;
    while (!shouldEnd()) {
      DeviceNode dn = queueRootDevice.getRootDevice();
      if (dn == null)
        continue;
      rootDevice = dn.getReference();
      if(!getListening())
        setListen();
      Activator.logger.INFO("[Exporter] Exporting device "+ rootDevice.getProperty(UPnPDevice.FRIENDLY_NAME));
     
            /*
       * I don't know if the exporting should be make default language of the framework
       * or without any lanuguages
      Root r = new Root(rootDevice, context, context
          .getProperty(Constants.FRAMEWORK_LANGUAGE));
      */
           
      synchronized (this) {
        Device d = BuildDevice.createCyberLinkDevice(dn.getReference());
        if (d != null) {
          if(!bindInvokes(d,rootDevice)){
            Activator.logger.DEBUG("Unable to find all the sub device or to set action listener");
            continue;
          }
          ServiceRegistration listenReg = bindSubscribe(d);
          if(listenReg==null){
            Activator.logger.DEBUG("Unable to set action listener event listener");
            continue;
          }     
          //makeIcons(r.getRootDevice(),xml.getAbsolutePath());
          d.start();
          exportedDevices.put(
              rootDevice.getProperty(UPnPDevice.UDN),
              new ExportedDeviceInfo(d,listenReg,dn)
          );
        }
      }
    }
  }

  /**
   *
   */
  private void setListen() {
    {
      try {
        Activator.bc.addServiceListener(
            this,
            // fixed by Matteo and Francesco 21/9/04
            "(&("+Constants.OBJECTCLASS+"="+UPnPDevice.class.getName()+")"
            + "(" + UPnPDevice.UPNP_EXPORT +"=*))"
        );
      } catch (InvalidSyntaxException ingnore) {}
    }
  }
  /*
  /**
   * @param upnpDev
   * @param refDev
   *
  private void makeIcons(
      org.apache.felix.upnpbase.export.xml.Device upnpDev,
      String path) {
    Icon[] icons = upnpDev.getIcons();
    if(icons!=null){
      byte[] buf = new byte[512];
      for (int i = 0; i < icons.length; i++) {
        try {
          String icoPath = path+icons[i].getUrl().replace('/',File.separatorChar);
          InputStream is = icons[i].getInputStream();
          Converter.makeParentPath(icoPath);
          FileOutputStream fos = new FileOutputStream(icoPath);
          int n=is.read(buf,0,buf.length);
          while(n>0){
            fos.write(buf,0,n);
            n=is.read(buf,0,buf.length);
          }
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
    org.apache.felix.upnpbase.export.xml.Device[] devs = upnpDev.getDevices();
    if(devs==null)
      return;
    for (int i = 0; i < devs.length; i++) {
      makeIcons(devs[i],path);
    }
  }*/
  /**
   * This method is used to connect all the Action that are shown to UPnP world
   * by CyberLink UPnP Device to the real implementation that is conatined iniside
   * the OSGi service.
   * This method will connect even all the subdevice of te given OSGi device.
   *
   * @param d CyberLink Device that will be used associated to the OSGi Device
   * @param rootDevice ServiceReference to the OSGi Device that will be used as
   *   implementation of the CyberLink Device
   * @return true if and only if the binding off all the action of all the children
   *     device is done succesfully
   */
  private boolean bindInvokes(Device d, ServiceReference rootDevice) {
    bindInvoke(d,rootDevice);
    ServiceReference[] childs = null;
    try {
      childs = Activator.bc.getServiceReferences(
        UPnPDevice.class.getName(),
        "("+UPnPDevice.PARENT_UDN+"="+rootDevice.getProperty(UPnPDevice.UDN)+")"
      );
    } catch (InvalidSyntaxException e) {
      e.printStackTrace();       
    }   
    String[] childsUDN = (String[]) rootDevice.getProperty(UPnPDevice.CHILDREN_UDN);
    if((childs==null)&&(childsUDN==null)){
      return true;     
    }else if((childs==null)||(childsUDN==null)){
      return false;
    }else if(childs.length==childsUDN.length){
            DeviceList dl = d.getDeviceList();
            for (int i = 0; i < childs.length; i++) {
                Device dev = (Device)dl.elementAt(i);
                if(!bindInvokes(dev,childs[i]))
                    return false;
            }

      return true;
    }else{
      return false;
    }
     
  }
   
  /**
   * This method add an UPnPEventListener Service to the OSGi Framework so that
   * the Base Driver can notify all the event listener registered on the CyberLink
   * UPnP device from the UPnP World.
   *
   * @param d Device of CyberLink that will be notified by the changing of the StateVariable
   *     that happen on the OSGi World 
   * @return ServiceRegistration of the new registered service.
   */
  private ServiceRegistration bindSubscribe(Device d) {
    ExporterUPnPEventListener eventer = new ExporterUPnPEventListener(d);
    Properties p = new Properties();

    StringBuffer sb = new StringBuffer("(|");
    Vector v = new Vector();
    v.add(d);
    Device current;
    while (v.size() != 0) {
      current = (Device) v.elementAt(0);
      v.remove(0);
      DeviceList dl = current.getDeviceList();
      for (int i = 0; i < dl.size(); i++) {
        v.add(dl.elementAt(i));
      }
      sb.append("(").append(UPnPDevice.ID).append("=").append(
          current.getUDN()).append(")");
    }
    sb.append(")");
    Filter f = null;
    try {
      f = Activator.bc.createFilter(sb.toString());
    } catch (InvalidSyntaxException e) {
      e.printStackTrace();
      return null;
    }
    if (f != null) p.put(UPnPEventListener.UPNP_FILTER, f);
   
    return Activator.bc.registerService(UPnPEventListener.class.getName(), eventer, p);
  }

  /**
   * This method do the real connection between OSGi UPnP Service action and
   * CyberLink UPnP Device action
   *
   * @param upnpDev the CyberLink UPnP Device object that will be connected
   * @param osgiDev the ServiceReference to OSGi UPnP Service that will be connected to
   *     CyberLink UPnP as implementation of the Action
   * @return true if and only if the binding off all the action is done succesfully
   */
  private boolean bindInvoke(Device upnpDev,ServiceReference osgiDev) {
    ServiceList sl = upnpDev.getServiceList();
    int l=sl.size();
    for (int i = 0; i < l; i++) {
      sl.getService(i).setActionListener(
        new GeneralActionListener(
          osgiDev,
          sl.getService(i).getServiceID()
        )
      );     
    }
    return true;
  }

  /**
   * 
   */
  public synchronized void cleanUp() {
    Activator.logger.INFO("Cleaning...");
   
    Enumeration keys;
   
    Activator.logger.INFO("Removing temporary listener....");
    keys=exportedDevices.keys();
    while (keys.hasMoreElements()) {
      ServiceRegistration sr = ((ExportedDeviceInfo)
          exportedDevices.get(keys.nextElement())).getServiceRegistration();
      sr.unregister();
    }   
    Activator.logger.INFO("Done");
   
    Activator.logger.INFO("Removing device....");
    keys=exportedDevices.keys();
    while (keys.hasMoreElements()) {
      Device dev = ((ExportedDeviceInfo)
          exportedDevices.get(keys.nextElement())).getDevice();
      dev.stop();
    }   
    Activator.logger.INFO("Done");
  }

  private synchronized boolean shouldEnd() {
    return end;
  }

  public synchronized void end() {
    end = true;
    queueRootDevice.addRootDevice(null);
  }
  /**
   * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent)
   */
  public void serviceChanged(ServiceEvent event) {
    switch(event.getType()){
      case ServiceEvent.REGISTERED:break;
     
      case ServiceEvent.MODIFIED:
      case ServiceEvent.UNREGISTERING:{
        this.unexportDevice(event.getServiceReference());
        if(exportedDevices.size()==0){
          Activator.bc.removeServiceListener(this);
          setListening(false);
        }
      }break;
    }
  }
  /**
   * @param b
   */
  private synchronized void setListening(boolean b) {
    listening=b; 
  }
 
  private synchronized boolean getListening(){
    return listening;
  }
 
  /**
   * @param property
   */
  private synchronized void unexportDevice(ServiceReference dev) {
    String udn=(String) dev.getProperty(UPnPDevice.PARENT_UDN);
    if(udn==null){
      ExportedDeviceInfo edi =
        (ExportedDeviceInfo) exportedDevices.get(
          dev.getProperty(UPnPDevice.UDN)
        );
      Device d = edi.getDevice();
      if(d!=null) {
                Activator.logger.INFO("[Exporter] removing device:" +d.getFriendlyName());
        d.stop();
        exportedDevices.remove(d.getUDN());
      }
      ServiceRegistration srListener=edi.getServiceRegistration();
      if(srListener!=null) srListener.unregister();
     
    }else{
      ServiceReference[] servs=null;
      try {
        servs = Activator.bc.getServiceReferences(
            UPnPDevice.class.getName(),
            "("+UPnPDevice.UDN+"="+udn+")"
        );
      } catch (InvalidSyntaxException ignored) {}
      if(servs==null) return;
      this.unexportDevice(servs[0]);
    }
  }
}
TOP

Related Classes of org.apache.felix.upnp.basedriver.export.ThreadExporter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.