// Path: cheddar/cheddar-messaging/src/main/java/com/clicktravel/cheddar/infrastructure/messaging/MessageListener.java
// public interface MessageListener {
// 
//     /**
//      * Starts the process of receiving messages from the queue and handling each message. This continues until this
//      * message listener is shut down.
//      */
//     void start();
// 
//     /**
//      * Gives a hint to this message listener that method {@link #shutdownListener()} will be invoked soon. This hint can
//      * be used to reduce the time taken to complete shutdown when it occurs.
//      */
//     void prepareForShutdown();
// 
//     /**
//      * Commences graceful shutdown of this message listener. No more messages will be received from the queue and
//      * handling of already received messages will be performed and run to completion. This method does not wait for the
//      * completion to occur, use method {@link #awaitShutdownComplete(long)} for that.
//      */
//     void shutdownListener();
// 
//     /**
//      * Waits until all outstanding message handling has been completed before returning, or until a timeout occurs.
//      * @param timeoutMillis Maximum time to wait for message processing to be completed
//      * @return {@code true} if message processing has completed, {@code false} if timeout occurred
//      */
//     boolean awaitShutdownComplete(long timeoutMillis);
// 
// }
// 
// Path: cheddar/cheddar-server/src/main/java/com/clicktravel/cheddar/server/rest/RestServer.java
// public class RestServer {
// 
//     private final Logger logger = LoggerFactory.getLogger(getClass());
//     private final ResourceConfig resourceConfig;
//     private HttpServer httpServer;
// 
//     public RestServer(final ResourceConfig resourceConfig) {
//         this.resourceConfig = resourceConfig;
//     }
// 
//     public void start(final int servicePort, final String bindAddress, final int workerThreads) throws IOException {
//         final URI baseUri = UriBuilder.fromUri("http://" + bindAddress).port(servicePort).build();
//         logger.info("Configuring REST server on: " + baseUri.toString());
//         httpServer = GrizzlyHttpServerFactory.createHttpServer(baseUri, resourceConfig, false);
//         enableAutoGenerationOfSwaggerSpecification();
//         configureWorkerThreadPool(httpServer.getListener("grizzly"), workerThreads);
//         logger.info("Starting REST server; servicePort:[" + servicePort + "]");
//         httpServer.start();
//     }
// 
//     private void enableAutoGenerationOfSwaggerSpecification() {
//         // The main scanner class used to scan the classes for swagger + jax-rs annoatations
//         final BeanConfig beanConfig = new BeanConfig();
//         beanConfig.setResourcePackage("com.clicktravel.services,com.clicktravel.services.*");
//         beanConfig.setSchemes(new String[] { "https" });
//         beanConfig.setBasePath("/");
//         final Info info = new Info();
//         info.setVersion("2.0.0");
//         beanConfig.setInfo(info);
//         beanConfig.setTitle("Swagger Specification");
//         beanConfig.setVersion("0.0.0");
//         beanConfig.setScan(true);
//     }
// 
//     private void configureWorkerThreadPool(final NetworkListener networkListener, final int workerThreads) {
//         final TCPNIOTransport transport = networkListener.getTransport();
// 
//         if (transport.getWorkerThreadPoolConfig() == null) {
//             transport.setWorkerThreadPoolConfig(ThreadPoolConfig.defaultConfig());
//         }
//         transport.getWorkerThreadPoolConfig().setMaxPoolSize(workerThreads).setCorePoolSize(workerThreads);
//     }
// 
//     public void shutdownAndAwait(final long timeoutMillis) {
//         try {
//             logger.info("Shutting down REST server");
//             if (httpServer != null) {
//                 final GrizzlyFuture<HttpServer> future = httpServer.shutdown(timeoutMillis, TimeUnit.MILLISECONDS);
//                 future.get();
//             }
//             logger.info("Shutdown of REST server complete");
//         } catch (final Exception e) {
//             throw new IllegalStateException(e);
//         }
//     }
// 
// }


import java.io.IOException;
import java.util.*;
import org.joda.time.DateTimeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.clicktravel.cheddar.infrastructure.messaging.MessageListener;
import com.clicktravel.cheddar.server.rest.RestServer;
/*
 * Copyright 2014 Click Travel Ltd
 *
 * 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 com.clicktravel.cheddar.server.application.lifecycle;




/**
 * Controls the start and shutdown of the {@link RestServer} and all {@link MessageListener}s.
 */
public class ApplicationLifecycleController {

    /**
     * Maximum overall time to allow for graceful shutdown of REST server and message listeners, in milliseconds. This
     * time must cover the completion of processing current REST requests. This time must also cover the maximum queue
     * poll time for message listeners and completion of processing for all messages already received.
     */
    static final long SHUTDOWN_TIMEOUT_MILLIS = 65000; // = 65s

    private final RestServer restServer;
    private final MessageListener systemEventMessageListener;
    private final Collection<MessageListener> messageListeners;
    private long shutdownDeadline;
    private boolean shutdownRequested;
    private final Logger logger = LoggerFactory.getLogger(getClass());

// Path: cheddar/cheddar-messaging/src/main/java/com/clicktravel/cheddar/infrastructure/messaging/MessageListener.java
// public interface MessageListener {
// 
//     /**
//      * Starts the process of receiving messages from the queue and handling each message. This continues until this
//      * message listener is shut down.
//      */
//     void start();
// 
//     /**
//      * Gives a hint to this message listener that method {@link #shutdownListener()} will be invoked soon. This hint can
//      * be used to reduce the time taken to complete shutdown when it occurs.
//      */
//     void prepareForShutdown();
// 
//     /**
//      * Commences graceful shutdown of this message listener. No more messages will be received from the queue and
//      * handling of already received messages will be performed and run to completion. This method does not wait for the
//      * completion to occur, use method {@link #awaitShutdownComplete(long)} for that.
//      */
//     void shutdownListener();
// 
//     /**
//      * Waits until all outstanding message handling has been completed before returning, or until a timeout occurs.
//      * @param timeoutMillis Maximum time to wait for message processing to be completed
//      * @return {@code true} if message processing has completed, {@code false} if timeout occurred
//      */
//     boolean awaitShutdownComplete(long timeoutMillis);
// 
// }
// 
// Path: cheddar/cheddar-server/src/main/java/com/clicktravel/cheddar/server/rest/RestServer.java
// public class RestServer {
// 
//     private final Logger logger = LoggerFactory.getLogger(getClass());
//     private final ResourceConfig resourceConfig;
//     private HttpServer httpServer;
// 
//     public RestServer(final ResourceConfig resourceConfig) {
//         this.resourceConfig = resourceConfig;
//     }
// 
//     public void start(final int servicePort, final String bindAddress, final int workerThreads) throws IOException {
//         final URI baseUri = UriBuilder.fromUri("http://" + bindAddress).port(servicePort).build();
//         logger.info("Configuring REST server on: " + baseUri.toString());
//         httpServer = GrizzlyHttpServerFactory.createHttpServer(baseUri, resourceConfig, false);
//         enableAutoGenerationOfSwaggerSpecification();
//         configureWorkerThreadPool(httpServer.getListener("grizzly"), workerThreads);
//         logger.info("Starting REST server; servicePort:[" + servicePort + "]");
//         httpServer.start();
//     }
// 
//     private void enableAutoGenerationOfSwaggerSpecification() {
//         // The main scanner class used to scan the classes for swagger + jax-rs annoatations
//         final BeanConfig beanConfig = new BeanConfig();
//         beanConfig.setResourcePackage("com.clicktravel.services,com.clicktravel.services.*");
//         beanConfig.setSchemes(new String[] { "https" });
//         beanConfig.setBasePath("/");
//         final Info info = new Info();
//         info.setVersion("2.0.0");
//         beanConfig.setInfo(info);
//         beanConfig.setTitle("Swagger Specification");
//         beanConfig.setVersion("0.0.0");
//         beanConfig.setScan(true);
//     }
// 
//     private void configureWorkerThreadPool(final NetworkListener networkListener, final int workerThreads) {
//         final TCPNIOTransport transport = networkListener.getTransport();
// 
//         if (transport.getWorkerThreadPoolConfig() == null) {
//             transport.setWorkerThreadPoolConfig(ThreadPoolConfig.defaultConfig());
//         }
//         transport.getWorkerThreadPoolConfig().setMaxPoolSize(workerThreads).setCorePoolSize(workerThreads);
//     }
// 
//     public void shutdownAndAwait(final long timeoutMillis) {
//         try {
//             logger.info("Shutting down REST server");
//             if (httpServer != null) {
//                 final GrizzlyFuture<HttpServer> future = httpServer.shutdown(timeoutMillis, TimeUnit.MILLISECONDS);
//                 future.get();
//             }
//             logger.info("Shutdown of REST server complete");
//         } catch (final Exception e) {
//             throw new IllegalStateException(e);
//         }
//     }
// 
// }


// Path: cheddar/cheddar-server/src/main/java/com/clicktravel/cheddar/server/application/lifecycle/ApplicationLifecycleController.java
import java.io.IOException;
import java.util.*;
import org.joda.time.DateTimeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.clicktravel.cheddar.infrastructure.messaging.MessageListener;
import com.clicktravel.cheddar.server.rest.RestServer;

/*
 * Copyright 2014 Click Travel Ltd
 *
 * 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 com.clicktravel.cheddar.server.application.lifecycle;




/**
 * Controls the start and shutdown of the {@link RestServer} and all {@link MessageListener}s.
 */
public class ApplicationLifecycleController {

    /**
     * Maximum overall time to allow for graceful shutdown of REST server and message listeners, in milliseconds. This
     * time must cover the completion of processing current REST requests. This time must also cover the maximum queue
     * poll time for message listeners and completion of processing for all messages already received.
     */
    static final long SHUTDOWN_TIMEOUT_MILLIS = 65000; // = 65s

    private final RestServer restServer;
    private final MessageListener systemEventMessageListener;
    private final Collection<MessageListener> messageListeners;
    private long shutdownDeadline;
    private boolean shutdownRequested;
    private final Logger logger = LoggerFactory.getLogger(getClass());

    public ApplicationLifecycleController(final RestServer restServer, final MessageListener systemEventMessageListener,