/** * 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); } }