private Set<String> validateSinks(Set<String> channelSet) {
// Preconditions.checkArgument(channelSet != null && channelSet.size() >
// 0);
Map<String, Context> newContextMap = new HashMap<String, Context>();
Set<String> sinkSet;
SinkConfiguration sinkConf = null;
if (sinks == null || sinks.isEmpty()) {
logger.warn("Agent configuration for '" + agentName
+ "' has no sinks.");
errorList.add(new FlumeConfigurationError(agentName,
BasicConfigurationConstants.CONFIG_SINKS,
FlumeConfigurationErrorType.PROPERTY_VALUE_NULL,
ErrorOrWarning.WARNING));
return new HashSet<String>();
} else {
sinkSet =
new HashSet<String>(Arrays.asList(sinks.split("\\s+")));
}
Iterator<String> iter = sinkSet.iterator();
/*
* The logic for the following code:
*
* Is it a known component?
* -Yes: Get the SinkType and set the string name of that to
* config and set configSpecified to true.
* -No.Look for config type for the given component:
* -Config Found:
* Set config to the type mentioned, set configSpecified to true
* -No Config found:
* Set config to OTHER, configSpecified to false,
* do basic validation. Leave the context in the
* contextMap to process later. Setting it to other returns
* a vanilla configuration(Source/Sink/Channel Configuration),
* which does basic syntactic validation. This object is not
* put into the map, so the context is retained which can be
* picked up - this is meant for older classes which don't
* implement ConfigurableComponent.
*/
while (iter.hasNext()) {
String sinkName = iter.next();
Context sinkContext = sinkContextMap.get(sinkName.trim());
if (sinkContext == null) {
iter.remove();
logger.warn("no context for sink" + sinkName);
errorList.add(new FlumeConfigurationError(agentName, sinkName,
FlumeConfigurationErrorType.CONFIG_ERROR, ErrorOrWarning.ERROR));
} else {
String config = null;
boolean configSpecified = false;
SinkType sinkType = getKnownSink(sinkContext.getString(
BasicConfigurationConstants.CONFIG_TYPE));
if (sinkType == null) {
config = sinkContext.getString(
BasicConfigurationConstants.CONFIG_CONFIG);
if (config == null || config.isEmpty()) {
config = "OTHER";
} else{
configSpecified = true;
}
} else {
config = sinkType.toString().toUpperCase();
configSpecified = true;
}
try {
logger.debug("Creating sink: " + sinkName + " using " + config);
sinkConf =
(SinkConfiguration) ComponentConfigurationFactory.create(
sinkName, config, ComponentType.SINK);
if (sinkConf != null) {
sinkConf.configure(sinkContext);
}
if(!channelSet.contains(sinkConf.getChannel())){
throw new ConfigurationException("Channel " +
sinkConf.getChannel() + " not in active set.");
}
if ((configSpecified && sinkConf.isNotFoundConfigClass()) ||
!configSpecified) {
newContextMap.put(sinkName, sinkContext);
} else if (configSpecified) {
sinkConfigMap.put(sinkName, sinkConf);
}
if (sinkConf != null) errorList.addAll(sinkConf.getErrors());
} catch (ConfigurationException e) {
iter.remove();
if (sinkConf != null) errorList.addAll(sinkConf.getErrors());
logger.warn("Configuration for : " + sinkName
+ " has errors, and will be removed: ", e);
}
}
// Filter out any sinks that have invalid channel