/*
* Copyright 2013 NGDATA nv
* Copyright 2008 Outerthought bvba and Schaubroeck nv
*
* 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 org.lilyproject.runtime.source;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.jci.monitor.FilesystemAlterationMonitor;
import org.lilyproject.runtime.LilyRTException;
import org.lilyproject.runtime.model.ModuleSourceType;
import org.lilyproject.runtime.rapi.ModuleSource;
/**
* Manages ModuleSources. One of the main purposes is so that when multiple module instances
* are created from the same module, only one module source is created for them.
*/
public class ModuleSourceManager {
private Map<String, SharedModuleSource> moduleSources = new HashMap<String, SharedModuleSource>();
private FilesystemAlterationMonitor fam;
public ModuleSourceManager(FilesystemAlterationMonitor fam) {
this.fam = fam;
}
public synchronized ModuleSource getModuleSource(File location, ModuleSourceType moduleSourceType)
throws ModuleSourceCreationException {
String key = getKey(location);
SharedModuleSource moduleSource = moduleSources.get(key);
if (moduleSource == null) {
ModuleSource newModuleSource = createModuleSource(location, moduleSourceType);
moduleSource = new SharedModuleSource(newModuleSource, this, key);
moduleSources.put(key, moduleSource);
} else {
if (getType(moduleSource.getDelegate()) != moduleSourceType) {
throw new LilyRTException("The same module location was requested earlier but with a different type. Type 1: " + getType(moduleSource) + ", type 2: " + moduleSourceType);
}
}
moduleSource.increaseRefCount();
return moduleSource;
}
private String getKey(File location) {
try {
return location.getCanonicalFile().getAbsolutePath();
} catch (IOException e) {
throw new LilyRTException("Error making key for module source location " + location, e);
}
}
private ModuleSource createModuleSource(File location, ModuleSourceType moduleSourceType)
throws ModuleSourceCreationException {
try {
ModuleSource moduleSource;
switch (moduleSourceType) {
case JAR:
moduleSource = new JarModuleSource(location);
break;
case EXPANDED_JAR:
moduleSource = new ExpandedJarModuleSource(location, fam);
break;
case SOURCE_DIRECTORY:
moduleSource = new MavenSourceDirectoryModuleSource(location, fam);
break;
default:
throw new LilyRTException("Unexpected module definition type: " + location);
}
return moduleSource;
} catch (Throwable t) {
throw new ModuleSourceCreationException("Creating a module source from " + location + " of type " + moduleSourceType + " failed.", t);
}
}
private ModuleSourceType getType(ModuleSource moduleSource) {
if (moduleSource instanceof JarModuleSource) {
return ModuleSourceType.JAR;
} else if (moduleSource instanceof ExpandedJarModuleSource) {
return ModuleSourceType.EXPANDED_JAR;
} else if (moduleSource instanceof MavenSourceDirectoryModuleSource) {
return ModuleSourceType.SOURCE_DIRECTORY;
} else {
throw new LilyRTException("Unrecognized module source implementation: " + moduleSource.getClass().getName());
}
}
protected synchronized void dispose(SharedModuleSource moduleSource) throws Exception {
// Remove from list of managed module sources
if (moduleSources.remove(moduleSource.getKey()) == null) {
throw new LilyRTException("Unexpected situation: disposed module source not found.");
}
// perform disposal of actual module source
moduleSource.getDelegate().dispose();
}
}