package com.googlecode.tawus.cometd.internal;
import java.util.ArrayList;
import java.util.List;
import org.apache.tapestry5.ioc.ObjectLocator;
import org.apache.tapestry5.ioc.services.RegistryShutdownListener;
import org.cometd.bayeux.server.BayeuxServer;
import org.cometd.bayeux.server.ServerSession;
import org.cometd.bayeux.server.ServerTransport;
import org.cometd.java.annotation.ServerAnnotationProcessor;
import org.cometd.server.BayeuxServerImpl;
import org.cometd.server.ServerSessionImpl;
import org.cometd.server.transport.HttpTransport;
import org.slf4j.Logger;
import com.googlecode.tawus.cometd.services.BayeuxServerConfigurer;
import com.googlecode.tawus.cometd.services.BayeuxServerSource;
public class BayeuxServerSourceImpl implements BayeuxServerSource,
RegistryShutdownListener {
private BayeuxServerImpl bayeux;
private List<HttpTransport> allowedTransports;
private List<Object> annotationServices;
private ServerAnnotationProcessor annotationProcessor;
private ObjectLocator locator;
private List<BayeuxServerConfigurer> configurers;
private Logger logger;
private boolean initialized;
public BayeuxServerSourceImpl(List<BayeuxServerConfigurer> configurers,
ObjectLocator locator, Logger logger) {
bayeux = newBayeuxServer();
this.locator = locator;
this.configurers = configurers;
this.logger = logger;
annotationServices = new ArrayList<Object>();
allowedTransports = new ArrayList<HttpTransport>();
initialized = false;
}
public synchronized void start(){
if(initialized){
throw new RuntimeException("The Bayeux Server is already started");
}
List<Class<?>> annotationServiceClasses = new ArrayList<Class<?>>();
logger.debug("Configuring Bayeux Server using configurers");
for(final BayeuxServerConfigurer configurer: configurers){
configurer.configure(bayeux, annotationServiceClasses);
}
try {
logger.debug("Starting server");
bayeux.start();
} catch (Exception e) {
throw new RuntimeException(e);
}
addAllowedTransports();
setupAnnotatedServices(annotationServiceClasses);
initialized = true;
}
private void addAllowedTransports() {
logger.debug("Adding allowed transports");
for (String transportName : bayeux.getAllowedTransports()) {
ServerTransport transport = bayeux.getTransport(transportName);
if (transport instanceof HttpTransport) {
logger.debug("Adding transport " + transportName);
allowedTransports.add((HttpTransport) transport);
}
}
}
private void setupAnnotatedServices(List<Class<?>> annotationServiceClasses) {
logger.debug("Setting annotation services processor");
annotationProcessor = new ServerAnnotationProcessor(getBayeux());
for (Class<?> service : annotationServiceClasses) {
Object object = locator.autobuild(service);
logger.info("Building service for interface " + service);
annotationProcessor.process(object);
annotationServices.add(object);
}
}
protected BayeuxServerImpl newBayeuxServer() {
return new BayeuxServerImpl();
}
public BayeuxServer getBayeux() {
return bayeux;
}
public BayeuxServerImpl getBayeuxImpl() {
return bayeux;
}
public List<HttpTransport> getAllowedTransports() {
return allowedTransports;
}
public void registryDidShutdown() {
if (!initialized) {
return;
}
cleanupAnnotatedServices();
cleanupSessions();
try {
bayeux.stop();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
bayeux = null;
}
allowedTransports.clear();
}
private void cleanupAnnotatedServices() {
if (annotationProcessor != null) {
for (Object service : annotationServices) {
logger.debug("Deprocessing " + service);
annotationProcessor.deprocess(service);
}
}
}
private void cleanupSessions() {
for (ServerSession session : bayeux.getSessions()) {
logger.debug("Cleaning up session : " + session);
((ServerSessionImpl) session).cancelSchedule();
}
}
}