try {
mdsDatasets.execute(new TxCallable<MDSDatasets, Void>() {
@Override
public Void call(MDSDatasets datasets) throws DatasetModuleConflictException {
DatasetModuleMeta existing = datasets.getTypeMDS().getModule(name);
if (existing != null) {
String msg = String.format("cannot add module %s, module with the same name already exists: %s",
name, existing);
LOG.warn(msg);
throw new DatasetModuleConflictException(msg);
}
ClassLoader cl;
DatasetModule module;
File unpackedLocation = Files.createTempDir();
DependencyTrackingRegistry reg;
try {
// NOTE: if jarLocation is null, we assume that this is a system module, ie. always present in classpath
if (jarLocation != null) {
BundleJarUtil.unpackProgramJar(jarLocation, unpackedLocation);
}
cl = jarLocation == null ? this.getClass().getClassLoader() :
ClassLoaders.newProgramClassLoader(unpackedLocation, ApiResourceListHolder.getResourceList(),
this.getClass().getClassLoader());
@SuppressWarnings("unchecked")
Class clazz = ClassLoaders.loadClass(className, cl, this);
module = DatasetModules.getDatasetModule(clazz);
reg = new DependencyTrackingRegistry(datasets);
module.register(reg);
} catch (Exception e) {
LOG.error("Could not instantiate instance of dataset module class {} for module {} using jarLocation {}",
className, name, jarLocation);
throw Throwables.propagate(e);
} finally {
try {
DirUtils.deleteDirectoryContents(unpackedLocation);
} catch (IOException e) {
LOG.warn("Failed to delete directory {}", unpackedLocation, e);
}
}
// NOTE: we use set to avoid duplicated dependencies
// NOTE: we use LinkedHashSet to preserve order in which dependencies must be loaded
Set<String> moduleDependencies = Sets.newLinkedHashSet();
for (String usedType : reg.getUsedTypes()) {
DatasetModuleMeta usedModule = datasets.getTypeMDS().getModuleByType(usedType);
// adding all used types and the module itself, in this very order to keep the order of loading modules
// for instantiating a type
moduleDependencies.addAll(usedModule.getUsesModules());
boolean added = moduleDependencies.add(usedModule.getName());
if (added) {
// also adding this module as a dependent for all modules it uses
usedModule.addUsedByModule(name);
datasets.getTypeMDS().write(usedModule);
}
}
DatasetModuleMeta moduleMeta = new DatasetModuleMeta(name, className,
jarLocation == null ? null : jarLocation.toURI(),
reg.getTypes(), Lists.newArrayList(moduleDependencies));
datasets.getTypeMDS().write(moduleMeta);
return null;