/* * Copyright (C) 2011 Rhegium Team * * 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.rhegium.internal.lifecycle; import java.io.IOException; import java.io.InputStream; import java.util.Calendar; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.Iterator; import java.util.Properties; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.atomic.AtomicBoolean; import org.rhegium.api.AbstractService; import org.rhegium.api.lifecycle.LifecycleAware; import org.rhegium.api.lifecycle.LifecycleManager; import org.rhegium.internal.utils.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.bridge.SLF4JBridgeHandler; class DefaultLifecycleManager extends AbstractService implements LifecycleManager { private static final Logger LOG = LoggerFactory.getLogger(LifecycleManager.class); private final Set<LifecycleAware> lifecycleAwares = new CopyOnWriteArraySet<LifecycleAware>(); private final String version; private final AtomicBoolean shutdown = new AtomicBoolean(false); private Calendar calendar; DefaultLifecycleManager() throws IOException { try (final InputStream is = LifecycleManager.class.getClassLoader().getResourceAsStream("META-INF/version.properties")) { if (is != null) { final Properties properties = new Properties(); properties.load(is); version = properties.getProperty("org.rhegium.version"); } else { version = "unknown"; } } } @Override public String getUptime() { long uptime = calculateUptime() / 1000; final String seconds = String.valueOf(uptime % 60); final String minutes = String.valueOf((uptime /= 60) % 60); final String hours = String.valueOf((uptime /= 60) % 24); final String days = String.valueOf(uptime / 24); return StringUtils.join(" ", days, "days,", hours, "hours,", minutes, "minutes,", seconds, "seconds"); } @Override public Date getStartTime() { return new Date(calendar.getTime().getTime()); } @Override public String getVersion() { return version; } @Override public void registerLifecycleAware(final LifecycleAware lifecycleAware) { if (lifecycleAware == this) { return; } lifecycleAwares.add(lifecycleAware); } @Override public void removeLifecycleAware(final LifecycleAware lifecycleAware) { lifecycleAwares.remove(lifecycleAware); } @Override public Collection<LifecycleAware> getLifecycleAwares() { return Collections.unmodifiableCollection(lifecycleAwares); } @Override public void initialized() throws Exception { Runtime.getRuntime().addShutdownHook(new ShutdownHook(this)); calendar = Calendar.getInstance(); notifyOnInitialize(); } @Override public void start() throws Exception { notifyOnStartup(); LOG.info("Startup successfully completed..."); } @Override public void shutdown() throws Exception { shutdown(0); } @Override public void shutdown(final long timeout) throws Exception { if (shutdown.get()) { return; } shutdown.set(true); LOG.info("Starting shutdown..."); try { // Shutdown Plugins notifyOnShutdown(); } catch (final Exception e) { e.printStackTrace(); } } private long calculateUptime() { final Calendar now = Calendar.getInstance(); final long endL = now.getTimeInMillis() + now.getTimeZone().getOffset(now.getTimeInMillis()); final long startL = calendar.getTimeInMillis() + calendar.getTimeZone().getOffset(calendar.getTimeInMillis()); return endL - startL; } private void notifyOnInitialize() throws Exception { final Iterator<LifecycleAware> iterator = lifecycleAwares.iterator(); while (iterator.hasNext()) { iterator.next().initialized(); } } private void notifyOnStartup() throws Exception { final Iterator<LifecycleAware> iterator = lifecycleAwares.iterator(); while (iterator.hasNext()) { iterator.next().start(); } } private void notifyOnShutdown() throws Exception { final Iterator<LifecycleAware> iterator = lifecycleAwares.iterator(); while (iterator.hasNext()) { iterator.next().shutdown(); } } private class ShutdownHook extends Thread { private final LifecycleManager lifecycleManager; private ShutdownHook(final LifecycleManager lifecycleManager) { this.lifecycleManager = lifecycleManager; } @Override public void run() { try { lifecycleManager.shutdown(2000); notifyOnShutdown(); SLF4JBridgeHandler.uninstall(); } catch (final Exception e) { throw new RuntimeException("Error while shutdown", e); } } } }