/** * Callback when a {@link SettingSpecifierProviderFactory} has been registered. * * @param provider the provider object * @param properties the service properties */ public void onBindFactory(SettingSpecifierProviderFactory provider, Map<String, ?> properties) { log.debug("Bind called on factory {} with props {}", provider, properties); final String factoryPid = provider.getFactoryUID(); synchronized (factories) { factories.put(factoryPid, new FactoryHelper(provider)); // find all configured factory instances, and publish those // configurations now. First we look up all registered factory // instances, so each returned result returns a configured instance // key List<KeyValuePair> instanceKeys = settingDao.getSettings(getFactorySettingKey(factoryPid)); for (KeyValuePair instanceKey : instanceKeys) { SettingsCommand cmd = new SettingsCommand(); cmd.setProviderKey(factoryPid); cmd.setInstanceKey(instanceKey.getKey()); // now lookup all settings for the configured instance List<KeyValuePair> settings = settingDao.getSettings(getFactoryInstanceSettingKey(factoryPid, instanceKey.getKey())); for (KeyValuePair setting : settings) { SettingValueBean bean = new SettingValueBean(); bean.setKey(setting.getKey()); bean.setValue(setting.getValue()); cmd.getValues().add(bean); } updateSettings(cmd); } } }
/** * 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); }
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); } }
@SuppressWarnings("unchecked") @Override public void updateSettings(SettingsCommand command) { // group all updates by provider+instance, to reduce the number of CA updates // when multiple settings are changed if (command.getProviderKey() == null) { Map<String, SettingsCommand> groups = new LinkedHashMap<String, SettingsCommand>(8); Map<String, SettingsCommand> indexedGroups = null; for (SettingValueBean bean : command.getValues()) { String groupKey = bean.getProviderKey() + (bean.getInstanceKey() == null ? "" : bean.getInstanceKey()); final boolean indexed = INDEXED_PROP_PATTERN.matcher(bean.getKey()).find(); SettingsCommand cmd = null; if (indexed) { // indexed property, add in indexed groups if (indexedGroups == null) { indexedGroups = new LinkedHashMap<String, SettingsCommand>(8); } cmd = indexedGroups.get(groupKey); } else { cmd = groups.get(groupKey); } if (cmd == null) { cmd = new SettingsCommand(); cmd.setProviderKey(bean.getProviderKey()); cmd.setInstanceKey(bean.getInstanceKey()); if (indexed) { indexedGroups.put(groupKey, cmd); } else { groups.put(groupKey, cmd); } } cmd.getValues().add(bean); } for (SettingsCommand cmd : groups.values()) { updateSettings(cmd); } if (indexedGroups != null) { for (SettingsCommand cmd : indexedGroups.values()) { updateSettings(cmd); } } return; } try { Configuration conf = getConfiguration(command.getProviderKey(), command.getInstanceKey()); Dictionary<String, Object> props = conf.getProperties(); if (props == null) { props = new Hashtable<String, Object>(); } for (SettingValueBean bean : command.getValues()) { String settingKey = command.getProviderKey(); String instanceKey = command.getInstanceKey(); if (instanceKey != null) { settingKey = getFactoryInstanceSettingKey(settingKey, instanceKey); } if (bean.isRemove()) { props.remove(bean.getKey()); } else { props.put(bean.getKey(), bean.getValue()); } if (!bean.isTransient()) { if (bean.isRemove()) { settingDao.deleteSetting(settingKey, bean.getKey()); } else { settingDao.storeSetting(settingKey, bean.getKey(), bean.getValue()); } } } if (conf != null && props != null) { if (command.getInstanceKey() != null) { props.put(OSGI_PROPERTY_KEY_FACTORY_INSTANCE_KEY, command.getInstanceKey()); } conf.update(props); } } catch (IOException e) { throw new RuntimeException(e); } catch (InvalidSyntaxException e) { throw new RuntimeException(e); } }