package com.mongodb.hvdf.channels;
import java.util.HashMap;
import java.util.Map;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.hvdf.api.FrameworkError;
import com.mongodb.hvdf.api.ServiceException;
import com.mongodb.hvdf.configuration.PluginConfiguration;
// Built in plugin packages
import com.mongodb.hvdf.interceptors.*;
import com.mongodb.hvdf.allocators.*;
import com.mongodb.hvdf.oid.*;
import com.mongodb.hvdf.rollup.*;
import com.mongodb.hvdf.tasks.*;
public class PluginFactory {
public static final String CONFIG_KEY = "config";
public static final String TYPE_KEY = "type";
private static HashMap<String, String> registeredPlugins =
new HashMap<String, String>();
static{
// Register the "friendly" names of built in plugins so the
// config does not need full class names like a custom plugin does
// Id Factories
registeredPlugins.put("time_only", HiDefTimeIdFactory.class.getName());
registeredPlugins.put("source_time_document", SourceTimeDocumentIdFactory.class.getName());
// Allocators
registeredPlugins.put("periodic", PeriodicAllocator.class.getName());
registeredPlugins.put("no_slicing", SingleCollectionAllocator.class.getName());
// Interceptors
registeredPlugins.put("retry", RetryInterceptor.class.getName());
registeredPlugins.put("batching", BatchingInterceptor.class.getName());
// Tasks
registeredPlugins.put("ensure_indexes", IndexingTask.class.getName());
registeredPlugins.put("limit_slices", LimitCollectionsTask.class.getName());
// Storage
registeredPlugins.put("rollup", RollupStorageInterceptor.class.getName());
registeredPlugins.put("raw", RawStorageInterceptor.class.getName());
// Rollup Operations
registeredPlugins.put("max", MaxRollup.class.getName());
registeredPlugins.put("min", MinRollup.class.getName());
registeredPlugins.put("count", CountRollup.class.getName());
registeredPlugins.put("total", TotalRollup.class.getName());
registeredPlugins.put("group_count", GroupCountRollup.class.getName());
}
public static <T> T loadPlugin(Class<T> pluginType, PluginConfiguration config) {
return loadPlugin(pluginType, config, null);
}
public static <T> T loadPlugin(Class<T> pluginType,
PluginConfiguration config, Map<String, Object> injectedConfig) {
// If the config item is not a document, return nothing
String className = config.get(TYPE_KEY, String.class);
if(registeredPlugins.containsKey(className)){
className = registeredPlugins.get(className);
}
// Get the plugin config and inject anything passed
DBObject rawPluginConf = config.get(CONFIG_KEY, DBObject.class, new BasicDBObject());
if(injectedConfig != null) rawPluginConf.putAll(injectedConfig);
// Get the plugin instance
T plugin = createPlugin(pluginType, className, rawPluginConf);
return plugin;
}
private static <T> T createPlugin(Class<T> pluginType, String className, DBObject rawConfig){
T pluginInstance = null;
try{
// Find the plugin impl class and create instance
Class<?> pluginClass = Class.forName(className);
PluginConfiguration pConfig = new PluginConfiguration(rawConfig, pluginClass);
Object instance = pluginClass.getConstructor(PluginConfiguration.class).newInstance(pConfig);
// Cast to the request plugin type
pluginInstance = pluginType.cast(instance);
} catch (NoSuchMethodException nsmex) {
throw new ServiceException(FrameworkError.FAILED_TO_LOAD_PLUGIN_CLASS).
set(TYPE_KEY, className).set("plugin_type", pluginType.getName()).
set("reason", "missing PluginConfiguration argument constructor");
} catch (ClassNotFoundException cnfex) {
throw new ServiceException(FrameworkError.FAILED_TO_LOAD_PLUGIN_CLASS).
set(TYPE_KEY, className).set("plugin_type", pluginType.getName());
} catch (ClassCastException cnfex) {
throw new ServiceException(FrameworkError.PLUGIN_INCORRECT_TYPE).
set(TYPE_KEY, className).set("plugin_type", pluginType.getName());
} catch (Exception e) {
throw ServiceException.wrap(e, FrameworkError.PLUGIN_ERROR).
set(TYPE_KEY, className).set("plugin_type", pluginType.getName());
}
return pluginInstance;
}
}