/* * Constellation - An open source and standard compliant SDI * http://www.constellation-sdi.org * * Copyright 2014 Geomatys. * * 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.constellation.ws; import org.apache.sis.util.logging.Logging; import org.constellation.util.ReflectionUtilities; import java.util.AbstractMap; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; /** * * @author Guilhem Legal (Geomatys) */ public final class WSEngine { private static final Logger LOGGER = Logging.getLogger("org.constellation.ws"); /** * Default value, changes nothing, just using reflection to instantiate the worker. */ private static WorkerFactory workerFactory = new WorkerFactory() { @Override public Worker build(Class<? extends Worker> workerClass, String identifier) { return (Worker) ReflectionUtilities.newInstance(workerClass, identifier); } }; private WSEngine() {} /** * A map of service worker. */ private static final Map<String, Map<String, Worker>> WORKERS_MAP = new HashMap<>(); /** * A map of the registred OGC services and their endpoint protocols (SOAP, REST). */ private static final Map<String, List<String>> REGISTERED_SERVICE = new HashMap<>(); /** * A map of {@link Worker} class for each OGC registred service. */ private static final Map<String, Class<? extends Worker>> SERVICE_WORKER_CLASS = new HashMap<>(); /** * A map of {@link ServiceConfigurer} class for eache OGC resgitred service. */ private static final Map<String, Class<? extends ServiceConfigurer>> SERVICE_CONFIGURER_CLASS = new HashMap<>(); @Deprecated private static final List<String> TO_RESTART = new ArrayList<>(); public static void setWorkerFactory(WorkerFactory workerFactory) { WSEngine.workerFactory = workerFactory; } public static Map<String, Worker> getWorkersMap(final String specification) { final Map<String, Worker> result = WORKERS_MAP.get(specification.toLowerCase()); if (result == null) { return new HashMap<>(); } return result; } @Deprecated public static void prepareRestart() { TO_RESTART.addAll(WORKERS_MAP.keySet()); } /** * Return the number of instances for the specified OGC service. * * @param specification the OGC service type (WMS, CSW, WFS, ...) * @return */ public static int getInstanceSize(final String specification) { final Map<String, Worker> workersMap = WORKERS_MAP.get(specification.toLowerCase()); if (workersMap != null) { return workersMap.size(); } return 0; } public static boolean serviceInstanceExist(final String specification, final String serviceID) { final Map<String, Worker> workersMap = WORKERS_MAP.get(specification.toLowerCase()); if (workersMap != null) { return workersMap.containsKey(serviceID); } return false; } public static Set<String> getInstanceNames(final String specification) { final Map<String, Worker> workersMap = WORKERS_MAP.get(specification.toLowerCase()); if (workersMap != null) { return workersMap.keySet(); } return new HashSet<>(); } public static Worker getInstance(final String specification, final String serviceID) { final Map<String, Worker> workersMap = WORKERS_MAP.get(specification.toLowerCase()); if (workersMap != null) { return workersMap.get(serviceID); } return null; } public static void destroyInstances(final String specification) { if (TO_RESTART.contains(specification.toLowerCase())) { TO_RESTART.remove(specification.toLowerCase()); return; } final Map<String, Worker> workersMap = WORKERS_MAP.get(specification.toLowerCase()); if (workersMap != null) { for (final Worker worker : workersMap.values()) { worker.destroy(); } workersMap.clear(); WORKERS_MAP.put(specification.toLowerCase(), null); } } public static boolean isSetService(final String specification) { if (TO_RESTART.contains(specification)) { return false; } final Map<String, Worker> workersMap = WORKERS_MAP.get(specification.toLowerCase()); return workersMap != null; } public static void setServiceInstances(final String specification, final Map<String, Worker> instances) { final Map<String, Worker> oldWorkersMap = WORKERS_MAP.put(specification.toLowerCase(), instances); if (oldWorkersMap != null && !oldWorkersMap.isEmpty()) { LOGGER.info("Destroying old workers"); for (Worker oldWorker : oldWorkersMap.values()) { oldWorker.destroy(); } } } public static void addServiceInstance(final String specification, final String serviceID, final Worker instance) { Map<String, Worker> workersMap = WORKERS_MAP.get(specification.toLowerCase()); if (workersMap == null) { workersMap = new HashMap<>(); WORKERS_MAP.put(specification.toLowerCase(), workersMap); } final Worker oldWorker = workersMap.put(serviceID, instance); if (oldWorker != null) { LOGGER.log(Level.INFO, "Destroying old worker: {0}({1})", new Object[]{specification.toLowerCase(), serviceID}); oldWorker.destroy(); } } public static Set<Entry<String, Boolean>> getEntriesStatus(final String specification) { final Set<Map.Entry<String, Boolean>> response = new HashSet<>(); final Map<String, Worker> workersMap = WORKERS_MAP.get(specification.toLowerCase()); if (workersMap != null) { for (Entry<String, Worker> entry : workersMap.entrySet()) { response.add(new AbstractMap.SimpleEntry<>(entry.getKey(), entry.getValue().isStarted())); } } return response; } public static void shutdownInstance(final String specification, final String serviceID) { final Map<String, Worker> workersMap = WORKERS_MAP.get(specification.toLowerCase()); if (workersMap != null) { final Worker worker = workersMap.get(serviceID); if (worker != null) { worker.destroy(); workersMap.remove(serviceID); } } } /** * Add a service type to the list of registered service if it is not already registered. * * @param specification A service type (CSW, SOS, WMS, ...). * @param protocol * @param workerClass the class binding of the service worker. * @param configurerClass the class binding of the service configurer */ public static void registerService(final String specification, final String protocol, final Class <? extends Worker> workerClass, final Class<? extends ServiceConfigurer> configurerClass) { if (REGISTERED_SERVICE.containsKey(specification.toLowerCase())) { final List<String> protocols = REGISTERED_SERVICE.get(specification.toLowerCase()); if (!protocols.contains(protocol)) { protocols.add(protocol); } REGISTERED_SERVICE.put(specification.toLowerCase(), protocols); } else { final List<String> protocols = new ArrayList<>(); protocols.add(protocol); REGISTERED_SERVICE.put(specification.toLowerCase(), protocols); } SERVICE_WORKER_CLASS.put(specification.toLowerCase(), workerClass); SERVICE_CONFIGURER_CLASS.put(specification.toLowerCase(), configurerClass); } public static Map<String, List<String>> getRegisteredServices() { return REGISTERED_SERVICE; } /** * Return the {@link Worker} implementation {@link Class} of a registered OGC service. * * @param specification The OGC service type (WMS, CSW, WFS, ...). * @return the worker class of a registered service or null if service not registered. */ private static Class<? extends Worker> getServiceWorkerClass(final String specification) { if (SERVICE_WORKER_CLASS.containsKey(specification.toLowerCase())) { return SERVICE_WORKER_CLASS.get(specification.toLowerCase()); } return null; } /** * Instanciate a new {@link Worker} for the specified OGC service. * * @param specification The OGC service type (WMS, CSW, WFS, ...). * @param identifier The identifier of the new {@link Worker}. * * @return The new instancied {@link Worker}. */ public static Worker buildWorker(final String specification, final String identifier) { final Class<? extends Worker> workerClass = getServiceWorkerClass(specification.toLowerCase()); return workerFactory.build(workerClass, identifier); } /** * Returns the {@link ServiceConfigurer} implementation {@link Class} for the * specified service specification. * * @param specification the service specification * @return the {@link ServiceConfigurer} implementation {@link Class} or null if service not registered */ public static Class<? extends ServiceConfigurer> getServiceConfigurerClass(final String specification) { if (SERVICE_CONFIGURER_CLASS.containsKey(specification.toLowerCase())) { return SERVICE_CONFIGURER_CLASS.get(specification.toLowerCase()); } return null; } }