/**
   * Callback when a {@link SettingSpecifierProvider} has been registered.
   *
   * @param provider the provider object
   * @param properties the service properties
   */
  public void onBind(SettingSpecifierProvider provider, Map<String, ?> properties) {
    log.debug("Bind called on {} with props {}", provider, properties);
    final String pid = provider.getSettingUID();

    List<SettingSpecifierProvider> factoryList = null;
    String factoryInstanceKey = null;
    synchronized (factories) {
      FactoryHelper helper = factories.get(pid);
      if (helper != null) {
        // Note: SERVICE_PID not normally provided by Spring: requires
        // custom SN implementation bundle
        String instancePid = (String) properties.get(Constants.SERVICE_PID);

        Configuration conf;
        try {
          conf = configurationAdmin.getConfiguration(instancePid, null);
          @SuppressWarnings("unchecked")
          Dictionary<String, ?> props = conf.getProperties();
          if (props != null) {
            factoryInstanceKey = (String) props.get(OSGI_PROPERTY_KEY_FACTORY_INSTANCE_KEY);
            log.debug("Got factory {} instance key {}", pid, factoryInstanceKey);

            factoryList = helper.getInstanceProviders(factoryInstanceKey);
            factoryList.add(provider);
          }
        } catch (IOException e) {
          log.error("Error getting factory instance configuration {}", instancePid, e);
        }
      }
    }

    if (factoryList == null) {
      synchronized (providers) {
        providers.put(pid, provider);
      }
    }

    final String settingKey = getFactoryInstanceSettingKey(pid, factoryInstanceKey);

    List<KeyValuePair> settings = settingDao.getSettings(settingKey);
    if (settings.size() < 1) {
      return;
    }
    SettingsCommand cmd = new SettingsCommand();
    for (KeyValuePair pair : settings) {
      SettingValueBean bean = new SettingValueBean();
      bean.setProviderKey(provider.getSettingUID());
      bean.setInstanceKey(factoryInstanceKey);
      bean.setKey(pair.getKey());
      bean.setValue(pair.getValue());
      cmd.getValues().add(bean);
    }
    updateSettings(cmd);
  }
 @Override
 public Object getSettingValue(SettingSpecifierProvider provider, SettingSpecifier setting) {
   if (setting instanceof KeyedSettingSpecifier<?>) {
     KeyedSettingSpecifier<?> keyedSetting = (KeyedSettingSpecifier<?>) setting;
     if (keyedSetting.isTransient()) {
       return keyedSetting.getDefaultValue();
     }
     final String providerUID = provider.getSettingUID();
     final String instanceUID =
         (provider instanceof FactorySettingSpecifierProvider
             ? ((FactorySettingSpecifierProvider) provider).getFactoryInstanceUID()
             : null);
     try {
       Configuration conf = getConfiguration(providerUID, instanceUID);
       @SuppressWarnings("unchecked")
       Dictionary<String, ?> props = conf.getProperties();
       Object val = (props == null ? null : props.get(keyedSetting.getKey()));
       if (val == null) {
         val = keyedSetting.getDefaultValue();
       }
       return val;
     } catch (IOException e) {
       throw new RuntimeException(e);
     } catch (InvalidSyntaxException e) {
       throw new RuntimeException(e);
     }
   }
   return null;
 }
  /**
   * Callback when a {@link SettingSpecifierProvider} has been un-registered.
   *
   * @param config the configuration object
   * @param properties the service properties
   */
  public void onUnbind(SettingSpecifierProvider provider, Map<String, ?> properties) {
    if (provider == null) {
      // gemini blueprint calls this when availability="optional" and there are no services
      return;
    }
    log.debug("Unbind called on {} with props {}", provider, properties);
    final String pid = provider.getSettingUID();

    synchronized (factories) {
      FactoryHelper helper = factories.get(pid);
      if (helper != null) {
        helper.removeProvider(provider);
        return;
      }
    }

    synchronized (providers) {
      providers.remove(pid);
    }
  }