/** * Copyright 2010 Marko Lavikainen * * 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 net.contextfw.web.application.internal; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedSet; import java.util.regex.Pattern; import net.contextfw.web.application.PropertyProvider; import net.contextfw.web.application.ResourceCleaner; import net.contextfw.web.application.configuration.Configuration; import net.contextfw.web.application.internal.development.InternalDevelopmentTools; import net.contextfw.web.application.internal.development.ReloadingClassLoaderConf; import net.contextfw.web.application.internal.initializer.InitializerProvider; import net.contextfw.web.application.internal.page.PageScope; import net.contextfw.web.application.internal.service.DirectoryWatcher; import net.contextfw.web.application.internal.service.InitHandler; import net.contextfw.web.application.internal.service.UpdateHandler; import net.contextfw.web.application.internal.servlet.CSSServlet; import net.contextfw.web.application.internal.servlet.DevelopmentFilter; import net.contextfw.web.application.internal.servlet.InitServlet; import net.contextfw.web.application.internal.servlet.RegexUriMapping; import net.contextfw.web.application.internal.servlet.ScriptServlet; import net.contextfw.web.application.internal.servlet.UpdateServlet; import net.contextfw.web.application.internal.servlet.UriMapping; import net.contextfw.web.application.internal.servlet.UriMappingFactory; import net.contextfw.web.application.internal.util.ClassScanner; import net.contextfw.web.application.lifecycle.LifecycleListener; import net.contextfw.web.application.lifecycle.RequestInvocationFilter; import net.contextfw.web.application.scope.WebApplicationStorage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.gson.Gson; import com.google.inject.Provides; import com.google.inject.Singleton; import com.google.inject.servlet.ServletModule; public class WebApplicationServletModule extends ServletModule { private Logger logger = LoggerFactory.getLogger(WebApplicationServletModule.class); private final Pattern classPattern = Pattern.compile(".+\\.class"); private final PropertyProvider properties; private final String resourcePrefix; private final Set<String> rootPackages; private final Configuration configuration; private final Map<String, InitServlet> servlets = new HashMap<String, InitServlet>(); private InitializerProvider initializerProvider; private ReloadingClassLoaderConf reloadConf; private final RequestInvocationFilter filter; private InitHandler initHandler; private PageScope pageScope; private InternalDevelopmentTools internalDevelopmentTools; public WebApplicationServletModule( Configuration configuration, PropertyProvider propertyProvider, PageScope pageScope, InternalDevelopmentTools internalDevelopmentTools) { resourcePrefix = configuration.get(Configuration.RESOURCES_PREFIX); this.configuration = configuration; this.properties = propertyProvider; this.pageScope = pageScope; this.internalDevelopmentTools = internalDevelopmentTools; rootPackages = configuration.get(Configuration.VIEW_COMPONENT_ROOT_PACKAGE); boolean reloadEnabled = configuration.get(Configuration.CLASS_RELOADING_ENABLED); if (reloadEnabled && configuration.get(Configuration.DEVELOPMENT_MODE)) { reloadConf = new ReloadingClassLoaderConf(configuration); } this.filter = configuration.get(Configuration.REQUEST_INVOCATION_FILTER); } @Override protected void configureServlets() { //bind(RequestInvocationFilter.class).toInstance(this.filter); requestInjection(this.filter); initHandler = new InitHandler(configuration, pageScope, internalDevelopmentTools); requestInjection(initHandler); initializerProvider = new InitializerProvider(); serve(resourcePrefix + ".js").with( ScriptServlet.class); serve(resourcePrefix + ".css").with( CSSServlet.class); serveRegex(".*/contextfw-update/.*").with(UpdateServlet.class); serveRegex(".*/contextfw-refresh/.*").with(UpdateServlet.class); serveRegex(".*/contextfw-remove/.*").with(UpdateServlet.class); requestInjection(this); if (configuration.get(Configuration.DEVELOPMENT_MODE)) { serveDevelopmentMode(); } else { serveProductionMode(); } } private void serveDevelopmentMode() { logger.info("Serving view components in DEVELOPMENT mode"); DirectoryWatcher classWatcher = reloadConf == null ? new DirectoryWatcher(configuration.get(Configuration.VIEW_COMPONENT_ROOT_PACKAGE), classPattern) : new DirectoryWatcher(reloadConf.getReloadablePackageNames(), classPattern); DevelopmentFilter developmentFilter = new DevelopmentFilter( rootPackages, initHandler, initializerProvider, internalDevelopmentTools, classWatcher, properties, filter); filter("/*").through(developmentFilter); requestInjection(developmentFilter); } private void serveProductionMode() { logger.info("Serving view components in PRODUCTION mode"); List<Class<?>> classes = ClassScanner.getClasses(rootPackages); ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); UriMappingFactory fact = new UriMappingFactory(); SortedSet<UriMapping> mappings = fact.createMappings( classes, classLoader, initializerProvider, initHandler, properties, filter); serveMappings(mappings); } private void serveMappings(SortedSet<UriMapping> mappings) { for (UriMapping mapping : mappings) { servlets.put(mapping.getViewClass().getCanonicalName(), mapping.getInitServlet()); if (mapping instanceof RegexUriMapping) { logger.info(" Serving url: " + mapping.getViewClass().getName() + " => {} (regex)", mapping.getPath()); serveRegex(mapping.getPath()).with(mapping.getInitServlet()); } else { logger.info(" Serving url: " + mapping.getViewClass().getName() + " => {}", mapping.getPath()); serve(mapping.getPath()).with(mapping.getInitServlet()); } } } @Provides @Singleton public UpdateHandler provideUpdateHandler( LifecycleListener listeners, DirectoryWatcher watcher, ResourceCleaner cleaner, WebApplicationStorage storage, Gson gson) { return new UpdateHandler(listeners, watcher, cleaner, storage, configuration, pageScope, gson); } }