/**
* Copyright (c) Codice Foundation
* <p>
* This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. A copy of the GNU Lesser General Public License
* is distributed along with this program and can be found at
* <http://www.gnu.org/licenses/lgpl.html>.
*/
package org.codice.ddf.registry.source.configuration;
import java.io.IOException;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.codice.ddf.parser.ParserException;
import org.codice.ddf.registry.common.RegistryConstants;
import org.codice.ddf.registry.common.metacard.RegistryUtility;
import org.codice.ddf.registry.federationadmin.service.internal.FederationAdminException;
import org.codice.ddf.registry.federationadmin.service.internal.FederationAdminService;
import org.codice.ddf.registry.federationadmin.service.internal.RegistrySourceConfiguration;
import org.codice.ddf.registry.schemabindings.helper.MetacardMarshaller;
import org.codice.ddf.registry.schemabindings.helper.RegistryPackageTypeHelper;
import org.codice.ddf.registry.schemabindings.helper.SlotTypeHelper;
import org.codice.ddf.security.common.Security;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;
import org.osgi.service.metatype.AttributeDefinition;
import org.osgi.service.metatype.MetaTypeInformation;
import org.osgi.service.metatype.MetaTypeService;
import org.osgi.service.metatype.ObjectClassDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ddf.catalog.data.Metacard;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import oasis.names.tc.ebxml_regrep.xsd.rim._3.ServiceBindingType;
import oasis.names.tc.ebxml_regrep.xsd.rim._3.SlotType1;
/**
* This handler class is responsible for the create/update/delete of source configurations that
* come from registry nodes. It listens to the create/update/delete events to trigger its logic.
*/
@SuppressFBWarnings("IS2_INCONSISTENT_SYNC")
public class SourceConfigurationHandler implements EventHandler, RegistrySourceConfiguration {
private static final Logger LOGGER = LoggerFactory.getLogger(SourceConfigurationHandler.class);
private static final String METACARD_PROPERTY = "ddf.catalog.event.metacard";
private static final String BINDING_TYPE = "bindingType";
private static final String DISABLED_CONFIGURATION_SUFFIX = "_disabled";
private static final String ID = "id";
private static final String SHORTNAME = "shortname";
private static final String CONFIGURATION_FILTER =
"(&(%s=%s)(|(service.factoryPid=*source*)(service.factoryPid=*Source*)(service.factoryPid=*service*)(service.factoryPid=*Service*)))";
private static final String CREATED_TOPIC = "ddf/catalog/event/CREATED";
private static final String UPDATED_TOPIC = "ddf/catalog/event/UPDATED";
private static final String DELETED_TOPIC = "ddf/catalog/event/DELETED";
private static final int SHUTDOWN_TIMEOUT_SECONDS = 60;
private ConfigurationAdmin configurationAdmin;
private FederationAdminService federationAdminService;
private MetaTypeService metaTypeService;
private MetacardMarshaller metacardMarshaller;
private ExecutorService executor;
private String urlBindingName;
private Map<String, String> bindingTypeToFactoryPidMap = new ConcurrentHashMap<>();
private List<String> sourceActivationPriorityOrder = new CopyOnWriteArrayList<>();
private boolean activateConfigurations;
private boolean preserveActiveConfigurations;
private boolean cleanUpOnDelete;
private SlotTypeHelper slotHelper;
private RegistryPackageTypeHelper registryTypeHelper;
public SourceConfigurationHandler(FederationAdminService federationAdminService,
ExecutorService executor) {
this.federationAdminService = federationAdminService;
this.executor = executor;
}
public void destroy() {
executor.shutdown();
try {
if (!executor.awaitTermination(SHUTDOWN_TIMEOUT_SECONDS, TimeUnit.SECONDS)) {
executor.shutdownNow();
if (!executor.awaitTermination(SHUTDOWN_TIMEOUT_SECONDS, TimeUnit.SECONDS)) {
LOGGER.debug("Thread pool didn't terminate");
}
}
} catch (InterruptedException e) {
executor.shutdownNow();
}
}
@Override
public void handleEvent(Event event) {
Metacard mcard = (Metacard) event.getProperty(METACARD_PROPERTY);
if (mcard == null || !RegistryUtility.isRegistryMetacard(mcard)
|| RegistryUtility.isIdentityNode(mcard)) {
return;
}
executor.execute(() -> {
if (event.getTopic()
.equals(CREATED_TOPIC)) {
processCreate(mcard);
} else if (event.getTopic()
.equals(UPDATED_TOPIC)) {
processUpdate(mcard);
} else if (event.getTopic()
.equals(DELETED_TOPIC)) {
processDelete(mcard);
}
});
}
private void processCreate(Metacard metacard) {
try {
updateRegistryConfigurations(metacard, true);
} catch (IOException | InvalidSyntaxException | ParserException | RuntimeException e) {
LOGGER.debug("Unable to update registry configurations, metacard still ingested");
}
}
private void processUpdate(Metacard metacard) {
try {
updateRegistryConfigurations(metacard, false);
} catch (IOException | InvalidSyntaxException | ParserException | RuntimeException e) {
LOGGER.debug("Unable to update registry configurations, metacard still updated");
}
}
private void processDelete(Metacard metacard) {
try {
if (cleanUpOnDelete) {
deleteRegistryConfigurations(metacard);
}
} catch (IOException | InvalidSyntaxException e) {
LOGGER.debug("Unable to delete registry configurations, metacard still deleted");
}
}
/**
* Finds all source configurations associated with the registry metacard creates/updates them
* with the information in the metacards service bindings. This method will enable/disable
* configurations if the right conditions are met but will never delete a configuration other
* than for switching a configuration from enabled to disabled or vice-versa
*
* @param metacard Registry metacard with new service binding info
* @param activationHint Flag indicating if the created/updated configuration should be activated.
* Configuration activation is not determined solely on this field but in
* conjunction with {@see setActivateConfigurations} and {@see setPreserveActiveConfigurations}.
* @throws IOException
* @throws InvalidSyntaxException
* @throws ParserException
*/
private synchronized void updateRegistryConfigurations(Metacard metacard,
boolean activationHint) throws IOException, InvalidSyntaxException, ParserException {
if (RegistryUtility.isIdentityNode(metacard)) {
return;
}
boolean autoActivateConfigurations =
activateConfigurations && (activationHint || !preserveActiveConfigurations);
List<ServiceBindingType> bindingTypes = registryTypeHelper.getBindingTypes(
metacardMarshaller.getRegistryPackageFromMetacard(metacard));
String registryId = RegistryUtility.getRegistryId(metacard);
String configId = getDeconflictedConfigId(metacard.getTitle(), registryId);
Map<String, Configuration> fpidToConfigurationMap = getCurrentConfigurations(registryId);
String bindingTypeToActivate = "";
if (autoActivateConfigurations) {
bindingTypeToActivate = getBindingTypeToActivate(bindingTypes);
if (StringUtils.isNotEmpty(bindingTypeToActivate)) {
String fPidToActivate = bindingTypeToFactoryPidMap.get(bindingTypeToActivate);
activateDeactivateExistingConfiguration(fPidToActivate,
fpidToConfigurationMap,
bindingTypeToActivate);
}
}
for (ServiceBindingType bindingType : bindingTypes) {
Map<String, Object> slotMap = this.getServiceBindingProperties(bindingType);
String factoryPidMask = (String) slotMap.get(BINDING_TYPE);
if (factoryPidMask == null) {
continue;
}
String factoryPid = bindingTypeToFactoryPidMap.get(factoryPidMask);
if (StringUtils.isBlank(factoryPid)) {
continue;
}
Configuration curConfig = findOrCreateConfig(factoryPid,
fpidToConfigurationMap,
factoryPidMask,
(autoActivateConfigurations && factoryPidMask.equals(bindingTypeToActivate)));
Hashtable<String, Object> serviceConfigurationProperties = new Hashtable<>();
if (fpidToConfigurationMap.containsKey(curConfig.getFactoryPid()
.concat(getConfigStringProperty(curConfig, BINDING_TYPE)))) {
serviceConfigurationProperties.putAll(getConfigurationsFromDictionary(curConfig.getProperties()));
} else {
serviceConfigurationProperties.putAll(getMetatypeDefaults(factoryPid));
}
serviceConfigurationProperties.putAll(slotMap);
serviceConfigurationProperties.put(ID, configId);
serviceConfigurationProperties.put(SHORTNAME, configId);
serviceConfigurationProperties.put(RegistryConstants.CONFIGURATION_REGISTRY_ID_PROPERTY,
registryId);
curConfig.update(serviceConfigurationProperties);
fpidToConfigurationMap.remove(curConfig.getFactoryPid()
.concat(factoryPidMask));
}
//if a binding was removed the configuration could still exist, If the registry
//entry gets renamed the non-binding configs will not get renamed appropriately so we
//go through them here and make sure the name is set correctly.
fpidToConfigurationMap.values()
.stream()
.forEach(config -> {
try {
Dictionary<String, Object> properties = config.getProperties();
properties.put(ID, configId);
properties.put(SHORTNAME, configId);
config.update(properties);
} catch (IOException e) {
LOGGER.debug("Could not remove configuration for {}:{}",
config.getProperties()
.get(ID),
config.getFactoryPid());
}
});
}
/**
* Finds a configuration in the map of current configurations or creates a new one if one doesn't
* exist yet.
*
* @param factoryPid The factory pid to lookup/create
* @param fpidToConfigurationMap Map containing current configurations
* @param createActiveConfig If a configuration needs to be created, indicates if it should
* be created as an active or disable configuration.
* @return
* @throws IOException
*/
private Configuration findOrCreateConfig(String factoryPid,
Map<String, Configuration> fpidToConfigurationMap, String bindingType,
boolean createActiveConfig) throws IOException {
String factoryPidDisabled = factoryPid.concat(DISABLED_CONFIGURATION_SUFFIX);
String factoryPidDisabledWithBinding = factoryPidDisabled.concat(bindingType);
String factoryPidWithBinding = factoryPid.concat(bindingType);
Configuration curConfig = fpidToConfigurationMap.get(factoryPidWithBinding);
if (curConfig == null) {
curConfig = fpidToConfigurationMap.get(factoryPidDisabledWithBinding);
}
if (curConfig == null) {
String pid = factoryPidDisabled;
if (createActiveConfig) {
pid = factoryPid;
}
curConfig = configurationAdmin.createFactoryConfiguration(pid, null);
}
return curConfig;
}
/**
* Activates an existing configuration if it isn't active and has the fpid matching the fPidToActivate.
* If there is an acticve configuration that isn't the fPidToActivate it will deactivate it.
*
* @param fPidToActivate Factory PID that should be active
* @param fpidToConfigurationMap Map of existing fpid -> configuration mappings
* @throws IOException
*/
private void activateDeactivateExistingConfiguration(String fPidToActivate,
Map<String, Configuration> fpidToConfigurationMap, String bindingType)
throws IOException {
String fpid;
String fpidToActivateWithBinding = fPidToActivate.concat(bindingType);
String disabledFpidToActivateWithBinding = fPidToActivate.concat(
DISABLED_CONFIGURATION_SUFFIX)
.concat(bindingType);
Configuration configToEnable = null;
Configuration configToDisable = null;
for (Map.Entry<String, Configuration> entry : fpidToConfigurationMap.entrySet()) {
fpid = entry.getKey();
if (!fpid.contains(DISABLED_CONFIGURATION_SUFFIX) && !fpid.equals(
fpidToActivateWithBinding)) {
configToDisable = entry.getValue();
} else if (fpid.equals(disabledFpidToActivateWithBinding)) {
configToEnable = entry.getValue();
}
if (configToDisable != null && configToEnable != null) {
break;
}
}
//Order of disable/enable important. Can't have two enabled configurations with the same
//id so if there is one to disable, disable it before enabling another one.
if (configToDisable != null) {
fpidToConfigurationMap.remove(configToDisable.getFactoryPid()
.concat(getConfigStringProperty(configToDisable, BINDING_TYPE)));
Configuration config = toggleConfiguration(configToDisable);
fpidToConfigurationMap.put(config.getFactoryPid()
.concat(getConfigStringProperty(config, BINDING_TYPE)), config);
}
if (configToEnable != null) {
fpidToConfigurationMap.remove(configToEnable.getFactoryPid()
.concat(getConfigStringProperty(configToEnable, BINDING_TYPE)));
Configuration config = toggleConfiguration(configToEnable);
fpidToConfigurationMap.put(config.getFactoryPid()
.concat(getConfigStringProperty(config, BINDING_TYPE)), config);
}
}
private void deleteRegistryConfigurations(Metacard metacard)
throws IOException, InvalidSyntaxException {
String registryId = RegistryUtility.getRegistryId(metacard);
if (registryId == null) {
return;
}
Configuration[] configurations = configurationAdmin.listConfigurations(String.format(
CONFIGURATION_FILTER,
RegistryConstants.CONFIGURATION_REGISTRY_ID_PROPERTY,
registryId));
if (configurations != null && configurations.length > 0) {
String sourceName = (String) configurations[0].getProperties()
.get(ID);
configurations = configurationAdmin.listConfigurations(String.format(
CONFIGURATION_FILTER,
ID,
sourceName));
for (Configuration configuration : configurations) {
configuration.delete();
}
}
}
/**
* Toggles a configuration between enabled and disabled.
*
* @param config The configuration to enable/disable
* @return The new enabled/disabled configuration
* @throws IOException
*/
private Configuration toggleConfiguration(Configuration config) throws IOException {
String newFpid;
if (config.getFactoryPid()
.contains(DISABLED_CONFIGURATION_SUFFIX)) {
newFpid = config.getFactoryPid()
.replace(DISABLED_CONFIGURATION_SUFFIX, "");
} else {
newFpid = config.getFactoryPid()
.concat(DISABLED_CONFIGURATION_SUFFIX);
}
Dictionary<String, Object> properties = config.getProperties();
config.delete();
Configuration newConfig = configurationAdmin.createFactoryConfiguration(newFpid, null);
newConfig.update(properties);
return newConfig;
}
/**
* Returns the service binding slots as a map of string properties with the slot name as the key
*
* @param binding ServiceBindingType to generate the map from
* @return A map of service binding slots
*/
private Map<String, Object> getServiceBindingProperties(ServiceBindingType binding) {
Map<String, Object> properties = new HashMap<>();
for (SlotType1 slot : binding.getSlot()) {
List<String> slotValues = slotHelper.getStringValues(slot);
if (CollectionUtils.isEmpty(slotValues)) {
continue;
}
properties.put(slot.getName(), slotValues.size() == 1 ? slotValues.get(0) : slotValues);
}
if (binding.isSetAccessURI() && properties.get(urlBindingName) != null) {
properties.put(properties.get(urlBindingName)
.toString(), binding.getAccessURI());
}
return properties;
}
/**
* Gets all the configurations that have a matching registry id
*
* @param registryId The registry id to match
* @return A map of configurations with factory pids as keys
* @throws IOException
* @throws InvalidSyntaxException
*/
private Map<String, Configuration> getCurrentConfigurations(String registryId)
throws IOException, InvalidSyntaxException {
Map<String, Configuration> configurationMap = new HashMap<>();
Configuration[] configurations = configurationAdmin.listConfigurations(String.format(
CONFIGURATION_FILTER,
RegistryConstants.CONFIGURATION_REGISTRY_ID_PROPERTY,
registryId));
if (configurations == null) {
return configurationMap;
}
//we have found a set of source configurations with a matching registry-id
//now we need to search again with the id of one of the matching configs because
//all source configurations for an id might not all have a registry id if they
//were manually added but we want to make sure we include them here.
configurations = configurationAdmin.listConfigurations(String.format(CONFIGURATION_FILTER,
"id",
configurations[0].getProperties()
.get("id")));
for (Configuration config : configurations) {
configurationMap.put(config.getFactoryPid()
.concat(getConfigStringProperty(config, BINDING_TYPE)), config);
}
return configurationMap;
}
/**
* Gets the deconflicted configuration id. Checks for current configurations with the same ID
* and if present makes sure they belong to this registry entry. If configuration not present or
* present with the same registryId then the id passed in will be returned. If configuration is
* present and does not have the same registry id then return a new id that is a combination of
* the id and registry id which is guaranteed to be unique.
*
* @param id Initial configuration ID
* @param registryId Associated registry ID
* @return A unique valid configuration ID
* @throws IOException
* @throws InvalidSyntaxException
*/
private String getDeconflictedConfigId(String id, String registryId)
throws IOException, InvalidSyntaxException {
String configId = id;
if (StringUtils.isEmpty(configId)) {
configId = registryId;
}
Configuration[] configurations = configurationAdmin.listConfigurations(String.format(
"(id=%s)",
configId));
if (configurations == null) {
return configId;
}
String configRegistryId = null;
for (Configuration config : configurations) {
configRegistryId = (String) config.getProperties()
.get(RegistryConstants.CONFIGURATION_REGISTRY_ID_PROPERTY);
if (configRegistryId != null) {
break;
}
}
if (configRegistryId == null || !configRegistryId.equals(registryId)) {
configId = String.format("%s - %s", configId, registryId);
}
return configId;
}
private String getBindingTypeToActivate(List<ServiceBindingType> bindingTypes) {
String bindingTypeToActivate = null;
String topPriority = sourceActivationPriorityOrder.get(0);
List<String> bindingTypesNames = new ArrayList<>();
for (ServiceBindingType bindingType : bindingTypes) {
Map<String, Object> slotMap = this.getServiceBindingProperties(bindingType);
if (slotMap.get(BINDING_TYPE) == null) {
continue;
}
String factoryPidMask = slotMap.get(BINDING_TYPE)
.toString();
if (StringUtils.isNotBlank(factoryPidMask)) {
if (factoryPidMask.equals(topPriority)) {
return factoryPidMask;
}
bindingTypesNames.add(factoryPidMask);
}
}
for (String prioritySource : sourceActivationPriorityOrder.subList(1,
sourceActivationPriorityOrder.size())) {
if (bindingTypesNames.contains(prioritySource)) {
return prioritySource;
}
}
return bindingTypeToActivate;
}
private Hashtable<String, Object> getConfigurationsFromDictionary(
Dictionary<String, Object> properties) {
Hashtable<String, Object> configProperties = new Hashtable<>();
Enumeration<String> enumeration = properties.keys();
while (enumeration.hasMoreElements()) {
String key = enumeration.nextElement();
configProperties.put(key, properties.get(key));
}
return configProperties;
}
private Map<String, Object> getMetatypeDefaults(String factoryPid) {
Map<String, Object> properties = new HashMap<>();
ObjectClassDefinition bundleMetatype = getObjectClassDefinition(factoryPid);
if (bundleMetatype != null) {
for (AttributeDefinition attributeDef : bundleMetatype.getAttributeDefinitions(
ObjectClassDefinition.ALL)) {
if (attributeDef.getID() != null) {
if (attributeDef.getDefaultValue() != null) {
if (attributeDef.getCardinality() == 0) {
properties.put(attributeDef.getID(),
getAttributeValue(attributeDef.getDefaultValue()[0],
attributeDef.getType()));
} else {
properties.put(attributeDef.getID(), attributeDef.getDefaultValue());
}
} else if (attributeDef.getCardinality() != 0) {
properties.put(attributeDef.getID(), new String[0]);
}
}
}
}
return properties;
}
private String getConfigStringProperty(Configuration config, String property) {
if (config == null || config.getProperties() == null || StringUtils.isBlank(property)) {
return "";
}
String propertyValue = null;
if (config.getProperties()
.get(property) instanceof String) {
propertyValue = (String) config.getProperties()
.get(property);
}
if (propertyValue == null) {
return "";
}
return propertyValue;
}
private ObjectClassDefinition getObjectClassDefinition(String pid) {
Bundle[] bundles = this.getBundleContext()
.getBundles();
for (int i = 0; i < bundles.length; i++) {
try {
ObjectClassDefinition ocd = this.getObjectClassDefinition(bundles[i], pid);
if (ocd != null) {
return ocd;
}
} catch (IllegalArgumentException iae) {
// don't care
}
}
return null;
}
private ObjectClassDefinition getObjectClassDefinition(Bundle bundle, String pid) {
Locale locale = Locale.getDefault();
if (bundle != null) {
if (metaTypeService != null) {
MetaTypeInformation mti = metaTypeService.getMetaTypeInformation(bundle);
if (mti != null) {
try {
return mti.getObjectClassDefinition(pid, locale.toString());
} catch (IllegalArgumentException e) {
// MetaTypeProvider.getObjectClassDefinition might throw illegal
// argument exception. So we must catch it here, otherwise the
// other configurations will not be shown
// See https://issues.apache.org/jira/browse/FELIX-2390
// https://issues.apache.org/jira/browse/FELIX-3694
}
}
}
}
// fallback to nothing found
return null;
}
private Object getAttributeValue(String value, int type) {
switch (type) {
case AttributeDefinition.BOOLEAN:
return Boolean.valueOf(value);
case AttributeDefinition.BYTE:
return Byte.valueOf(value);
case AttributeDefinition.DOUBLE:
return Double.valueOf(value);
case AttributeDefinition.CHARACTER:
return value.toCharArray()[0];
case AttributeDefinition.FLOAT:
return Float.valueOf(value);
case AttributeDefinition.INTEGER:
return Integer.valueOf(value);
case AttributeDefinition.LONG:
return Long.valueOf(value);
case AttributeDefinition.SHORT:
return Short.valueOf(value);
case AttributeDefinition.PASSWORD:
case AttributeDefinition.STRING:
default:
return value;
}
}
protected BundleContext getBundleContext() {
return FrameworkUtil.getBundle(this.getClass())
.getBundleContext();
}
private void updateRegistrySourceConfigurations() {
this.updateRegistrySourceConfigurations(false);
}
private void updateRegistrySourceConfigurations(boolean deleteOldConfig) {
try {
List<Metacard> metacards = Security.getInstance()
.runAsAdminWithException(() -> federationAdminService.getRegistryMetacards());
for (Metacard metacard : metacards) {
try {
if (deleteOldConfig) {
deleteRegistryConfigurations(metacard);
}
updateRegistryConfigurations(metacard, deleteOldConfig);
} catch (InvalidSyntaxException | ParserException | IOException e) {
LOGGER.debug(
"Unable to update registry configurations. Registry source configurations won't be updated for metacard id: {}",
metacard.getId());
}
}
} catch (PrivilegedActionException e) {
LOGGER.debug(
"Error getting registry metacards. Registry source configurations won't be updated.");
}
}
public void setActivateConfigurations(boolean activateConfigurations) {
if (!(activateConfigurations == this.activateConfigurations)) {
this.activateConfigurations = activateConfigurations;
if (!activateConfigurations || preserveActiveConfigurations) {
return;
}
updateRegistrySourceConfigurations();
}
}
public void setPreserveActiveConfigurations(boolean preserveActiveConfigurations) {
if (!(preserveActiveConfigurations == this.preserveActiveConfigurations)) {
this.preserveActiveConfigurations = preserveActiveConfigurations;
if (preserveActiveConfigurations || !activateConfigurations) {
return;
}
updateRegistrySourceConfigurations();
}
}
public void setCleanUpOnDelete(boolean cleanUpOnDelete) {
this.cleanUpOnDelete = cleanUpOnDelete;
}
public synchronized void setBindingTypeFactoryPid(List<String> bindingTypeFactoryPid) {
bindingTypeToFactoryPidMap.clear();
for (String mapping : bindingTypeFactoryPid) {
String bindingType = StringUtils.substringBefore(mapping, "=");
String factoryPid = StringUtils.substringAfter(mapping, "=");
if (StringUtils.isNotBlank(bindingType) && StringUtils.isNotBlank(factoryPid)) {
bindingTypeToFactoryPidMap.put(bindingType, factoryPid);
}
}
}
public synchronized void setSourceActivationPriorityOrder(
List<String> sourceActivationPriorityOrder) {
if (!sourceActivationPriorityOrder.equals(this.sourceActivationPriorityOrder)) {
this.sourceActivationPriorityOrder.clear();
this.sourceActivationPriorityOrder.addAll(sourceActivationPriorityOrder);
if (!activateConfigurations && preserveActiveConfigurations) {
return;
}
updateRegistrySourceConfigurations();
}
}
public void setUrlBindingName(String urlBindingName) {
this.urlBindingName = urlBindingName;
}
public void setConfigurationAdmin(ConfigurationAdmin configurationAdmin) {
this.configurationAdmin = configurationAdmin;
}
public void setMetaTypeService(MetaTypeService metaTypeService) {
this.metaTypeService = metaTypeService;
}
public void setRegistryTypeHelper(RegistryPackageTypeHelper registryTypeHelper) {
this.registryTypeHelper = registryTypeHelper;
}
public void setSlotHelper(SlotTypeHelper slotHelper) {
this.slotHelper = slotHelper;
}
public void setMetacardMarshaller(MetacardMarshaller helper) {
this.metacardMarshaller = helper;
}
@Override
public void regenerateAllSources() throws FederationAdminException {
updateRegistrySourceConfigurations(true);
}
@Override
public void regenerateOneSource(String registryId) throws FederationAdminException {
try {
List<Metacard> metacards = federationAdminService.getRegistryMetacardsByRegistryIds(
Collections.singletonList(registryId));
if (metacards.size() != 1) {
throw new FederationAdminException(
"Error looking up metacard to regenerate sources. registry-id="
+ registryId);
}
deleteRegistryConfigurations(metacards.get(0));
updateRegistryConfigurations(metacards.get(0), true);
} catch (IOException | ParserException | InvalidSyntaxException e) {
throw new FederationAdminException(
"Error regenerating sources for registry entry " + registryId, e);
}
}
}