/**
* Copyright 2014 Comcast Cable Communications Management, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.comcast.viper.flume2storm.spout;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.MapConfiguration;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import com.comcast.viper.flume2storm.F2SConfigurationException;
import com.comcast.viper.flume2storm.connection.receptor.EventReceptorFactory;
import com.comcast.viper.flume2storm.location.LocationServiceFactory;
import com.comcast.viper.flume2storm.location.ServiceProviderSerialization;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
/**
* Configuration for {@link FlumeSpout}
*/
public class FlumeSpoutConfiguration implements Supplier<Configuration>, Serializable {
private static final long serialVersionUID = -8862782920258510684L;
/**
* Configuration attribute name for
* {@link #getLocationServiceFactoryClassName()}
*/
public static final String LOCATION_SERVICE_FACTORY_CLASS = "location.service.factory";
/**
* Default value for {@value #LOCATION_SERVICE_FACTORY_CLASS}
*/
public static final String LOCATION_SERVICE_FACTORY_CLASS_DEFAULT = "com.comcast.viper.flume2storm.location.DynamicLocationServiceFactory";
/**
* Configuration attribute name for
* {@link #getServiceProviderSerializationClassName()}
*/
public static final String SERVICE_PROVIDER_SERIALIZATION_CLASS = "service.provider.serialization";
/**
* Default value for {@value #SERVICE_PROVIDER_SERIALIZATION_CLASS}
*/
public static final String SERVICE_PROVIDER_SERIALIZATION_CLASS_DEFAULT = "com.comcast.viper.flume2storm.location.KryoNetServiceProviderSerialization";
/**
* Configuration attribute name for
* {@link #getEventReceptorFactoryClassName()}
*/
public static final String EVENT_RECEPTOR_FACTORY_CLASS = "event.receptor.factory";
/**
* Default value for {@value #EVENT_RECEPTOR_FACTORY_CLASS}
*/
public static final String EVENT_RECEPTOR_FACTORY_CLASS_DEFAULT = "com.comcast.viper.flume2storm.connection.receptor.KryoNetEventReceptorFactory";
protected String locationServiceFactoryClassName;
protected String serviceProviderSerializationClassName;
protected String eventReceptorFactoryClassName;
protected Map<String, Object> configuration;
/**
* Builds a new {@link FlumeSpoutConfiguration} based on a Configuration
*
* @param config
* The configuration to use
* @return The newly created {@link F2SConfiguration}
* @throws F2SConfigurationException
* If the class is not found in the class path
*/
public static FlumeSpoutConfiguration from(Configuration config) throws F2SConfigurationException {
FlumeSpoutConfiguration result = new FlumeSpoutConfiguration();
try {
result.setLocationServiceFactoryClassName(config.getString(LOCATION_SERVICE_FACTORY_CLASS,
LOCATION_SERVICE_FACTORY_CLASS_DEFAULT));
} catch (Exception e) {
throw F2SConfigurationException.with(config, LOCATION_SERVICE_FACTORY_CLASS, e);
}
try {
result.setServiceProviderSerializationClassName(config.getString(SERVICE_PROVIDER_SERIALIZATION_CLASS,
SERVICE_PROVIDER_SERIALIZATION_CLASS_DEFAULT));
} catch (Exception e) {
throw F2SConfigurationException.with(config, SERVICE_PROVIDER_SERIALIZATION_CLASS, e);
}
try {
result.setEventReceptorFactoryClassName(config.getString(EVENT_RECEPTOR_FACTORY_CLASS,
EVENT_RECEPTOR_FACTORY_CLASS_DEFAULT));
} catch (Exception e) {
throw F2SConfigurationException.with(config, EVENT_RECEPTOR_FACTORY_CLASS, e);
}
result.configuration = getMapFromConfiguration(config);
return result;
}
/**
* @param configuration
* A configuration object
* @return A map that contains the configuration key/values (in order to
* serialize it via Kryo)
*/
protected static Map<String, Object> getMapFromConfiguration(Configuration configuration) {
Map<String, Object> result = new HashMap<String, Object>();
Iterator<?> it = configuration.getKeys();
while (it.hasNext()) {
String key = it.next().toString();
result.put(key, configuration.getProperty(key));
}
return result;
}
/**
* Empty constructor - initializes with default values when available
*/
public FlumeSpoutConfiguration() {
locationServiceFactoryClassName = LOCATION_SERVICE_FACTORY_CLASS_DEFAULT;
serviceProviderSerializationClassName = SERVICE_PROVIDER_SERIALIZATION_CLASS_DEFAULT;
eventReceptorFactoryClassName = EVENT_RECEPTOR_FACTORY_CLASS_DEFAULT;
configuration = new HashMap<String, Object>();
}
/**
* Copy constructor
*
* @param other
* the configuration to copy
*/
public FlumeSpoutConfiguration(final FlumeSpoutConfiguration other) {
locationServiceFactoryClassName = other.locationServiceFactoryClassName;
serviceProviderSerializationClassName = other.serviceProviderSerializationClassName;
eventReceptorFactoryClassName = other.eventReceptorFactoryClassName;
configuration = new HashMap<String, Object>(other.configuration);
}
/**
* @return The class name of the location service factory
*/
public String getLocationServiceFactoryClassName() {
return locationServiceFactoryClassName;
}
/**
* @param locationServiceFactoryClassName
* See {@link #getLocationServiceFactoryClassName()}
* @throws ClassNotFoundException
* If the class specified is not found in the classpath
*/
public void setLocationServiceFactoryClassName(String locationServiceFactoryClassName) throws ClassNotFoundException {
Class<?> locationServiceFactoryClass = Class.forName(locationServiceFactoryClassName);
Preconditions.checkArgument(LocationServiceFactory.class.isAssignableFrom(locationServiceFactoryClass),
"The class must implement " + LocationServiceFactory.class.getCanonicalName());
this.locationServiceFactoryClassName = locationServiceFactoryClassName;
}
/**
* @return The class name of the service provider serialization
*/
public String getServiceProviderSerializationClassName() {
return serviceProviderSerializationClassName;
}
/**
* @param serviceProviderSerializationClassName
* See {@link #getServiceProviderSerializationClassName()}
* @throws ClassNotFoundException
* If the class specified is not found in the classpath
*/
public void setServiceProviderSerializationClassName(String serviceProviderSerializationClassName)
throws ClassNotFoundException {
Class<?> serviceProviderSerializationClass = Class.forName(serviceProviderSerializationClassName);
Preconditions.checkArgument(ServiceProviderSerialization.class.isAssignableFrom(serviceProviderSerializationClass),
"The class must implement " + ServiceProviderSerialization.class.getCanonicalName());
this.serviceProviderSerializationClassName = serviceProviderSerializationClassName;
}
/**
* @return The class name of the event receptor factory
*/
public String getEventReceptorFactoryClassName() {
return eventReceptorFactoryClassName;
}
/**
* @param eventReceptorFactoryClassName
* See {@link #getEventReceptorFactoryClassName()}
* @throws ClassNotFoundException
* If the class specified is not found in the classpath
*/
public void setEventReceptorFactoryClassName(String eventReceptorFactoryClassName) throws ClassNotFoundException {
Class<?> eventReceptorFactoryClass = Class.forName(eventReceptorFactoryClassName);
Preconditions.checkArgument(EventReceptorFactory.class.isAssignableFrom(eventReceptorFactoryClass),
"The class must implement " + EventReceptorFactory.class.getCanonicalName());
this.eventReceptorFactoryClassName = eventReceptorFactoryClassName;
}
/**
* @see com.google.common.base.Supplier#get()
* @return This object as a {@link Configuration}
*/
public Configuration get() {
return new MapConfiguration(configuration);
}
/**
* @param map
* The {@link FlumeSpout} configuration as a {@link Map}
*/
public void setConfiguration(Map<String, Object> map) {
this.configuration = map;
}
/**
* @param configuration
* The {@link FlumeSpout} configuration as a
* {@link FlumeSpoutConfiguration}
*/
public void setConfiguration(Configuration configuration) {
this.configuration = getMapFromConfiguration(configuration);
}
/**
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return new HashCodeBuilder().append(locationServiceFactoryClassName).append(serviceProviderSerializationClassName)
.append(eventReceptorFactoryClassName).append(configuration).hashCode();
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
FlumeSpoutConfiguration other = (FlumeSpoutConfiguration) obj;
return new EqualsBuilder().append(this.eventReceptorFactoryClassName, other.eventReceptorFactoryClassName)
.append(this.locationServiceFactoryClassName, other.locationServiceFactoryClassName)
.append(this.serviceProviderSerializationClassName, other.serviceProviderSerializationClassName)
.append(this.configuration, other.configuration).isEquals();
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return new ToStringBuilder("FlumeSpoutConfiguration")
.append("locationServiceFactoryClass", locationServiceFactoryClassName)
.append("serviceProviderSerializationClass", serviceProviderSerializationClassName)
.append("eventReceptorFactory", eventReceptorFactoryClassName).append("configuration", configuration)
.toString();
}
}