/** * 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 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(); 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 getAlgorithms(){ List allAlgorithmNamesCollection = new ArrayList(); 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(); } } }