package com.fredhopper.server; import java.util.Collection; import java.util.List; import java.util.function.Function; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.server.handler.RequestLogHandler; import org.eclipse.jetty.server.handler.ShutdownHandler; import org.eclipse.jetty.servlet.ServletContextHandler; import com.fredhopper.environment.Environment; import com.fredhopper.server.spi.ApplicationFactory; import com.fredhopper.server.spi.ContextHandlerFactory; import com.fredhopper.server.spi.RequestLogHandlerFactory; /** * Collects all implementations of {@link ApplicationFactory}, * {@link ContextHandlerFactory}, and * {@link RequestLogHandlerFactory}. */ class HandlerCollectionLoader implements Function<Environment, HandlerCollection> { @Override public HandlerCollection apply(Environment environment) { HandlerCollection handlers = new HandlerCollection(); List<RequestLogHandler> requestLogHandlers = createRequestLogHandlers(environment); Collection<ServletContextHandler> servletContextHandlers = createServletContexts(environment); Collection<ContextHandler> contextHandlers = createContextHandlers(environment); ContextHandlerCollection contexts = new ContextHandlerCollection(); addContextHandlers(contexts, servletContextHandlers); addContextHandlers(contexts, contextHandlers); if (contexts.getHandlers() != null && contexts.getHandlers().length > 0) { handlers.addHandler(contexts); } // Shutdown Handler of Jetty ShutdownHandler shutdownHandler = createShutdownHandler(environment); if (shutdownHandler != null) { handlers.addHandler(shutdownHandler); } // Log handlers are created the first but processed the // last. In case there is an access log handler, the HTTP // response codes should be correct. addHandlers(handlers, requestLogHandlers); return handlers; } /** * See {@link ApplicationFactoryLoader}. * * @param environment the environment * @return the collection of loaded * {@link ServletContextHandler}s */ protected Collection<ServletContextHandler> createServletContexts(Environment environment) { ApplicationFactoryLoader afl = new ApplicationFactoryLoader(); return afl.apply(environment); } /** * See {@link ContextHandlerFactoryLoader}. * * @param environment the environment * @return a collection of loaded {@link ContextHandler} */ protected Collection<ContextHandler> createContextHandlers(Environment environment) { ContextHandlerFactoryLoader chfl = new ContextHandlerFactoryLoader(); return chfl.apply(environment); } /** * See {@link RequestLogHandlerFactoryLoader}. * * @param environment the environment * @return the {@link List} of loaded * {@link RequestLogHandler}s */ protected List<RequestLogHandler> createRequestLogHandlers(Environment environment) { RequestLogHandlerFactoryLoader rlhfl = new RequestLogHandlerFactoryLoader(); return rlhfl.apply(environment); } /** * Creates Jetty's {@link ShutdownHandler}. * * @param environment the environment * @return an instance of {@link ShutdownHandler} if * {@link Environment#SERVER_SHUTDOWN_TOKEN_KEY} is * available; otherwise <code>null</code> */ protected ShutdownHandler createShutdownHandler(Environment environment) { String shutdownToken = environment.getServerShutdownToken(); if (shutdownToken == null || shutdownToken.isEmpty()) { return null; } return new ShutdownHandler(shutdownToken, true, false); } private void addHandlers(HandlerCollection parentHandler, Collection<? extends AbstractHandler> childHandlers) { if (!childHandlers.isEmpty()) { for (AbstractHandler h : childHandlers) { parentHandler.addHandler(h); } } } private void addContextHandlers(ContextHandlerCollection parentHandler, Collection<? extends ContextHandler> childContexts) { if (!childContexts.isEmpty()) { for (ContextHandler h : childContexts) { parentHandler.addHandler(h); } } } }