public Map getSystemProperties() {
    Map map = new HashMap();
    Properties props = System.getProperties();

    for (Enumeration e = props.keys(); e.hasMoreElements(); ) {
      String key = (String) e.nextElement();
      String val = (String) props.get(key);
      map.put(key, val);
    }
    return map;
  }
public class RemoteFWServer implements RemoteFW {

  ServiceRegistration reg = null;

  ServiceTracker slTracker;
  ServiceTracker pkgTracker;

  Thread reaper = null;
  boolean bReap = false;
  long reapDelay = 60 * 1000;

  boolean bDebug =
      "true".equals(System.getProperty("org.knopflerfish.soap.remotefw.server.debug", "false"));

  public RemoteFWServer() {}

  public void startBundle(long bid) {
    try {
      Activator.bc.getBundle(bid).start();
    } catch (BundleException e) {
      throw new IllegalArgumentException("Failed to start bid=" + bid);
    }
  }

  public void stopBundle(long bid) {
    try {
      Activator.bc.getBundle(bid).stop();
    } catch (BundleException e) {
      throw new IllegalArgumentException("Failed to stop bid=" + bid);
    }
  }

  public void updateBundle(long bid) {
    try {
      Activator.bc.getBundle(bid).update();
    } catch (BundleException e) {
      throw new IllegalArgumentException("Failed to update bid=" + bid);
    }
  }

  public void uninstallBundle(long bid) {
    try {
      Activator.bc.getBundle(bid).uninstall();
    } catch (BundleException e) {
      throw new IllegalArgumentException("Failed to uninstall bid=" + bid);
    }
  }

  public long installBundle(String location) {
    try {
      Bundle b = Activator.bc.installBundle(location);
      return b.getBundleId();
    } catch (BundleException e) {
      throw new IllegalArgumentException("Failed to install location=" + location);
    }
  }

  public long getBundle() {
    return Activator.bc.getBundle().getBundleId();
  }

  public long[] getBundles() {
    Bundle[] bl = Activator.bc.getBundles();
    long[] bids = new long[bl.length];

    for (int i = 0; i < bl.length; i++) {
      bids[i] = bl[i].getBundleId();
    }
    return bids;
  }

  public String getBundleContextProperty(String key) {
    String v = Activator.bc.getProperty(key);

    return v == null ? NULL_STR : v;
  }

  public String getBundleLocation(long bid) {
    Bundle b = Activator.bc.getBundle(bid);

    return b.getLocation();
  }

  public int getBundleState(long bid) {
    Bundle b = Activator.bc.getBundle(bid);

    return b.getState();
  }

  public long[] getServicesInUse(long bid) {
    Bundle b = Activator.bc.getBundle(bid);
    return Util.referencesToLong(b.getServicesInUse());
  }

  public long[] getRegisteredServices(long bid) {
    Bundle b = Activator.bc.getBundle(bid);
    return Util.referencesToLong(b.getRegisteredServices());
  }

  public long[] getServiceReferences(String filter) {
    return getServiceReferences2(null, filter);
  }

  public long[] getServiceReferences2(String clazz, String filter) {
    try {
      if (NULL_STR.equals(clazz)) {
        clazz = null;
      }
      if (NULL_STR.equals(filter)) {
        filter = null;
      }
      ServiceReference[] srl = Activator.bc.getServiceReferences(clazz, filter);

      /*
        System.out.println("server:getServiceReferences2 class=" + clazz +
        ", filter=" + filter +
        ", srl=" + (srl != null ? ("" + srl.length) : "null"));
      */
      if (srl == null) {
        return new long[0];
      }
      long[] r = new long[srl.length * 2];
      int n = 0;
      for (int i = 0; i < srl.length; i++) {
        r[n * 2] = ((Long) srl[i].getProperty(Constants.SERVICE_ID)).longValue();
        r[n * 2 + 1] = srl[i].getBundle().getBundleId();

        n++;
      }
      return r;
    } catch (Exception e) {
      throw new RuntimeException("Failed to get services from filter=" + filter + ",  " + e);
    }
  }

  public Map getBundleManifest(long bundleId) {
    Bundle b = Activator.bc.getBundle(bundleId);

    Dictionary d = b.getHeaders();

    Map result = new HashMap();

    int i = 0;
    for (Enumeration e = d.keys(); e.hasMoreElements(); ) {
      String key = (String) e.nextElement();
      String val = (String) d.get(key);

      result.put(key, val);

      i += 2;
    }

    result.remove("Application-Icon");
    return result;
  }

  public long[] getServices() {
    return null;
  }

  public long[] getFrameworkEvents() {
    synchronized (frameworkEvents) {
      try {

        long[] r = new long[frameworkEvents.size() * 2];
        if (bDebug) {
          System.out.println("server: getFrameworkEvents size=" + r.length / 2);
        }
        int i = 0;

        for (Iterator it = frameworkEvents.iterator(); it.hasNext(); ) {
          FrameworkEvent ev = (FrameworkEvent) it.next();
          Bundle b = ev.getBundle();
          long bid = -1;
          if (b == null) {
            if (bDebug) {
              System.out.println("fw event: " + ev + " - no bundle");
            }
          } else {
            bid = b.getBundleId();
          }
          r[i * 2] = bid;
          r[i * 2 + 1] = ev.getType();
          i++;
        }

        frameworkEvents.clear();
        if (bDebug) {
          System.out.println("server: getFrameworkEvents -> " + r);
        }
        return r;
      } catch (Exception e) {
        if (bDebug) {
          e.printStackTrace();
        }
      }
    }
    return null;
  }

  public long[] getBundleEvents() {
    synchronized (bundleEvents) {
      long[] r = new long[bundleEvents.size() * 2];
      int i = 0;

      for (Iterator it = bundleEvents.iterator(); it.hasNext(); ) {
        BundleEvent ev = (BundleEvent) it.next();
        r[i * 2] = ev.getBundle().getBundleId();
        r[i * 2 + 1] = ev.getType();
        i++;
      }
      bundleEvents.clear();
      return r;
    }
  }

  public long[] getServiceEvents() {
    synchronized (serviceEvents) {
      long[] r = new long[serviceEvents.size() * 2];
      int i = 0;

      for (Iterator it = serviceEvents.iterator(); it.hasNext(); ) {
        ServiceEvent ev = (ServiceEvent) it.next();
        r[i * 2] = ((Long) ev.getServiceReference().getProperty(Constants.SERVICE_ID)).longValue();
        r[i * 2 + 1] = ev.getType();
        i++;
      }

      serviceEvents.clear();
      return r;
    }
  }

  public Map getServiceProperties(long sid) {
    try {
      ServiceReference[] srl = Activator.bc.getServiceReferences(null, "(service.id=" + sid + ")");

      String[] keys = srl[0].getPropertyKeys();

      Map result = new HashMap();

      for (int i = 0; i < keys.length; i++) {
        String key = keys[i];
        Object val = srl[0].getProperty(keys[i]);
        //      Object strVal = Util.encodeAsString(val);

        result.put(key, val);
      }

      return result;

    } catch (Exception e) {
      throw new IllegalArgumentException(
          "Failed to get service properties " + "for service.id=" + sid + ", " + e);
    }
  }

  public int getStartLevel() {
    return ((StartLevel) slTracker.getService()).getStartLevel();
  }

  public void setStartLevel(int level) {
    ((StartLevel) slTracker.getService()).setStartLevel(level);
  }

  public void setBundleStartLevel(long bid, int level) {
    Bundle b = Activator.bc.getBundle(bid);
    ((StartLevel) slTracker.getService()).setBundleStartLevel(b, level);
  }

  public int getBundleStartLevel(long bid) {
    Bundle b = Activator.bc.getBundle(bid);
    return ((StartLevel) slTracker.getService()).getBundleStartLevel(b);
  }

  public void setInitialBundleStartLevel(int level) {
    ((StartLevel) slTracker.getService()).setInitialBundleStartLevel(level);
  }

  public int getInitialBundleStartLevel() {
    return ((StartLevel) slTracker.getService()).getInitialBundleStartLevel();
  }

  public boolean isBundlePersistentlyStarted(long bid) {
    Bundle b = Activator.bc.getBundle(bid);
    return ((StartLevel) slTracker.getService()).isBundlePersistentlyStarted(b);
  }

  public boolean isBundleActivationPolicyUsed(long bid) {
    Bundle b = Activator.bc.getBundle(bid);
    return ((StartLevel) slTracker.getService()).isBundleActivationPolicyUsed(b);
  }

  public Map getExportedPackage(String name) {
    Map map = new HashMap();
    ExportedPackage pkg = ((PackageAdmin) pkgTracker.getService()).getExportedPackage(name);

    putExportPackage(map, pkg);
    return map;
  }

  public Map[] getExportedPackages(long bid) {
    Bundle b = -1 == bid ? null : Activator.bc.getBundle(bid);
    ExportedPackage[] pkgs = ((PackageAdmin) pkgTracker.getService()).getExportedPackages(b);

    if (pkgs == null) {
      return new Map[0];
    }

    Map[] maps = new Map[pkgs.length];
    for (int i = 0; i < pkgs.length; i++) {
      maps[i] = new HashMap();
      putExportPackage(maps[i], pkgs[i]);
    }
    return maps;
  }

  public void refreshPackages(long[] bids) {
    if (bids.length == 0) {
      ((PackageAdmin) pkgTracker.getService()).refreshPackages(null);
      bids = null;
    } else {
      Bundle[] bl = new Bundle[bids.length];
      for (int i = 0; i < bids.length; i++) {
        bl[i] = Activator.bc.getBundle(bids[i]);
      }
      ((PackageAdmin) pkgTracker.getService()).refreshPackages(bl);
    }
  }

  void putExportPackage(Map map, ExportedPackage pkg) {
    if (pkg != null) {
      Long[] bids;
      Bundle[] bl = pkg.getImportingBundles();
      if (bl == null) {
        bids = new Long[0];
      } else {
        bids = new Long[bl.length];
        for (int i = 0; i < bids.length; i++) {
          bids[i] = new Long(bl[i].getBundleId());
        }
      }
      map.put("getExportingBundle", new Long(pkg.getExportingBundle().getBundleId()));
      map.put("getImportingBundles", bids);
      map.put("getName", pkg.getName());
      map.put("getSpecificationVersion", pkg.getSpecificationVersion());
      map.put("isRemovalPending", pkg.isRemovalPending() ? Boolean.TRUE : Boolean.FALSE);
    }
  }

  public Map getSystemProperties() {
    Map map = new HashMap();
    Properties props = System.getProperties();

    for (Enumeration e = props.keys(); e.hasMoreElements(); ) {
      String key = (String) e.nextElement();
      String val = (String) props.get(key);
      map.put(key, val);
    }
    return map;
  }

  public void start() {
    if (reg == null) {

      slTracker = new ServiceTracker(Activator.bc, StartLevel.class.getName(), null);
      slTracker.open();

      pkgTracker = new ServiceTracker(Activator.bc, PackageAdmin.class.getName(), null);
      pkgTracker.open();

      Hashtable props = new Hashtable();

      props.put("SOAP.service.name", "OSGiFramework");

      reg = Activator.bc.registerService(RemoteFW.class.getName(), this, props);

      Activator.bc.addBundleListener(
          new BundleListener() {
            public void bundleChanged(BundleEvent event) {
              synchronized (bundleEvents) {
                bundleEvents.add(event);
              }
            }
          });
      Activator.bc.addServiceListener(
          new ServiceListener() {
            public void serviceChanged(ServiceEvent event) {
              synchronized (serviceEvents) {
                serviceEvents.add(event);
              }
            }
          });
      Activator.bc.addFrameworkListener(
          new FrameworkListener() {
            public void frameworkEvent(FrameworkEvent ev) {
              synchronized (frameworkEvents) {
                int type = ev.getType();
                Bundle b = ev.getBundle();
                if (b == null) {
                  Object obj = ev.getSource();
                  if (bDebug) {
                    System.out.println("obj=" + obj);
                    if (obj != null) {
                      System.out.println("source class=" + obj.getClass().getName());
                    }
                  }
                  if (obj != null && (obj instanceof Bundle)) {
                    b = (Bundle) obj;
                  }
                }
                if (bDebug) {

                  System.out.println(
                      "server: add fw event: " + ev + ", type=" + type + ", bundle=" + b);
                }
                if (b != null) {
                  frameworkEvents.add(new FrameworkEvent(type, b, null));
                }
              }
            }
          });

      reaper =
          new Thread() {
            public void run() {
              while (bReap) {
                try {
                  reapEvents();
                  Thread.sleep(reapDelay);
                } catch (Exception e) {

                }
              }
            }
          };

      bReap = true;
      reaper.start();
    }
  }

  void reapEvents() {
    trimList(serviceEvents, MAX_SERVICE_EVENTS);
    trimList(bundleEvents, MAX_BUNDLE_EVENTS);
    trimList(frameworkEvents, MAX_FRAMEWORK_EVENTS);
  }

  void trimList(List list, int max) {
    synchronized (list) {
      while (list.size() > max) {
        list.remove(0);
      }
    }
  }

  public void stop() {
    if (reaper != null) {
      bReap = false;
      try {
        reaper.wait(1000);
      } catch (Exception ignored) {
      }
      reaper = null;
    }
    if (reg != null) {
      reg.unregister();
      reg = null;

      slTracker.close();
    }
  }

  static int MAX_SERVICE_EVENTS = 1000;
  static int MAX_BUNDLE_EVENTS = 1000;
  static int MAX_FRAMEWORK_EVENTS = 1000;

  List bundleEvents = new ArrayList();
  List serviceEvents = new ArrayList();
  List frameworkEvents = new ArrayList();
}