Example #1
0
  /**
   * @param serviceID
   * @return
   */
  static RemoteServiceRegistration getServiceRegistration(final String serviceID) {

    final String filter =
        "".equals(serviceID)
            ? null
            : '(' //$NON-NLS-1$
                + Constants.SERVICE_ID
                + "="
                + serviceID
                + ")"; //$NON-NLS-1$ //$NON-NLS-2$

    try {
      final ServiceReference[] refs =
          RemoteOSGiActivator.getActivator().getContext().getServiceReferences(null, filter);
      if (refs == null) {
        if (log != null) {
          log.log(LogService.LOG_WARNING, "COULD NOT FIND " + filter); // $NON-NLS-1$
        }
        return null;
      }
      return (RemoteServiceRegistration) serviceRegistrations.get(refs[0]);
    } catch (final InvalidSyntaxException e) {
      e.printStackTrace();
      return null;
    }
  }
 /** Starts the factory. This method is not called when holding the monitor lock. */
 public void starting() {
   if (m_tracker == null) {
     if (m_requiredHandlers.size() != 0) {
       try {
         String filter =
             "(&("
                 + Handler.HANDLER_TYPE_PROPERTY
                 + "="
                 + PrimitiveHandler.HANDLER_TYPE
                 + ")"
                 + "(factory.state=1)"
                 + ")";
         m_tracker = new Tracker(m_context, m_context.createFilter(filter), this);
         m_tracker.open();
       } catch (InvalidSyntaxException e) {
         m_logger.log(
             Logger.ERROR,
             "A factory filter is not valid: "
                 + e.getMessage()); // Holding the lock should not be an issue here.
         stop();
       }
     }
   }
   // Else, the tracking has already started.
 }
Example #3
0
  private NetworkChannelFactory getNetworkChannelFactory(final String protocol)
      throws RemoteOSGiException {
    try {
      final Filter filter =
          RemoteOSGiActivator.getActivator()
              .getContext()
              .createFilter(
                  "(" //$NON-NLS-1$
                      + NetworkChannelFactory.PROTOCOL_PROPERTY
                      + "="
                      + protocol //$NON-NLS-1$
                      + ")"); //$NON-NLS-1$
      final ServiceReference[] refs = networkChannelFactoryTracker.getServiceReferences();

      if (refs != null) {
        for (int i = 0; i < refs.length; i++) {
          if (filter.match(refs[i])) {
            return (NetworkChannelFactory) networkChannelFactoryTracker.getService(refs[i]);
          }
        }
      }
      throw new RemoteOSGiException(
          "No NetworkChannelFactory for " //$NON-NLS-1$
              + protocol
              + " found."); //$NON-NLS-1$

    } catch (final InvalidSyntaxException e) {
      // does not happen
      e.printStackTrace();
      return null;
    }
  }
 /** Handle the system notifying that it's ready to install configs. */
 public void checkReady() throws BootstrapFailure {
   if (requireRepository) {
     ServiceTracker repoTracker = null;
     try {
       if (repo == null) {
         Filter filter =
             ctx.createFilter(
                 "(" + Constants.OBJECTCLASS + "=" + RepoBootService.class.getName() + ")");
         repoTracker = new ServiceTracker(ctx, filter, null);
         repoTracker.open();
         logger.debug("Bootstrapping repository");
         RepoBootService rawRepo = (RepoBootService) repoTracker.waitForService(5000);
         if (rawRepo != null) {
           logger.debug("Bootstrap obtained repository");
           repo = rawRepo;
         } else {
           logger.info("Failed to bootstrap repo, returned null");
         }
       }
     } catch (InterruptedException ex) {
       logger.warn("Failed to bootstrap repo " + ex.getMessage(), ex);
     } catch (InvalidSyntaxException ex) {
       logger.warn("Failed to bootstrap repo " + ex.getMessage(), ex);
     } finally {
       if (repoTracker != null) {
         repoTracker.close();
       }
     }
     if (repo == null) {
       throw new BootstrapFailure(
           "Failed to acquire the bootstrap repository service to access configuration persistence.");
     }
   }
 }
Example #5
0
  protected Component getContent(MPart mPart) {
    BundleContext context = getBundleContext();

    String id = getServiceID(mPart);

    try {
      String filter = String.format("(%s=%s)", IOutlineViewProvider.PROPERTY, id);
      Collection<ServiceReference<IOutlineViewProvider>> services =
          context.getServiceReferences(IOutlineViewProvider.class, filter);
      if (!services.isEmpty()) {
        ServiceReference<IOutlineViewProvider> ref = services.iterator().next();
        IOutlineViewProvider service = context.getService(ref);
        if (service != null) {
          try {
            return service.getOutlineContent(mPart);
          } finally {
            getBundleContext().ungetService(ref);
          }
        }
      }
    } catch (InvalidSyntaxException e) {
      e.printStackTrace();
    }

    return null;
  }
 /**
  * Add a service listener.
  *
  * <p>This method is the same as calling {@link #addServiceListener(ServiceListener, String)} with
  * filter set to <code>null</code>.
  *
  * @see #addServiceListener(ServiceListener, String)
  */
 public void addServiceListener(ServiceListener listener) {
   try {
     addServiceListener(listener, null);
   } catch (InvalidSyntaxException e) {
     if (Debug.DEBUG_GENERAL) {
       Debug.println("InvalidSyntaxException w/ null filter" + e.getMessage()); // $NON-NLS-1$
       Debug.printStackTrace(e);
     }
   }
 }
  /**
   * Retrieves a reference to the Gibberish bundle, stops it and uninstalls it and then reinstalls
   * it in order to make sure that accounts are not reloaded once removed.
   *
   * @throws java.lang.Exception if something goes wrong while manipulating the bundles.
   */
  public void testAccountUninstallationPersistence() throws Exception {
    Bundle providerBundle = GibberishSlickFixture.providerBundle;

    providerBundle.stop();

    assertTrue(
        "Couldn't stop the protocol provider bundle. State was " + providerBundle.getState(),
        Bundle.ACTIVE != providerBundle.getState() && Bundle.STOPPING != providerBundle.getState());

    providerBundle.uninstall();

    assertEquals(
        "Couldn't stop the protocol provider bundle.",
        Bundle.UNINSTALLED,
        providerBundle.getState());

    // Now reinstall the bundle and restart the provider
    providerBundle = GibberishSlickFixture.bc.installBundle(providerBundle.getLocation());

    assertEquals(
        "Couldn't re-install protocol provider bundle.",
        Bundle.INSTALLED,
        providerBundle.getState());

    AccountManagerUtils.startBundleAndWaitStoredAccountsLoaded(
        GibberishSlickFixture.bc, providerBundle, "Gibberish");
    assertEquals(
        "Couldn't re-start protocol provider bundle.", Bundle.ACTIVE, providerBundle.getState());

    // verify that the provider is not reinstalled
    ServiceReference[] gibberishProviderRefs = null;
    try {
      gibberishProviderRefs =
          GibberishSlickFixture.bc.getServiceReferences(
              ProtocolProviderService.class.getName(),
              "(" + ProtocolProviderFactory.PROTOCOL + "=Gibberish)");
    } catch (InvalidSyntaxException ex) {
      fail("We apparently got our filter wrong " + ex.getMessage());
    }

    // make sure we didn't retrieve a service
    assertTrue(
        "A Gibberish Protocol Provider Service was still regged "
            + "as an osgi service after it was explicitly uninstalled",
        gibberishProviderRefs == null || gibberishProviderRefs.length == 0);

    // and a nasty hack at the end - delete the configuration file so that
    // we get a fresh start on next run.
    ServiceReference confReference =
        GibberishSlickFixture.bc.getServiceReference(ConfigurationService.class.getName());
    ConfigurationService configurationService =
        (ConfigurationService) GibberishSlickFixture.bc.getService(confReference);

    configurationService.purgeStoredConfiguration();
  }
Example #8
0
 /** mapping rule: LDAP filter --> output value the more specific filters should be given first. */
 public void initialize(BundleContext ctx, String[][] mappingRules) {
   filters = new Filter[mappingRules.length];
   outputStrings = new String[mappingRules.length];
   for (int i = 0; i < mappingRules.length; i++) {
     try {
       filters[i] = ctx.createFilter(mappingRules[i][0]);
       outputStrings[i] = mappingRules[i][1];
     } catch (InvalidSyntaxException e) {
       // TODO Neeed to process this
       e.printStackTrace();
     }
   }
 }
 /**
  * fetchReferences.
  *
  * @return an array of {@link org.osgi.framework.ServiceReference} objects.
  */
 public ServiceReference<?>[] fetchReferences() {
   try {
     LOGGER.debug(
         "Try to locate a suitable service for objectClass = "
             + serviceInterface
             + " and filter = "
             + filterString);
     return bundleContext.getAllServiceReferences(serviceInterface, filterString);
   } catch (InvalidSyntaxException e) {
     LOGGER.error("Creation of filter failed: {}", e.getMessage(), e);
     throw new RuntimeException("Creation of filter failed", e);
   }
 }
 private void scanForExistingHandlers() {
   try {
     final ServiceReference<?>[] allServiceReferences =
         this.bundleContext.getAllServiceReferences("org.vertx.java.core.Handler", null);
     if (allServiceReferences != null) {
       for (final ServiceReference<?> serviceReference : allServiceReferences) {
         registerHandlerIfNecessary(serviceReference);
       }
     }
   } catch (final InvalidSyntaxException e) {
     e.printStackTrace();
   }
 }
  private IBackendService getBackendService() {
    ServiceReference[] references = null;
    try {
      references =
          Activator.getBundleContext()
              .getAllServiceReferences(IBackendService.class.getName(), null);
    } catch (InvalidSyntaxException e) {
      log.error(e.getMessage());
    }

    if ((references == null) || (references.length == 0)) {
      return null;
    }

    return (IBackendService) Activator.getBundleContext().getService(references[0]);
  }
 @SuppressWarnings("rawtypes")
 private Set<ServiceReference<?>> findHandlerRefs(final int portNumber, final String filter) {
   final Set<ServiceReference<?>> result = new HashSet<ServiceReference<?>>();
   try {
     final Collection<ServiceReference<Handler>> refs =
         this.bundleContext.getServiceReferences(Handler.class, filter);
     for (final ServiceReference<Handler> ref : refs) {
       if (portNumber == getHandlerPortNumber(ref)) {
         result.add(ref);
       }
     }
   } catch (final InvalidSyntaxException e) {
     // Should never happen
     e.printStackTrace();
   }
   return result;
 }
  /** Uinstalls our test account and makes sure it really has been removed. */
  public void testUninstallAccount() {
    assertFalse(
        "No installed accounts found", fixture.providerFactory.getRegisteredAccounts().isEmpty());

    assertNotNull(
        "Found no provider corresponding to URI " + fixture.userID1,
        fixture.providerFactory.getProviderForAccount(fixture.provider1.getAccountID()));

    assertTrue(
        "Failed to remove a provider corresponding to URI " + fixture.userID1,
        fixture.providerFactory.uninstallAccount(fixture.provider1.getAccountID()));
    assertTrue(
        "Failed to remove a provider corresponding to URI " + fixture.userID1,
        fixture.providerFactory.uninstallAccount(fixture.provider2.getAccountID()));

    // make sure no providers have remained installed.
    ServiceReference[] sipProviderRefs = null;
    try {
      sipProviderRefs =
          fixture.bc.getServiceReferences(
              ProtocolProviderService.class.getName(),
              "(" + ProtocolProviderFactory.PROTOCOL + "=" + ProtocolNames.SIP + ")");
    } catch (InvalidSyntaxException ex) {
      fail("We apparently got our filter wrong " + ex.getMessage());
    }

    // make sure we didn't see a service
    assertTrue(
        "A Protocol Provider Service was still regged as an osgi "
            + "service for SIP URI:"
            + fixture.userID1
            + "After it was explicitly uninstalled",
        sipProviderRefs == null || sipProviderRefs.length == 0);

    // verify that the provider factory knows that we have uninstalled the
    // provider.
    assertTrue(
        "The SIP provider factory kept a reference to the provider we just "
            + "uninstalled (uri="
            + fixture.userID1
            + ")",
        fixture.providerFactory.getRegisteredAccounts().isEmpty()
            && fixture.providerFactory.getProviderForAccount(fixture.provider1.getAccountID())
                == null);
  }
Example #14
0
 /**
  * @param ref the <code>RemoteServiceReference</code> to the service.
  * @return the service reference of the service (or service proxy) or <code>null</code> if the
  *     service is not (yet) present.
  * @see
  *     ch.ethz.iks.r_osgi.RemoteOSGiService#getFetchedServiceReference(ch.ethz.iks.r_osgi.RemoteServiceReference)
  * @category RemoteOSGiService
  * @since 0.6
  */
 private ServiceReference getFetchedServiceReference(final RemoteServiceReference ref) {
   try {
     final ServiceReference[] refs =
         RemoteOSGiActivator.getActivator()
             .getContext()
             .getServiceReferences(
                 ref.getServiceInterfaces()[0],
                 "(" //$NON-NLS-1$
                     + SERVICE_URI
                     + "="
                     + ref.getURI()
                     + ")"); //$NON-NLS-1$ //$NON-NLS-2$
     if (refs != null) {
       return refs[0];
     }
   } catch (final InvalidSyntaxException doesNotHappen) {
     doesNotHappen.printStackTrace();
   }
   return null;
 }
  /**
   * Constructor for configuration resource manager
   *
   * @param configAdmin {@code ConfigurationAdmin}
   */
  public ConfigAdminResourceManager(Object configAdmin) {
    super(CONFIG_PATH);
    this.m_configAdmin = (ConfigurationAdmin) configAdmin;
    this.m_configListener = new ConfigurationListenerHandler();
    setRelations(
        new DefaultRelation(
            getPath(),
            Action.CREATE,
            "create",
            new DefaultParameter()
                .name(BUNDLE_LOCATION)
                .description("bundle location")
                .type(String.class)
                .optional(false),
            new DefaultParameter()
                .name(PID)
                .description("Persistent id of configuration")
                .type(String.class)
                .optional(true),
            new DefaultParameter()
                .name(FACTORY_PID)
                .description("Persistent id of factory pid")
                .type(String.class)
                .optional(true)));

    try {
      Configuration[] configs = m_configAdmin.listConfigurations(null);
      if (configs != null) {
        for (Configuration cfg : configs) {
          m_configurationResourceMap.put(cfg.getPid(), new ConfigurationResource(cfg));
        }
      }
    } catch (IOException e) {
      // well, this may happen..
      throw new RuntimeException(e.getMessage());
    } catch (InvalidSyntaxException e) {
      // should never happen..
      throw new RuntimeException(e.getMessage());
    }
  }
Example #16
0
 /**
  * @see ch.ethz.iks.r_osgi.RemoteOSGiService#getRemoteServiceReferences(ch.ethz.iks.r_osgi.URI,
  *     java.lang.String, org.osgi.framework.Filter)
  */
 public RemoteServiceReference[] getRemoteServiceReferences(
     final URI service, final String clazz, final Filter filter) {
   final String uri = getChannelURI(service);
   ChannelEndpointImpl channel = (ChannelEndpointImpl) channels.get(uri);
   if (channel == null) {
     try {
       connect(service);
       channel = (ChannelEndpointImpl) channels.get(uri);
     } catch (final IOException ioe) {
       throw new RemoteOSGiException("Cannot connect to " + uri); // $NON-NLS-1$
     }
   }
   if (clazz == null) {
     return channel.getAllRemoteReferences(null);
   }
   try {
     return channel.getAllRemoteReferences(
         RemoteOSGiActivator.getActivator()
             .getContext()
             .createFilter(
                 filter != null
                     ? "(&"
                         + filter
                         + "(" //$NON-NLS-1$ //$NON-NLS-2$
                         + Constants.OBJECTCLASS
                         + "="
                         + clazz
                         + "))"
                     : "(" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                         + Constants.OBJECTCLASS
                         + "="
                         + clazz
                         + ")")); //$NON-NLS-1$ //$NON-NLS-2$
   } catch (final InvalidSyntaxException ise) {
     ise.printStackTrace();
     return null;
   }
 }
  @Override
  protected void doInit() throws Exception {
    final String filterStr = getApplicationContext().getInitProperties().get("filter");
    if (null != filterStr) {
      try {
        filter = FrameworkUtil.createFilter(filterStr);
      } catch (final InvalidSyntaxException e) {
        throw new IllegalArgumentException(
            String.format(
                "The specified filter '%s' is invalid. Please check the application configuration. %s",
                filterStr, e.getMessage()),
            e);
      }
    }

    final Dictionary<String, Object> props =
        new Hashtable<String, Object>(getApplicationContext().getInitProperties());

    if (null == props.get(Constants.SERVICE_DESCRIPTION)) {
      props.put(Constants.SERVICE_DESCRIPTION, "Gyrex web application based OSGi HttpService");
    }
    if (null == props.get(Constants.SERVICE_VENDOR)) {
      props.put(Constants.SERVICE_VENDOR, "Eclipse Gyrex");
    }
    if (null == props.get(Constants.SERVICE_PID)) {
      props.put(
          Constants.SERVICE_PID, HttpActivator.SYMBOLIC_NAME.concat(".service-").concat(getId()));
    }

    serviceRegistration =
        HttpActivator.getInstance()
            .getBundle()
            .getBundleContext()
            .registerService(
                new String[] {HttpService.class.getName(), ExtendedHttpService.class.getName()},
                this,
                props);
  }
 /**
  * Creates an OSGi filter for the classes.
  *
  * @param bundleContext a bundle context
  * @param classes array of tracked classes
  * @return osgi filter
  */
 private static Filter createFilter(final BundleContext bundleContext, final Class... classes) {
   final StringBuilder filter = new StringBuilder();
   if (classes != null) {
     if (classes.length > 1) {
       filter.append("(|");
     }
     for (Class clazz : classes) {
       filter
           .append("(")
           .append(Constants.OBJECTCLASS)
           .append("=")
           .append(clazz.getName())
           .append(")");
     }
     if (classes.length > 1) {
       filter.append(")");
     }
   }
   try {
     return bundleContext.createFilter(filter.toString());
   } catch (InvalidSyntaxException e) {
     throw new IllegalArgumentException("Unexpected InvalidSyntaxException: " + e.getMessage());
   }
 }
  /**
   * Stops and removes the tested bundle, verifies that it has unregistered its provider, then
   * reloads and restarts the bundle and verifies that the protocol provider is reRegistered in the
   * bundle context.
   *
   * @throws java.lang.Exception if an exception occurs during testing.
   */
  public void testInstallationPersistency() throws Exception {
    Bundle providerBundle = fixture.findProtocolProviderBundle(fixture.provider1);

    // set the global providerBundle reference that we will be using
    // in the last series of tests (Account uninstallation persistency)
    SipSlickFixture.providerBundle = providerBundle;

    assertNotNull("Couldn't find a bundle for the tested provider", providerBundle);

    providerBundle.stop();

    assertTrue(
        "Couldn't stop the protocol provider bundle. State was " + providerBundle.getState(),
        Bundle.ACTIVE != providerBundle.getState() && Bundle.STOPPING != providerBundle.getState());

    providerBundle.uninstall();

    assertEquals(
        "Couldn't stop the protocol provider bundle.",
        Bundle.UNINSTALLED,
        providerBundle.getState());

    // verify that the provider is no longer available
    ServiceReference[] sipProviderRefs = null;
    try {
      sipProviderRefs =
          fixture.bc.getServiceReferences(
              ProtocolProviderService.class.getName(),
              "(&"
                  + "("
                  + ProtocolProviderFactory.PROTOCOL
                  + "="
                  + ProtocolNames.SIP
                  + ")"
                  + "("
                  + ProtocolProviderFactory.USER_ID
                  + "="
                  + fixture.userID1
                  + ")"
                  + ")");
    } catch (InvalidSyntaxException ex) {
      fail("We apparently got our filter wrong: " + ex.getMessage());
    }

    // make sure we didn't see a service
    assertTrue(
        "A Protocol Provider Service was still regged as an osgi service "
            + "for SIP URI:"
            + fixture.userID1
            + "After it was explicitly uninstalled",
        sipProviderRefs == null || sipProviderRefs.length == 0);

    // verify that the provider factory knows that we have uninstalled the
    // provider.
    assertTrue(
        "The SIP provider factory kept a reference to the provider we just "
            + "uninstalled (uri="
            + fixture.userID1
            + ")",
        fixture.providerFactory.getRegisteredAccounts().isEmpty()
            && fixture.providerFactory.getProviderForAccount(fixture.provider1.getAccountID())
                == null);

    // Now reinstall the bundle
    providerBundle = fixture.bc.installBundle(providerBundle.getLocation());

    // set the global providerBundle reference that we will be using
    // in the last series of tests (Account uninstallation persistency)
    SipSlickFixture.providerBundle = providerBundle;

    assertEquals(
        "Couldn't re-install protocol provider bundle.",
        Bundle.INSTALLED,
        providerBundle.getState());

    AccountManagerUtils.startBundleAndWaitStoredAccountsLoaded(
        fixture.bc, providerBundle, ProtocolNames.SIP);
    assertEquals(
        "Couldn't re-start protocol provider bundle.", Bundle.ACTIVE, providerBundle.getState());

    // Make sure that the provider is there again.
    // verify that the provider is no longer available
    try {
      sipProviderRefs =
          fixture.bc.getServiceReferences(
              ProtocolProviderService.class.getName(),
              "(&"
                  + "("
                  + ProtocolProviderFactory.PROTOCOL
                  + "="
                  + ProtocolNames.SIP
                  + ")"
                  + "("
                  + ProtocolProviderFactory.USER_ID
                  + "="
                  + fixture.userID1
                  + ")"
                  + ")");
    } catch (InvalidSyntaxException ex) {
      fail("We apparently got our filter wrong " + ex.getMessage());
    }

    // make sure we didn't see a service
    assertTrue(
        "A Protocol Provider Service was not restored after being"
            + "reinstalled. SIP URI:"
            + fixture.userID1,
        sipProviderRefs != null && sipProviderRefs.length > 0);

    ServiceReference[] sipFactoryRefs = null;
    try {
      sipFactoryRefs =
          fixture.bc.getServiceReferences(
              ProtocolProviderFactory.class.getName(),
              "(" + ProtocolProviderFactory.PROTOCOL + "=" + ProtocolNames.SIP + ")");
    } catch (InvalidSyntaxException ex) {
      fail("We apparently got our filter wrong " + ex.getMessage());
    }

    // we're the ones who've reinstalled the factory so it's our
    // responsibility to update the fixture.
    fixture.providerFactory = (ProtocolProviderFactory) fixture.bc.getService(sipFactoryRefs[0]);
    fixture.provider1 = (ProtocolProviderService) fixture.bc.getService(sipProviderRefs[0]);

    // verify that the provider is also restored in the provider factory
    // itself
    assertTrue(
        "The SIP provider did not restore its own reference to the provider "
            + "that we just reinstalled (URI="
            + fixture.userID1
            + ")",
        !fixture.providerFactory.getRegisteredAccounts().isEmpty()
            && fixture.providerFactory.getProviderForAccount(fixture.provider1.getAccountID())
                != null);
  }
Example #20
0
  private void setupTrackers(final BundleContext context) throws IOException {

    // initialize service trackers
    eventAdminTracker = new ServiceTracker(context, EventAdmin.class.getName(), null);
    eventAdminTracker.open();
    if (eventAdminTracker.getTrackingCount() == 0 && log != null) {
      log.log(
          LogService.LOG_WARNING,
          "NO EVENT ADMIN FOUND. REMOTE EVENT DELIVERY TEMPORARILY DISABLED."); //$NON-NLS-1$
    }

    try {
      eventHandlerTracker =
          new ServiceTracker(
              context,
              context.createFilter(
                  "(&("
                      + Constants.OBJECTCLASS
                      + "=" //$NON-NLS-1$ //$NON-NLS-2$
                      + EventHandler.class.getName()
                      + ")(!(" //$NON-NLS-1$
                      + R_OSGi_INTERNAL
                      + "=*)))"), //$NON-NLS-1$
              new ServiceTrackerCustomizer() {

                public Object addingService(final ServiceReference reference) {
                  final String[] theTopics =
                      (String[]) reference.getProperty(EventConstants.EVENT_TOPIC);
                  final LeaseUpdateMessage lu = new LeaseUpdateMessage();
                  lu.setType(LeaseUpdateMessage.TOPIC_UPDATE);
                  lu.setServiceID(""); // $NON-NLS-1$
                  lu.setPayload(new Object[] {theTopics, null});
                  updateLeases(lu);

                  return Arrays.asList(theTopics);
                }

                public void modifiedService(
                    final ServiceReference reference, final Object oldTopics) {

                  final List oldTopicList = (List) oldTopics;
                  final List newTopicList =
                      Arrays.asList((String[]) reference.getProperty(EventConstants.EVENT_TOPIC));
                  final Collection removed =
                      CollectionUtils.rightDifference(newTopicList, oldTopicList);
                  final Collection added =
                      CollectionUtils.leftDifference(newTopicList, oldTopicList);
                  final String[] addedTopics = (String[]) added.toArray(new String[removed.size()]);
                  final String[] removedTopics = (String[]) removed.toArray(addedTopics);
                  oldTopicList.removeAll(removed);
                  oldTopicList.addAll(added);
                  final LeaseUpdateMessage lu = new LeaseUpdateMessage();
                  lu.setType(LeaseUpdateMessage.TOPIC_UPDATE);
                  lu.setServiceID(""); // $NON-NLS-1$
                  lu.setPayload(new Object[] {addedTopics, removedTopics});
                  updateLeases(lu);
                }

                public void removedService(
                    final ServiceReference reference, final Object oldTopics) {
                  final List oldTopicsList = (List) oldTopics;
                  final String[] removedTopics =
                      (String[]) oldTopicsList.toArray(new String[oldTopicsList.size()]);
                  final LeaseUpdateMessage lu = new LeaseUpdateMessage();
                  lu.setType(LeaseUpdateMessage.TOPIC_UPDATE);
                  lu.setServiceID(""); // $NON-NLS-1$
                  lu.setPayload(new Object[] {null, removedTopics});
                  updateLeases(lu);
                }
              });
      eventHandlerTracker.open();

      if (DEBUG) {
        log.log(
            LogService.LOG_DEBUG,
            "Local topic space " //$NON-NLS-1$
                + Arrays.asList(getTopics()));
      }

      remoteServiceListenerTracker =
          new ServiceTracker(context, RemoteServiceListener.class.getName(), null);
      remoteServiceListenerTracker.open();

      serviceDiscoveryHandlerTracker =
          new ServiceTracker(
              context,
              ServiceDiscoveryHandler.class.getName(),
              new ServiceTrackerCustomizer() {

                public Object addingService(final ServiceReference reference) {
                  // register all known services for discovery
                  final ServiceDiscoveryHandler handler =
                      (ServiceDiscoveryHandler) context.getService(reference);

                  final RemoteServiceRegistration[] regs =
                      (RemoteServiceRegistration[])
                          serviceRegistrations
                              .values()
                              .toArray(new RemoteServiceRegistration[serviceRegistrations.size()]);

                  for (int i = 0; i < regs.length; i++) {
                    handler.registerService(
                        regs[i].getReference(),
                        regs[i].getProperties(),
                        URI.create(
                            "r-osgi://" //$NON-NLS-1$
                                + RemoteOSGiServiceImpl.MY_ADDRESS
                                + ":" //$NON-NLS-1$
                                + RemoteOSGiServiceImpl.R_OSGI_PORT
                                + "#" //$NON-NLS-1$
                                + regs[i].getServiceID()));
                  }
                  return handler;
                }

                public void modifiedService(
                    final ServiceReference reference, final Object service) {}

                public void removedService(
                    final ServiceReference reference, final Object service) {}
              });
      serviceDiscoveryHandlerTracker.open();

      remoteServiceTracker =
          new ServiceTracker(
              context,
              context.createFilter(
                  "(" //$NON-NLS-1$
                      + RemoteOSGiService.R_OSGi_REGISTRATION
                      + "=*)"),
              new ServiceTrackerCustomizer() { //$NON-NLS-1$

                public Object addingService(final ServiceReference reference) {

                  // FIXME: Surrogates have to be monitored
                  // separately!!!
                  final ServiceReference service =
                      Arrays.asList((String[]) reference.getProperty(Constants.OBJECTCLASS))
                              .contains(SurrogateRegistration.class.getName())
                          ? (ServiceReference)
                              reference.getProperty(SurrogateRegistration.SERVICE_REFERENCE)
                          : reference;

                  try {
                    final RemoteServiceRegistration reg =
                        new RemoteServiceRegistration(reference, service);

                    if (log != null) {
                      log.log(
                          LogService.LOG_INFO,
                          "REGISTERING " //$NON-NLS-1$
                              + reference
                              + " AS PROXIED SERVICES"); //$NON-NLS-1$
                    }

                    serviceRegistrations.put(service, reg);

                    registerWithServiceDiscovery(reg);

                    final LeaseUpdateMessage lu = new LeaseUpdateMessage();
                    lu.setType(LeaseUpdateMessage.SERVICE_ADDED);
                    lu.setServiceID(String.valueOf(reg.getServiceID()));
                    lu.setPayload(new Object[] {reg.getInterfaceNames(), reg.getProperties()});
                    updateLeases(lu);
                    return service;
                  } catch (final ClassNotFoundException e) {
                    e.printStackTrace();
                    throw new RemoteOSGiException("Cannot find class " + service, e); // $NON-NLS-1$
                  }
                }

                public void modifiedService(
                    final ServiceReference reference, final Object service) {
                  if (reference.getProperty(R_OSGi_REGISTRATION) == null) {
                    removedService(reference, service);
                    return;
                  }
                  final RemoteServiceRegistration reg =
                      (RemoteServiceRegistration) serviceRegistrations.get(reference);

                  unregisterFromServiceDiscovery(reg);
                  registerWithServiceDiscovery(reg);

                  final LeaseUpdateMessage lu = new LeaseUpdateMessage();
                  lu.setType(LeaseUpdateMessage.SERVICE_MODIFIED);
                  lu.setServiceID(String.valueOf(reg.getServiceID()));
                  lu.setPayload(new Object[] {null, reg.getProperties()});
                  updateLeases(lu);
                }

                public void removedService(final ServiceReference reference, final Object service) {

                  final ServiceReference sref =
                      Arrays.asList((String[]) reference.getProperty(Constants.OBJECTCLASS))
                              .contains(SurrogateRegistration.class.getName())
                          ? (ServiceReference)
                              reference.getProperty(SurrogateRegistration.SERVICE_REFERENCE)
                          : reference;

                  final RemoteServiceRegistration reg =
                      (RemoteServiceRegistration) serviceRegistrations.remove(sref);

                  unregisterFromServiceDiscovery(reg);

                  final LeaseUpdateMessage lu = new LeaseUpdateMessage();
                  lu.setType(LeaseUpdateMessage.SERVICE_REMOVED);
                  lu.setServiceID(String.valueOf(reg.getServiceID()));
                  lu.setPayload(new Object[] {null, null});
                  updateLeases(lu);
                }
              });
      remoteServiceTracker.open();

      networkChannelFactoryTracker =
          new ServiceTracker(
              context,
              context.createFilter(
                  "("
                      + Constants.OBJECTCLASS
                      + "=" //$NON-NLS-1$ //$NON-NLS-2$
                      + NetworkChannelFactory.class.getName()
                      + ")"),
              new ServiceTrackerCustomizer() { //$NON-NLS-1$

                public Object addingService(final ServiceReference reference) {
                  final NetworkChannelFactory factory =
                      (NetworkChannelFactory) context.getService(reference);
                  try {
                    factory.activate(RemoteOSGiServiceImpl.this);
                  } catch (final IOException ioe) {
                    if (log != null) {
                      log.log(LogService.LOG_ERROR, ioe.getMessage(), ioe);
                    }
                  }
                  return factory;
                }

                public void modifiedService(
                    final ServiceReference reference, final Object factory) {}

                public void removedService(
                    final ServiceReference reference, final Object factory) {}
              });
      networkChannelFactoryTracker.open();

    } catch (final InvalidSyntaxException ise) {
      ise.printStackTrace();
    }
  }
  private void importSettingsCSV(Reader in, final ImportCallback callback) throws IOException {
    final ICsvBeanReader reader = new CsvBeanReader(in, CsvPreference.STANDARD_PREFERENCE);
    final CellProcessor[] processors =
        new CellProcessor[] {
          null,
          new ConvertNullTo(""),
          null,
          new CellProcessor() {

            @Override
            public Object execute(Object arg, CsvContext ctx) {
              Set<net.solarnetwork.node.Setting.SettingFlag> set = null;
              if (arg != null) {
                int mask = Integer.parseInt(arg.toString());
                set = net.solarnetwork.node.Setting.SettingFlag.setForMask(mask);
              }
              return set;
            }
          },
          new org.supercsv.cellprocessor.ParseDate(SETTING_MODIFIED_DATE_FORMAT)
        };
    reader.getHeader(true);
    final List<Setting> importedSettings = new ArrayList<Setting>();
    transactionTemplate.execute(
        new TransactionCallbackWithoutResult() {

          @Override
          protected void doInTransactionWithoutResult(final TransactionStatus status) {
            Setting s;
            try {
              while ((s = reader.read(Setting.class, CSV_HEADERS, processors)) != null) {
                if (!callback.shouldImportSetting(s)) {
                  continue;
                }
                if (s.getKey() == null) {
                  continue;
                }
                if (s.getValue() == null) {
                  settingDao.deleteSetting(s.getKey(), s.getType());
                } else {
                  settingDao.storeSetting(s);
                  importedSettings.add(s);
                }
              }
            } catch (IOException e) {
              log.error("Unable to import settings: {}", e.getMessage());
              status.setRollbackOnly();
            } finally {
              try {
                reader.close();
              } catch (IOException e) {
                // ingore
              }
              if (status.isRollbackOnly()) {
                importedSettings.clear();
              }
            }
          }
        });

    // now that settings have been imported into DAO layer, we need to apply them to the existing
    // runtime

    // first, determine what factories we have... these have keys like <factoryPID>.FACTORY
    final Map<String, Setting> factorySettings = new HashMap<String, Setting>();
    for (Setting s : importedSettings) {
      if (s.getKey() == null || !s.getKey().endsWith(FACTORY_SETTING_KEY_SUFFIX)) {
        continue;
      }
      String factoryPID =
          s.getKey().substring(0, s.getKey().length() - FACTORY_SETTING_KEY_SUFFIX.length());
      log.debug("Discovered imported factory setting {}", factoryPID);
      factorySettings.put(factoryPID, s);

      // Now create the CA configuration for all defined factories, to handle situation where we
      // don't actually
      // configure any custom settings on the factory. In that case we don't have any settings, but
      // we need
      // to instantiate the factory so we create a default instance.
      try {
        int instanceCount = Integer.valueOf(s.getValue());
        for (int i = 1; i <= instanceCount; i++) {
          String instanceKey = String.valueOf(i);
          Configuration conf = getConfiguration(factoryPID, instanceKey);
          @SuppressWarnings("unchecked")
          Dictionary<String, Object> props = conf.getProperties();
          if (props == null) {
            props = new Hashtable<String, Object>();
            props.put(OSGI_PROPERTY_KEY_FACTORY_INSTANCE_KEY, instanceKey);
            conf.update(props);
          }
        }
      } catch (NumberFormatException e) {
        log.warn(
            "Factory {} setting does not have instance count value: {}",
            factoryPID,
            e.getMessage());
      } catch (InvalidSyntaxException e) {
        log.warn("Factory {} setting has invalid syntax: {}", factoryPID, e.getMessage());
      }
    }

    // now convert imported settings into a SettingsCommand, so values are applied to Configuration
    // Admin
    SettingsCommand cmd = new SettingsCommand();

    for (Setting s : importedSettings) {
      if (s.getKey() == null) {
        continue;
      }

      // skip factory instance definitions
      if (s.getKey().endsWith(FACTORY_SETTING_KEY_SUFFIX)) {
        continue;
      }

      // skip things that don't look like CA settings
      if (!CA_PID_PATTERN.matcher(s.getKey()).matches()
          || s.getType() == null
          || SetupSettings.SETUP_TYPE_KEY.equals(s.getType())
          || s.getType().length() < 1) {
        continue;
      }

      SettingValueBean bean = new SettingValueBean();

      // find out if this is a factory
      for (String factoryPID : factorySettings.keySet()) {
        if (s.getKey().startsWith(factoryPID + ".")
            && s.getKey().length() > (factoryPID.length() + 1)) {
          bean.setProviderKey(factoryPID);
          bean.setInstanceKey(s.getKey().substring(factoryPID.length() + 1));
          break;
        }
      }

      if (bean.getProviderKey() == null) {
        // not a factory setting
        bean.setProviderKey(s.getKey());
      }
      bean.setKey(s.getType());
      bean.setValue(s.getValue());
      bean.setTransient(s.getFlags() != null && s.getFlags().contains(SettingFlag.Volatile));
      cmd.getValues().add(bean);
    }
    if (cmd.getValues().size() > 0) {
      updateSettings(cmd);
    }
  }