/* * This file is part of l2jserver . * * l2jserver is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * l2jserver 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. * * You should have received a copy of the GNU General Public License * along with l2jserver. If not, see . */ package com.l2jserver.service; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.inject.Inject; import com.google.inject.Injector; import com.l2jserver.service.core.LoggingService; import com.l2jserver.util.ClassUtils; import com.l2jserver.util.factory.CollectionFactory; /** * The {@link ServiceManager} is responsible for starting and stopping services * * @author Rogiel */ public class ServiceManager { /** * The logger */ private final Logger logger; /** * The Guice Injector */ private final Injector injector; /** * List of all known services by this manager */ private final Set knownServices = CollectionFactory.newSet(); @Inject public ServiceManager(Injector injector) { this.injector = injector; final LoggingService service = injector .getInstance(LoggingService.class); knownServices.add(service); try { service.start(); } catch (ServiceStartException e) { throw new RuntimeException(e); } logger = LoggerFactory.getLogger(ServiceManager.class); } public T get(Class serviceClass) { return injector.getInstance(serviceClass); } public T start(Class serviceClass) throws ServiceStartException { final T service = injector.getInstance(serviceClass); if (service == null) return null; if (service.isStarted()) return service; knownServices.add(service); try { startDependencies(service.getDependencies()); logger.info("{}: Starting service...", serviceClass.getCanonicalName()); service.start(); logger.info("{}: Service started!", serviceClass.getCanonicalName()); return service; } catch (ServiceStartException e) { logger.error("{}: Error starting service: {}", serviceClass.getCanonicalName(), e); throw e; } catch (Exception e) { logger.error("{}: Error starting service: {}", serviceClass.getCanonicalName(), e); throw new ServiceStartException(e); } } private void startDependencies(Class[] dependencies) throws ServiceStartException { if (dependencies == null) return; if (dependencies.length == 0) return; for (final Class serviceClass : dependencies) { this.start(serviceClass); } } public void stop(Class serviceClass) throws ServiceStopException { final Service service = injector.getInstance(serviceClass); if (service == null) return; if (service.isStopped()) return; knownServices.add(service); try { logger.info("{0}: Stopping service...", serviceClass.getCanonicalName()); stopDependencies(service); service.stop(); logger.info("{0}: Service stopped!", serviceClass.getCanonicalName()); } catch (ServiceStopException e) { logger.error("{0}: Error stopping service: {1}", serviceClass.getCanonicalName(), e.getCause()); throw e; } } private void stopDependencies(Service service) throws ServiceStopException { final Set> dependencies = createStopDependencies( null, service); for (final Class dependency : dependencies) { this.stop(dependency); } } private Set> createStopDependencies( Set> depends, Service serviceClass) { if (depends == null) depends = CollectionFactory.newSet(); for (final Service service : knownServices) { if (service.getDependencies() == null || service.getDependencies().length == 0) continue; for (final Class dependency : service .getDependencies()) { if (!ClassUtils.isSubclass(service.getClass(), dependency)) continue; depends.add(dependency); createStopDependencies(depends, injector.getInstance(dependency)); } } return depends; } public T restart(Class serviceClass) throws ServiceException { final T service = injector.getInstance(serviceClass); if (service == null) return null; if (service.isStopped()) throw new ServiceStopException("Service is already stopped"); knownServices.add(service); try { logger.info("{0}: Restaring service...", serviceClass.getCanonicalName()); service.restart(); logger.info("{0}: Service restarted!", serviceClass.getCanonicalName()); return service; } catch (ServiceStartException e) { logger.error("{0}: Error starting service: {1}", serviceClass.getCanonicalName(), e.getCause()); throw e; } catch (ServiceStopException e) { logger.error("{0}: Error stopping service: {1}", serviceClass.getCanonicalName(), e.getCause()); throw e; } catch (ServiceException e) { logger.error("{0}: Error restarting service: {1}", serviceClass.getCanonicalName(), e.getCause()); throw e; } } }