All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.frameworkset.web.socket.config.WebsocketLifecycleProcessor Maven / Gradle / Ivy

Go to download

bboss is a j2ee framework include aop/ioc,mvc,persistent,taglib,rpc,event ,bean-xml serializable and so on.http://www.bbossgroups.com

There is a newer version: 6.2.7
Show newest version
package org.frameworkset.web.socket.config;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.frameworkset.spi.ApplicationContextException;
import org.frameworkset.spi.Lifecycle;
import org.frameworkset.spi.LifecycleProcessor;
import org.frameworkset.spi.Phased;
import org.frameworkset.spi.SmartLifecycle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class WebsocketLifecycleProcessor implements LifecycleProcessor {
	private WebSocketHandlerMapping webSocketHandlerMapping;
	public WebsocketLifecycleProcessor(WebSocketHandlerMapping webSocketHandlerMapping) {
		this.webSocketHandlerMapping = webSocketHandlerMapping;
	}

	 
 
 
	 
 
	
	
	
	private final Logger logger = LoggerFactory.getLogger(getClass());

	private volatile long timeoutPerShutdownPhase = 30000;

	private volatile boolean running;

	 

	/**
	 * Specify the maximum time allotted in milliseconds for the shutdown of
	 * any phase (group of SmartLifecycle beans with the same 'phase' value).
	 * The default value is 30 seconds.
	 */
	public void setTimeoutPerShutdownPhase(long timeoutPerShutdownPhase) {
		this.timeoutPerShutdownPhase = timeoutPerShutdownPhase;
	}

	 


	// Lifecycle implementation

	/**
	 * Start all registered beans that implement Lifecycle and are
	 * not already running. Any bean that implements SmartLifecycle
	 * will be started within its 'phase', and all phases will be ordered
	 * from lowest to highest value. All beans that do not implement
	 * SmartLifecycle will be started in the default phase 0. A bean
	 * declared as a dependency of another bean will be started before
	 * the dependent bean regardless of the declared phase.
	 */
	@Override
	public void start() {
		startBeans(false);
		this.running = true;
	}

	/**
	 * Stop all registered beans that implement Lifecycle and are
	 * currently running. Any bean that implements SmartLifecycle
	 * will be stopped within its 'phase', and all phases will be ordered
	 * from highest to lowest value. All beans that do not implement
	 * SmartLifecycle will be stopped in the default phase 0. A bean
	 * declared as dependent on another bean will be stopped before
	 * the dependency bean regardless of the declared phase.
	 */
	@Override
	public void stop() {
		stopBeans();
		this.running = false;
	}

	@Override
	public void onRefresh() {
		startBeans(true);
		this.running = true;
	}

	@Override
	public void onClose() {
		stopBeans();
		this.running = false;
	}

	@Override
	public boolean isRunning() {
		return this.running;
	}


	// internal helpers

	private void startBeans(boolean autoStartupOnly) {
		Map lifecycleBeans = getLifecycleBeans();
		Map phases = new HashMap();
		for (Map.Entry entry : lifecycleBeans.entrySet()) {
			Lifecycle bean = entry.getValue();
			if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
				int phase = getPhase(bean);
				LifecycleGroup group = phases.get(phase);
				if (group == null) {
					group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
					phases.put(phase, group);
				}
				group.add(entry.getKey(), bean);
			}
		}
		if (phases.size() > 0) {
			List keys = new ArrayList(phases.keySet());
			Collections.sort(keys);
			for (Integer key : keys) {
				phases.get(key).start();
			}
		}
	}

	/**
	 * Start the specified bean as part of the given set of Lifecycle beans,
	 * making sure that any beans that it depends on are started first.
	 * @param lifecycleBeans Map with bean name as key and Lifecycle instance as value
	 * @param beanName the name of the bean to start
	 */
	private void doStart(Map lifecycleBeans, String beanName, boolean autoStartupOnly) {
		Lifecycle bean = lifecycleBeans.remove(beanName);
		if (bean != null && !this.equals(bean)) {
//			String[] dependenciesForBean = this.beanFactory.getDependenciesForBean(beanName);
//			for (String dependency : dependenciesForBean) {
//				doStart(lifecycleBeans, dependency, autoStartupOnly);
//			}
			if (!bean.isRunning() &&
					(!autoStartupOnly || !(bean instanceof SmartLifecycle) || ((SmartLifecycle) bean).isAutoStartup())) {
				if (logger.isDebugEnabled()) {
					logger.debug("Starting bean '" + beanName + "' of type [" + bean.getClass() + "]");
				}
				try {
					bean.start();
				}
				catch (Throwable ex) {
					throw new ApplicationContextException("Failed to start bean '" + beanName + "'", ex);
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Successfully started bean '" + beanName + "'");
				}
			}
		}
	}

	private void stopBeans() {
		Map lifecycleBeans = getLifecycleBeans();
		Map phases = new HashMap();
		for (Map.Entry entry : lifecycleBeans.entrySet()) {
			Lifecycle bean = entry.getValue();
			int shutdownOrder = getPhase(bean);
			LifecycleGroup group = phases.get(shutdownOrder);
			if (group == null) {
				group = new LifecycleGroup(shutdownOrder, this.timeoutPerShutdownPhase, lifecycleBeans, false);
				phases.put(shutdownOrder, group);
			}
			group.add(entry.getKey(), bean);
		}
		if (phases.size() > 0) {
			List keys = new ArrayList(phases.keySet());
			Collections.sort(keys, Collections.reverseOrder());
			for (Integer key : keys) {
				phases.get(key).stop();
			}
		}
	}

	/**
	 * Stop the specified bean as part of the given set of Lifecycle beans,
	 * making sure that any beans that depends on it are stopped first.
	 * @param lifecycleBeans Map with bean name as key and Lifecycle instance as value
	 * @param beanName the name of the bean to stop
	 */
	private void doStop(Map lifecycleBeans, final String beanName,
			final CountDownLatch latch, final Set countDownBeanNames) {

		Lifecycle bean = lifecycleBeans.remove(beanName);
		if (bean != null) {
//			String[] dependentBeans = this.beanFactory.getDependentBeans(beanName);
//			for (String dependentBean : dependentBeans) {
//				doStop(lifecycleBeans, dependentBean, latch, countDownBeanNames);
//			}
			try {
				if (bean.isRunning()) {
					if (bean instanceof SmartLifecycle) {
						if (logger.isDebugEnabled()) {
							logger.debug("Asking bean '" + beanName + "' of type [" + bean.getClass() + "] to stop");
						}
						countDownBeanNames.add(beanName);
						((SmartLifecycle) bean).stop(new Runnable() {
							@Override
							public void run() {
								latch.countDown();
								countDownBeanNames.remove(beanName);
								if (logger.isDebugEnabled()) {
									logger.debug("Bean '" + beanName + "' completed its stop procedure");
								}
							}
						});
					}
					else {
						if (logger.isDebugEnabled()) {
							logger.debug("Stopping bean '" + beanName + "' of type [" + bean.getClass() + "]");
						}
						bean.stop();
						if (logger.isDebugEnabled()) {
							logger.debug("Successfully stopped bean '" + beanName + "'");
						}
					}
				}
				else if (bean instanceof SmartLifecycle) {
					// don't wait for beans that aren't running
					latch.countDown();
				}
			}
			catch (Throwable ex) {
				{
					logger.warn("Failed to stop bean '" + beanName + "'", ex);
				}
			}
		}
	}


	// overridable hooks

	/**
	 * Retrieve all applicable Lifecycle beans: all singletons that have already been created,
	 * as well as all SmartLifecycle beans (even if they are marked as lazy-init).
	 * @return the Map of applicable beans, with bean names as keys and bean instances as values
	 */
	protected Map getLifecycleBeans() {
		Map beans = new LinkedHashMap();
//		String[] beanNames = this.beanFactory.getBeanNamesForType(Lifecycle.class, false, false);
//		for (String beanName : beanNames) {
//			String beanNameToRegister =  beanName;
//			boolean isFactoryBean = this.beanFactory.isFactoryBean(beanNameToRegister);
//			String beanNameToCheck =   beanName;
//			if ((this.beanFactory.containsSingleton(beanNameToRegister) &&
//					(!isFactoryBean || Lifecycle.class.isAssignableFrom(this.beanFactory.getType(beanNameToCheck)))) ||
//					SmartLifecycle.class.isAssignableFrom(this.beanFactory.getType(beanNameToCheck))) {
//				Lifecycle bean = this.beanFactory.getTBeanObject(beanNameToCheck, Lifecycle.class);
//				if (bean != this) {
//					beans.put(beanNameToRegister, bean);
//				}
//			}
//		}
		beans.put("WebSocketHandlerMapping", this.webSocketHandlerMapping);
		return beans;
	}

	/**
	 * Determine the lifecycle phase of the given bean.
	 * 

The default implementation checks for the {@link Phased} interface. * Can be overridden to apply other/further policies. * @param bean the bean to introspect * @return the phase an an integer value. The suggested default is 0. * @see Phased * @see SmartLifecycle */ protected int getPhase(Lifecycle bean) { return (bean instanceof Phased ? ((Phased) bean).getPhase() : 0); } /** * Helper class for maintaining a group of Lifecycle beans that should be started * and stopped together based on their 'phase' value (or the default value of 0). */ private class LifecycleGroup { private final List members = new ArrayList(); private final int phase; private final long timeout; private final Map lifecycleBeans; private final boolean autoStartupOnly; private volatile int smartMemberCount; public LifecycleGroup(int phase, long timeout, Map lifecycleBeans, boolean autoStartupOnly) { this.phase = phase; this.timeout = timeout; this.lifecycleBeans = lifecycleBeans; this.autoStartupOnly = autoStartupOnly; } public void add(String name, Lifecycle bean) { if (bean instanceof SmartLifecycle) { this.smartMemberCount++; } this.members.add(new LifecycleGroupMember(name, bean)); } public void start() { if (this.members.isEmpty()) { return; } if (logger.isInfoEnabled()) { logger.info("Starting beans in phase " + this.phase); } Collections.sort(this.members); for (LifecycleGroupMember member : this.members) { if (this.lifecycleBeans.containsKey(member.name)) { doStart(this.lifecycleBeans, member.name, this.autoStartupOnly); } } } public void stop() { if (this.members.isEmpty()) { return; } if (logger.isInfoEnabled()) { logger.info("Stopping beans in phase " + this.phase); } Collections.sort(this.members, Collections.reverseOrder()); CountDownLatch latch = new CountDownLatch(this.smartMemberCount); Set countDownBeanNames = Collections.synchronizedSet(new LinkedHashSet()); for (LifecycleGroupMember member : this.members) { if (this.lifecycleBeans.containsKey(member.name)) { doStop(this.lifecycleBeans, member.name, latch, countDownBeanNames); } else if (member.bean instanceof SmartLifecycle) { // already removed, must have been a dependent latch.countDown(); } } try { latch.await(this.timeout, TimeUnit.MILLISECONDS); if (latch.getCount() > 0 && !countDownBeanNames.isEmpty() ) { logger.warn("Failed to shut down " + countDownBeanNames.size() + " bean" + (countDownBeanNames.size() > 1 ? "s" : "") + " with phase value " + this.phase + " within timeout of " + this.timeout + ": " + countDownBeanNames); } } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } } } /** * Adapts the Comparable interface onto the lifecycle phase model. */ private class LifecycleGroupMember implements Comparable { private final String name; private final Lifecycle bean; LifecycleGroupMember(String name, Lifecycle bean) { this.name = name; this.bean = bean; } @Override public int compareTo(LifecycleGroupMember other) { int thisOrder = getPhase(this.bean); int otherOrder = getPhase(other.bean); return (thisOrder == otherOrder ? 0 : (thisOrder < otherOrder) ? -1 : 1); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy