346 lines
12 KiB
Java
346 lines
12 KiB
Java
/**
|
||
* Copyright (C) 2007 - 2016 52°North Initiative for Geospatial Open Source
|
||
* Software GmbH
|
||
*
|
||
* This program is free software; you can redistribute it and/or modify it
|
||
* under the terms of the GNU General Public License version 2 as published
|
||
* by the Free Software Foundation.
|
||
*
|
||
* If the program is linked with libraries which are licensed under one of
|
||
* the following licenses, the combination of the program with the linked
|
||
* library is not considered a "derivative work" of the program:
|
||
*
|
||
* • Apache License, version 2.0
|
||
* • Apache Software License, version 1.0
|
||
* • GNU Lesser General Public License, version 3
|
||
* • Mozilla Public License, versions 1.0, 1.1 and 2.0
|
||
* • Common Development and Distribution License (CDDL), version 1.0
|
||
*
|
||
* Therefore the distribution of the program linked with libraries licensed
|
||
* under the aforementioned licenses, is permitted by the copyright holders
|
||
* if the distribution is compliant with both the GNU General Public
|
||
* License version 2 and the aforementioned licenses.
|
||
*
|
||
* This program is distributed in the hope that it will be useful, but
|
||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||
* Public License for more details.
|
||
*/
|
||
package org.n52.wps.server;
|
||
|
||
import java.beans.PropertyChangeEvent;
|
||
import java.beans.PropertyChangeListener;
|
||
import java.lang.reflect.Constructor;
|
||
import java.lang.reflect.InvocationTargetException;
|
||
import java.util.ArrayList;
|
||
import java.util.List;
|
||
|
||
import net.opengis.wps.x100.ProcessDescriptionType;
|
||
|
||
import org.n52.wps.PropertyDocument.Property;
|
||
import org.n52.wps.RepositoryDocument.Repository;
|
||
import org.n52.wps.commons.WPSConfig;
|
||
import org.slf4j.Logger;
|
||
import org.slf4j.LoggerFactory;
|
||
|
||
/**
|
||
* @author Bastian Schaeffer, University of Muenster
|
||
*
|
||
*/
|
||
public class RepositoryManager {
|
||
|
||
private static RepositoryManager instance;
|
||
private static Logger LOGGER = LoggerFactory.getLogger(RepositoryManager.class);
|
||
private List<IAlgorithmRepository> repositories;
|
||
private ProcessIDRegistry globalProcessIDs = ProcessIDRegistry.getInstance();
|
||
private UpdateThread updateThread;
|
||
|
||
private RepositoryManager(){
|
||
|
||
// clear registry
|
||
globalProcessIDs.clearRegistry();
|
||
|
||
// initialize all Repositories
|
||
loadAllRepositories();
|
||
|
||
// FvK: added Property Change Listener support
|
||
// creates listener and register it to the wpsConfig instance.
|
||
WPSConfig.getInstance().addPropertyChangeListener(WPSConfig.WPSCONFIG_PROPERTY_EVENT_NAME, new PropertyChangeListener() {
|
||
public void propertyChange(
|
||
final PropertyChangeEvent propertyChangeEvent) {
|
||
LOGGER.info("Received Property Change Event: {}",
|
||
propertyChangeEvent.getPropertyName());
|
||
loadAllRepositories();
|
||
}
|
||
});
|
||
|
||
Double updateHours = WPSConfig.getInstance().getWPSConfig().getServer().getRepoReloadInterval();
|
||
|
||
if (updateHours != 0){
|
||
LOGGER.info("Setting repository update period to {} hours.", updateHours);
|
||
updateHours = updateHours * 3600 * 1000; // make milliseconds
|
||
long updateInterval = updateHours.longValue();
|
||
this.updateThread = new UpdateThread(updateInterval);
|
||
updateThread.start();
|
||
}
|
||
|
||
|
||
}
|
||
|
||
private void loadAllRepositories(){
|
||
repositories = new ArrayList<IAlgorithmRepository>();
|
||
LOGGER.debug("Loading all repositories: {} (doing a gc beforehand...)", repositories);
|
||
|
||
System.gc();
|
||
|
||
Repository[] repositoryList = WPSConfig.getInstance().getRegisterdAlgorithmRepositories();
|
||
|
||
for(Repository repository : repositoryList){
|
||
if(repository.getActive()==false){
|
||
continue;
|
||
}
|
||
String repositoryClassName = repository.getClassName();
|
||
try {
|
||
IAlgorithmRepository algorithmRepository = null;
|
||
Class repositoryClass = RepositoryManager.class.getClassLoader().loadClass(repositoryClassName);
|
||
Constructor[] constructors = repositoryClass.getConstructors();
|
||
for(Constructor constructor : constructors){
|
||
|
||
if(constructor.getParameterTypes().length==1 && constructor.getParameterTypes()[0].equals(String.class)){
|
||
Property[] properties = repository.getPropertyArray();
|
||
Property formatProperty = WPSConfig.getInstance().getPropertyForKey(properties, "supportedFormat");
|
||
String format = formatProperty.getStringValue();
|
||
algorithmRepository = (IAlgorithmRepository) repositoryClass.getConstructor(String.class).newInstance(format);
|
||
}else{
|
||
algorithmRepository = (IAlgorithmRepository) repositoryClass.newInstance();
|
||
}
|
||
}
|
||
|
||
repositories.add(algorithmRepository);
|
||
LOGGER.info("Algorithm Repository {} initialized", repositoryClassName);
|
||
} catch (InstantiationException e) {
|
||
LOGGER.warn("An error occured while registering AlgorithmRepository: {}", repositoryClassName);
|
||
} catch (IllegalAccessException e) {
|
||
//in case of an singleton
|
||
// try {
|
||
//
|
||
// IAlgorithmRepository algorithmRepository = (IAlgorithmRepository)RepositoryManager.class.getClassLoader().loadClass(repositoryClassName).getMethod("getInstance", new Class[0]).invoke(null, new Object[0]);
|
||
// repositories.add(algorithmRepository);
|
||
// } catch (IllegalArgumentException e1) {
|
||
// LOGGER.warn("An error occured while registering AlgorithmRepository: " + repositoryClassName);
|
||
// } catch (SecurityException e1) {
|
||
// LOGGER.warn("An error occured while registering AlgorithmRepository: " + repositoryClassName);
|
||
// } catch (IllegalAccessException e1) {
|
||
// LOGGER.warn("An error occured while registering AlgorithmRepository: " + repositoryClassName);
|
||
// } catch (InvocationTargetException e1) {
|
||
// LOGGER.warn("An error occured while registering AlgorithmRepository: " + repositoryClassName);
|
||
// } catch (NoSuchMethodException e1) {
|
||
// LOGGER.warn("An error occured while registering AlgorithmRepository: " + repositoryClassName);
|
||
// } catch (ClassNotFoundException e1) {
|
||
// LOGGER.warn("An error occured while registering AlgorithmRepository: " + repositoryClassName);
|
||
// }
|
||
LOGGER.warn("An error occured while registering AlgorithmRepository: {}", repositoryClassName);
|
||
|
||
} catch (ClassNotFoundException e) {
|
||
LOGGER.warn("An error occured while registering AlgorithmRepository: {}",
|
||
repositoryClassName,
|
||
e.getMessage());
|
||
} catch (IllegalArgumentException e) {
|
||
LOGGER.warn("An error occured while registering AlgorithmRepository: {}",
|
||
repositoryClassName,
|
||
e.getMessage());
|
||
} catch (SecurityException e) {
|
||
LOGGER.warn("An error occured while registering AlgorithmRepository: {}",
|
||
repositoryClassName,
|
||
e.getMessage());
|
||
} catch (InvocationTargetException e) {
|
||
LOGGER.warn("An error occured while registering AlgorithmRepository: {}",
|
||
repositoryClassName,
|
||
e.getMessage());
|
||
} catch (NoSuchMethodException e) {
|
||
LOGGER.warn("An error occured while registering AlgorithmRepository: {}",
|
||
repositoryClassName,
|
||
e.getMessage());
|
||
}
|
||
}
|
||
}
|
||
|
||
public static RepositoryManager getInstance(){
|
||
if(instance==null){
|
||
instance = new RepositoryManager();
|
||
}
|
||
return instance;
|
||
}
|
||
|
||
/**
|
||
* Allows to reInitialize the RepositoryManager... This should not be called to often.
|
||
*
|
||
*/
|
||
public static void reInitialize() {
|
||
instance = new RepositoryManager();
|
||
}
|
||
|
||
/**
|
||
* Allows to reInitialize the Repositories
|
||
*
|
||
*/
|
||
protected void reloadRepositories() {
|
||
loadAllRepositories();
|
||
}
|
||
|
||
/**
|
||
* Methods looks for Algorithm in all Repositories.
|
||
* The first match is returned.
|
||
* If no match could be found, null is returned
|
||
*
|
||
* @param className
|
||
* @return IAlgorithm or null
|
||
* @throws Exception
|
||
*/
|
||
public IAlgorithm getAlgorithm(String className){
|
||
for(IAlgorithmRepository repository : repositories){
|
||
if(repository.containsAlgorithm(className)){
|
||
return repository.getAlgorithm(className);
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
*
|
||
* @return allAlgorithms
|
||
*/
|
||
public List<String> getAlgorithms(){
|
||
List<String> allAlgorithmNamesCollection = new ArrayList<String>();
|
||
for(IAlgorithmRepository repository : repositories){
|
||
allAlgorithmNamesCollection.addAll(repository.getAlgorithmNames());
|
||
}
|
||
return allAlgorithmNamesCollection;
|
||
|
||
}
|
||
|
||
public boolean containsAlgorithm(String algorithmName) {
|
||
for(IAlgorithmRepository repository : repositories){
|
||
if(repository.containsAlgorithm(algorithmName)){
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
public IAlgorithmRepository getRepositoryForAlgorithm(String algorithmName){
|
||
for(IAlgorithmRepository repository : repositories){
|
||
if(repository.containsAlgorithm(algorithmName)){
|
||
return repository;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
public Class getInputDataTypeForAlgorithm(String algorithmIdentifier, String inputIdentifier){
|
||
IAlgorithm algorithm = getAlgorithm(algorithmIdentifier);
|
||
return algorithm.getInputDataType(inputIdentifier);
|
||
|
||
}
|
||
|
||
public Class getOutputDataTypeForAlgorithm(String algorithmIdentifier, String inputIdentifier){
|
||
IAlgorithm algorithm = getAlgorithm(algorithmIdentifier);
|
||
return algorithm.getOutputDataType(inputIdentifier);
|
||
|
||
}
|
||
|
||
public boolean registerAlgorithm(String id, IAlgorithmRepository repository){
|
||
if (globalProcessIDs.addID(id)){
|
||
return true;
|
||
}
|
||
else return false;
|
||
}
|
||
|
||
public boolean unregisterAlgorithm(String id){
|
||
if (globalProcessIDs.removeID(id)){
|
||
return true;
|
||
}
|
||
else return false;
|
||
}
|
||
|
||
public IAlgorithmRepository getAlgorithmRepository(String name){
|
||
for (IAlgorithmRepository repo : repositories ){
|
||
if(repo.getClass().getName().equals(name)){
|
||
return repo;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
public IAlgorithmRepository getRepositoryForClassName(
|
||
String className) {
|
||
for(IAlgorithmRepository repository : repositories){
|
||
if(repository.getClass().getName().equals(className)){
|
||
return repository;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
public ProcessDescriptionType getProcessDescription(String processClassName){
|
||
for(IAlgorithmRepository repository : repositories){
|
||
if(repository.containsAlgorithm(processClassName)){
|
||
return repository.getProcessDescription(processClassName);
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
static class UpdateThread extends Thread {
|
||
|
||
private final long interval;
|
||
private boolean firstrun = true;
|
||
|
||
public UpdateThread (long interval){
|
||
this.interval = interval;
|
||
}
|
||
|
||
@Override
|
||
public void run() {
|
||
LOGGER.debug("UpdateThread started");
|
||
|
||
try {
|
||
// never terminate the run method
|
||
while (true){
|
||
// do not update on first run!
|
||
if (!firstrun){
|
||
LOGGER.info("Reloading repositories - this might take a while ...");
|
||
long timestamp = System.currentTimeMillis();
|
||
RepositoryManager.getInstance().reloadRepositories();
|
||
LOGGER.info("Repositories reloaded - going to sleep. Took {} seconds.",
|
||
(System.currentTimeMillis() - timestamp) / 1000);
|
||
} else {
|
||
firstrun = false;
|
||
}
|
||
|
||
// sleep for a given INTERVAL
|
||
sleep(interval);
|
||
}
|
||
} catch (InterruptedException e) {
|
||
LOGGER.debug("Interrupt received - Terminating the UpdateThread.");
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
// shut down the update thread
|
||
public void finalize(){
|
||
if (updateThread != null){
|
||
updateThread.interrupt();
|
||
}
|
||
}
|
||
|
||
public void shutdown() {
|
||
LOGGER.debug("Shutting down all repositories..");
|
||
for (IAlgorithmRepository repo : repositories) {
|
||
repo.shutdown();
|
||
}
|
||
}
|
||
|
||
}
|