@Test
  public void test_static_binding() throws BundleException {
    final String pid = "test_static_binding";

    // install a bundle to get a location for binding
    bundle = installBundle(pid);
    final String location = bundle.getLocation();

    // create and statically bind the configuration
    configure(pid);
    final Configuration config = getConfiguration(pid);
    TestCase.assertEquals(pid, config.getPid());
    TestCase.assertNull(config.getBundleLocation());
    config.setBundleLocation(location);
    TestCase.assertEquals(location, config.getBundleLocation());

    // ensure configuration is settled before starting the bundle
    delay();

    // start the bundle
    bundle.start();
    delay();
    TestCase.assertEquals(location, config.getBundleLocation());

    // assert the configuration is supplied
    final ManagedServiceTestActivator tester = ManagedServiceTestActivator.INSTANCE;
    TestCase.assertNotNull("Activator not started !!", tester);
    TestCase.assertNotNull("Expect Properties after Service Registration", tester.props);
    TestCase.assertEquals("Expect a single update call", 1, tester.numManagedServiceUpdatedCalls);

    // remove the static binding and assert still bound
    config.setBundleLocation(null);
    TestCase.assertEquals(location, config.getBundleLocation());

    // uninstall bundle and assert configuration unbound
    bundle.uninstall();
    bundle = null;
    delay();
    TestCase.assertNull(config.getBundleLocation());
  }
  @Test
  public void test_static_binding_and_unbinding() throws BundleException {
    final String pid = "test_static_binding_and_unbinding";
    final String location = bundleContext.getBundle().getLocation();

    // create and statically bind the configuration
    configure(pid);
    final Configuration config = getConfiguration(pid);
    TestCase.assertEquals(pid, config.getPid());
    TestCase.assertNull(config.getBundleLocation());

    // bind the configuration
    config.setBundleLocation(location);
    TestCase.assertEquals(location, config.getBundleLocation());

    // restart CM bundle
    final Bundle cmBundle = getCmBundle();
    cmBundle.stop();
    delay();
    cmBundle.start();

    // assert configuration still bound
    final Configuration configAfterRestart = getConfiguration(pid);
    TestCase.assertEquals(pid, configAfterRestart.getPid());
    TestCase.assertEquals(location, configAfterRestart.getBundleLocation());

    // unbind the configuration
    configAfterRestart.setBundleLocation(null);
    TestCase.assertNull(configAfterRestart.getBundleLocation());

    // restart CM bundle
    cmBundle.stop();
    delay();
    cmBundle.start();

    // assert configuration unbound
    final Configuration configUnboundAfterRestart = getConfiguration(pid);
    TestCase.assertEquals(pid, configUnboundAfterRestart.getPid());
    TestCase.assertNull(configUnboundAfterRestart.getBundleLocation());
  }
  @Test
  public void test_create_with_location_unbind_before_service_supply()
      throws BundleException, IOException {

    final String pid = "test_create_with_location_unbind_before_service_supply";
    final String dummyLocation = "http://some/dummy/location";

    // 1. create and statically bind the configuration
    final Configuration config = configure(pid, dummyLocation, false);
    TestCase.assertEquals(pid, config.getPid());
    TestCase.assertEquals(dummyLocation, config.getBundleLocation());

    // 2. update configuration
    Hashtable<String, String> props = new Hashtable<String, String>();
    props.put(PROP_NAME, PROP_NAME);
    config.update(props);
    TestCase.assertEquals(PROP_NAME, config.getProperties().get(PROP_NAME));
    TestCase.assertEquals(pid, config.getPid());
    TestCase.assertEquals(dummyLocation, config.getBundleLocation());

    // 3. (statically) set location to null
    config.setBundleLocation(null);
    TestCase.assertNull(config.getBundleLocation());

    // 4. install bundle with service
    bundle = installBundle(pid);
    bundle.start();
    delay();

    final ManagedServiceTestActivator tester = ManagedServiceTestActivator.INSTANCE;
    TestCase.assertNotNull("Activator not started !!", tester);

    // assert activater has configuration (two calls, one per pid)
    TestCase.assertNotNull("Expect Properties after Service Registration", tester.props);
    TestCase.assertEquals("Expect a single update call", 1, tester.numManagedServiceUpdatedCalls);

    TestCase.assertEquals(bundle.getLocation(), config.getBundleLocation());

    bundle.uninstall();
    bundle = null;

    delay();

    // statically bound configurations must remain bound after bundle
    // uninstall
    TestCase.assertNull(config.getBundleLocation());

    // remove the configuration for good
    deleteConfig(pid);
  }
  @Test
  public void test_statically_bound() throws BundleException {
    final String pid = "test_statically_bound";

    // install the bundle (we need the location)
    bundle = installBundle(pid);
    final String location = bundle.getLocation();

    // create and statically bind the configuration
    configure(pid);
    final Configuration config = getConfiguration(pid);
    TestCase.assertEquals(pid, config.getPid());
    TestCase.assertNull(config.getBundleLocation());
    config.setBundleLocation(location);
    TestCase.assertEquals(location, config.getBundleLocation());

    // ensure configuration is settled before starting the bundle
    delay();

    bundle.start();

    // give cm time for distribution
    delay();

    final ManagedServiceTestActivator tester = ManagedServiceTestActivator.INSTANCE;
    TestCase.assertNotNull("Activator not started !!", tester);

    // assert activater has configuration (two calls, one per pid)
    TestCase.assertNotNull("Expect Properties after Service Registration", tester.props);
    TestCase.assertEquals("Expect a single update call", 1, tester.numManagedServiceUpdatedCalls);

    TestCase.assertEquals(location, config.getBundleLocation());

    bundle.uninstall();
    bundle = null;

    delay();

    // statically bound configurations must remain bound after bundle
    // uninstall
    TestCase.assertEquals(location, config.getBundleLocation());

    // remove the configuration for good
    deleteConfig(pid);
  }
  public void createLocalServer(int port, CreateEnsembleOptions options) {
    try {
      IZKClient client;
      Hashtable<String, Object> properties;
      String version = ZkDefs.DEFAULT_VERSION;
      String karafName = System.getProperty(SystemProperties.KARAF_NAME);
      String minimumPort = System.getProperty(ZkDefs.MINIMUM_PORT);
      String maximumPort = System.getProperty(ZkDefs.MAXIMUM_PORT);
      int mappedPort = mapPortToRange(port, minimumPort, maximumPort);

      if (options.getZookeeperPassword() != null) {
        // do nothing
      } else if (System.getProperties().containsKey(SystemProperties.ZOOKEEPER_PASSWORD)) {
        options.setZookeeperPassword(System.getProperty(SystemProperties.ZOOKEEPER_PASSWORD));
      } else {
        options.setZookeeperPassword(ZooKeeperRetriableUtils.generatePassword());
      }

      // Install or stop the fabric-configadmin bridge
      Bundle bundleFabricAgent =
          findAndStopBundle(bundleContext, "org.fusesource.fabric.fabric-agent");
      Bundle bundleFabricConfigAdmin =
          installOrStopBundle(
              bundleContext,
              "org.fusesource.fabric.fabric-configadmin",
              "mvn:org.fusesource.fabric/fabric-configadmin/" + FabricConstants.FABRIC_VERSION);
      Bundle bundleFabricZooKeeper =
          installOrStopBundle(
              bundleContext,
              "org.fusesource.fabric.fabric-zookeeper",
              "mvn:org.fusesource.fabric/fabric-zookeeper/" + FabricConstants.FABRIC_VERSION);
      Bundle bundleFabricJaas =
          installOrStopBundle(
              bundleContext,
              "org.fusesource.fabric.fabric-jaas  ",
              "mvn:org.fusesource.fabric/fabric-jaas/" + FabricConstants.FABRIC_VERSION);
      Bundle bundleFabricCommands =
          installOrStopBundle(
              bundleContext,
              "org.fusesource.fabric.fabric-commands  ",
              "mvn:org.fusesource.fabric/fabric-commands/" + FabricConstants.FABRIC_VERSION);
      Bundle bundleFabricMavenProxy =
          installOrStopBundle(
              bundleContext,
              "org.fusesource.fabric.fabric-commands  ",
              "mvn:org.fusesource.fabric/fabric-maven-proxy/" + FabricConstants.FABRIC_VERSION);

      // Create configuration
      String connectionUrl = HostUtils.getLocalHostName() + ":" + Integer.toString(mappedPort);

      String autoImportFrom = System.getProperty(SystemProperties.PROFILES_AUTOIMPORT_PATH);

      Configuration config =
          configurationAdmin.createFactoryConfiguration("org.fusesource.fabric.zookeeper.server");
      properties = new Hashtable<String, Object>();
      if (autoImportFrom != null) {
        loadPropertiesFrom(
            properties,
            autoImportFrom
                + "/fabric/configs/versions/1.0/profiles/default/org.fusesource.fabric.zookeeper.server.properties");
      }
      properties.put("tickTime", "2000");
      properties.put("initLimit", "10");
      properties.put("syncLimit", "5");
      properties.put("dataDir", "data/zookeeper/0000");
      properties.put("clientPort", Integer.toString(mappedPort));
      properties.put("fabric.zookeeper.pid", "org.fusesource.fabric.zookeeper.server-0000");
      config.setBundleLocation(null);
      config.update(properties);

      // Update the client configuration
      config = configurationAdmin.getConfiguration("org.fusesource.fabric.zookeeper");
      properties = new Hashtable<String, Object>();
      if (autoImportFrom != null) {
        loadPropertiesFrom(
            properties,
            autoImportFrom
                + "/fabric/configs/versions/1.0/profiles/default/org.fusesource.fabric.zookeeper.properties");
      }
      properties.put("zookeeper.url", connectionUrl);
      properties.put(
          "zookeeper.timeout",
          System.getProperties().containsKey("zookeeper.timeout")
              ? System.getProperties().getProperty("zookeeper.timeout")
              : "30000");
      properties.put("fabric.zookeeper.pid", "org.fusesource.fabric.zookeeper");
      properties.put("zookeeper.password", options.getZookeeperPassword());
      config.setBundleLocation(null);
      config.update(properties);

      // Start fabric-zookeeper bundle
      bundleFabricZooKeeper.start();

      // Wait for the client to be available
      ServiceTracker tracker = new ServiceTracker(bundleContext, IZKClient.class.getName(), null);
      tracker.open();
      client = (IZKClient) tracker.waitForService(5000);
      if (client == null) {
        throw new IllegalStateException("Timeout waiting for ZooKeeper client to be registered");
      }
      tracker.close();
      client.waitForConnected();

      // Import data into zookeeper
      if (autoImportFrom != null) {
        getDataStore().importFromFileSystem(autoImportFrom);
      }

      getDataStore().setDefaultVersion(version);

      // configure default profile
      String defaultProfile = getDataStore().getProfile(version, "default", true);

      ZooKeeperRetriableUtils.set(
          client,
          ZkPath.CONFIG_ENSEMBLE_URL.getPath(),
          "${zk:" + karafName + "/ip}:" + Integer.toString(mappedPort));
      ZooKeeperRetriableUtils.set(
          client, ZkPath.CONFIG_ENSEMBLE_PASSWORD.getPath(), options.getZookeeperPassword());

      Properties zkProps = new Properties();
      zkProps.setProperty("zookeeper.url", "${zk:" + ZkPath.CONFIG_ENSEMBLE_URL.getPath() + "}");
      zkProps.setProperty(
          "zookeeper.password", "${zk:" + ZkPath.CONFIG_ENSEMBLE_PASSWORD.getPath() + "}");
      getDataStore()
          .setFileConfiguration(
              version,
              defaultProfile,
              "org.fusesource.fabric.zookeeper.properties",
              DataStoreHelpers.toBytes(zkProps));

      // configure the ensemble
      String ensembleProfile = getDataStore().getProfile(version, "fabric-ensemble-0000", true);
      getDataStore().setProfileAttribute(version, ensembleProfile, "abstract", "true");
      getDataStore().setProfileAttribute(version, ensembleProfile, "hidden", "true");

      Properties ensembleProps = new Properties();
      ensembleProps.put("tickTime", "2000");
      ensembleProps.put("initLimit", "10");
      ensembleProps.put("syncLimit", "5");
      ensembleProps.put("dataDir", "data/zookeeper/0000");

      loadPropertiesFrom(
          ensembleProps,
          autoImportFrom
              + "/fabric/configs/versions/1.0/profiles/default/org.fusesource.fabric.zookeeper.server.properties");
      getDataStore()
          .setFileConfiguration(
              version,
              ensembleProfile,
              "org.fusesource.fabric.zookeeper.server-0000.properties",
              DataStoreHelpers.toBytes(ensembleProps));

      // configure this server in the ensemble
      String ensembleServerProfile =
          getDataStore().getProfile(version, "fabric-ensemble-0000-1", true);
      getDataStore().setProfileAttribute(version, ensembleServerProfile, "hidden", "true");
      getDataStore()
          .setProfileAttribute(version, ensembleServerProfile, "parents", ensembleProfile);
      Properties serverProps = new Properties();
      serverProps.put("clientPort", String.valueOf(mappedPort));
      getDataStore()
          .setFileConfiguration(
              version,
              ensembleServerProfile,
              "org.fusesource.fabric.zookeeper.server-0000.properties",
              DataStoreHelpers.toBytes(serverProps));

      ZooKeeperRetriableUtils.set(client, ZkPath.CONFIG_ENSEMBLES.getPath(), "0000");
      ZooKeeperRetriableUtils.set(client, ZkPath.CONFIG_ENSEMBLE.getPath("0000"), karafName);

      // configure fabric profile
      String fabricProfile = getDataStore().getProfile(version, "fabric", true);
      Properties agentProps =
          DataStoreHelpers.toProperties(
              getDataStore()
                  .getFileConfiguration(
                      version, fabricProfile, "org.fusesource.fabric.agent.properties"));
      agentProps.put("feature.fabric-commands", "fabric-commands");
      getDataStore()
          .setFileConfiguration(
              version,
              "fabric",
              "org.fusesource.fabric.agent.properties",
              DataStoreHelpers.toBytes(agentProps));

      ZooKeeperRetriableUtils.createDefault(
          client, ZkPath.CONFIG_CONTAINER.getPath(karafName), version);
      String assignedProfile = System.getProperty(SystemProperties.PROFILE);
      if (assignedProfile != null
          && !assignedProfile.isEmpty()
          && !"fabric".equals(assignedProfile)) {
        ZooKeeperRetriableUtils.createDefault(
            client,
            ZkPath.CONFIG_VERSIONS_CONTAINER.getPath(version, karafName),
            "fabric fabric-ensemble-0000-1 " + assignedProfile);
      } else {
        ZooKeeperRetriableUtils.createDefault(
            client,
            ZkPath.CONFIG_VERSIONS_CONTAINER.getPath(version, karafName),
            "fabric fabric-ensemble-0000-1");
      }

      // add auth
      Map<String, String> configs = new HashMap<String, String>();
      configs.put("encryption.enabled", "${zk:/fabric/authentication/encryption.enabled}");
      getDataStore()
          .setConfiguration(version, defaultProfile, "org.fusesource.fabric.jaas", configs);

      // outside of the profile storage area, so we'll keep these in zk
      ZooKeeperRetriableUtils.createDefault(
          client, "/fabric/authentication/encryption.enabled", "true");
      ZooKeeperRetriableUtils.createDefault(client, "/fabric/authentication/domain", "karaf");
      addUsersToZookeeper(client, options.getUsers());

      ZooKeeperRetriableUtils.createDefault(
          client, ZkPath.AUTHENTICATION_CRYPT_ALGORITHM.getPath(), "PBEWithMD5AndDES");
      ZooKeeperRetriableUtils.createDefault(
          client, ZkPath.AUTHENTICATION_CRYPT_PASSWORD.getPath(), options.getZookeeperPassword());

      // Fix acls
      ZookeeperCommandBuilder.fixAcls("/", true).execute(client);

      // Reset the autostart flag
      if (ensembleAutoStart) {
        System.setProperty(SystemProperties.ENSEMBLE_AUTOSTART, Boolean.FALSE.toString());
        File file = new File(System.getProperty("karaf.base") + "/etc/system.properties");
        org.apache.felix.utils.properties.Properties props =
            new org.apache.felix.utils.properties.Properties(file);
        props.put(SystemProperties.ENSEMBLE_AUTOSTART, Boolean.FALSE.toString());
        props.save();
      }

      // Restart fabric-configadmin bridge
      bundleFabricConfigAdmin.start();
      bundleFabricJaas.start();
      bundleFabricCommands.start();
      bundleFabricMavenProxy.start();

      // Check if the agent is configured to auto start.
      if (!System.getProperties().containsKey(SystemProperties.AGENT_AUTOSTART)
          || Boolean.parseBoolean(System.getProperty(SystemProperties.AGENT_AUTOSTART))) {
        bundleFabricAgent =
            findOrInstallBundle(
                bundleContext,
                "org.fusesource.fabric.fabric-agent  ",
                "mvn:org.fusesource.fabric/fabric-agent/" + FabricConstants.FABRIC_VERSION);
        bundleFabricAgent.start();
      }
    } catch (Exception e) {
      throw new FabricException("Unable to create zookeeper server configuration", e);
    }
  }
  @Test
  public void test_switch_dynamic_binding_factory() throws BundleException, IOException {
    // 1. create config with pid and locationA
    // 2. update config with properties
    final String factoryPid = "test_switch_static_binding_factory";
    final String locationA = "test:location/A/" + factoryPid;
    final Configuration config = createFactoryConfiguration(factoryPid, null, true);
    final String pid = config.getPid();

    TestCase.assertNull(config.getBundleLocation());

    // 3. register ManagedService ms1 with pid from said locationA
    final Bundle bundleA =
        installBundle(factoryPid, ManagedServiceFactoryTestActivator.class, locationA);
    bundleA.start();
    delay();

    // ==> configuration supplied to the service ms1
    final ManagedServiceFactoryTestActivator testerA1 = ManagedServiceFactoryTestActivator.INSTANCE;
    TestCase.assertNotNull(testerA1.configs.get(pid));
    TestCase.assertEquals(1, testerA1.numManagedServiceFactoryUpdatedCalls);
    TestCase.assertEquals(locationA, config.getBundleLocation());

    // 4. register ManagedService ms2 with pid from locationB
    final String locationB = "test:location/B/" + factoryPid;
    final Bundle bundleB =
        installBundle(factoryPid, ManagedServiceFactoryTestActivator2.class, locationB);
    bundleB.start();
    delay();

    // ==> configuration not supplied to service ms2
    final ManagedServiceFactoryTestActivator2 testerB1 =
        ManagedServiceFactoryTestActivator2.INSTANCE;
    TestCase.assertNull(testerB1.configs.get(pid));
    TestCase.assertEquals(0, testerB1.numManagedServiceFactoryUpdatedCalls);
    TestCase.assertEquals(locationA, config.getBundleLocation());

    // 5. Call Configuration.setBundleLocation( "locationB" )
    config.setBundleLocation(locationB);
    delay();

    // ==> configuration is bound to locationB
    TestCase.assertEquals(locationB, config.getBundleLocation());

    /*
     * According to BJ Hargrave configuration is not re-dispatched
     * due to setting the bundle location.
     * <p>
     * Therefore, we have two sets one with re-dispatch expectation and
     * one without re-dispatch expectation.
     */
    if (REDISPATCH_CONFIGURATION_ON_SET_BUNDLE_LOCATION) {
      // ==> configuration removed from service ms1
      TestCase.assertNull(testerA1.configs.get(pid));
      TestCase.assertEquals(1, testerA1.numManagedServiceFactoryUpdatedCalls);
      TestCase.assertEquals(1, testerA1.numManagedServiceFactoryDeleteCalls);

      // ==> configuration supplied to the service ms2
      TestCase.assertNotNull(testerB1.configs.get(pid));
      TestCase.assertEquals(1, testerB1.numManagedServiceFactoryUpdatedCalls);
    } else {
      // ==> configuration not removed from service ms1
      TestCase.assertNotNull(testerA1.configs.get(pid));
      TestCase.assertEquals(1, testerA1.numManagedServiceFactoryUpdatedCalls);
      TestCase.assertEquals(0, testerA1.numManagedServiceFactoryDeleteCalls);

      // ==> configuration not supplied to the service ms2
      TestCase.assertNull(testerB1.configs.get(pid));
      TestCase.assertEquals(0, testerB1.numManagedServiceFactoryUpdatedCalls);
    }

    // 6. Update configuration now
    config.update();
    delay();

    // ==> configuration supplied to the service ms2
    TestCase.assertNotNull(testerB1.configs.get(pid));
    TestCase.assertEquals(1, testerB1.numManagedServiceFactoryUpdatedCalls);
  }