// Copyright (c) 2003-present, Jodd Team (http://jodd.org) // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. package jodd.madvoc; import jodd.madvoc.component.ActionMethodParamNameResolver; import jodd.madvoc.component.ActionPathMacroManager; import jodd.madvoc.component.ContextInjectorComponent; import jodd.madvoc.component.FiltersManager; import jodd.madvoc.component.InjectorsManager; import jodd.madvoc.component.InterceptorsManager; import jodd.madvoc.component.ResultsManager; import jodd.madvoc.component.ActionMethodParser; import jodd.madvoc.component.ActionsManager; import jodd.madvoc.component.MadvocController; import jodd.madvoc.component.MadvocConfig; import jodd.madvoc.component.ResultMapper; import jodd.madvoc.component.ActionPathRewriter; import jodd.madvoc.component.ScopeDataResolver; import jodd.madvoc.config.MadvocConfigurator; import jodd.petite.PetiteContainer; import javax.servlet.ServletContext; import java.lang.reflect.Modifier; import java.util.Properties; import jodd.props.Props; import jodd.log.Logger; import jodd.log.LoggerFactory; /** * Web application contains all configurations and holds all managers and controllers of one web application. * Custom implementations may override this class to enhance several different functionality. */ @SuppressWarnings({"UnusedDeclaration"}) public class WebApplication { private static Logger log; public static final String MADVOC_CONTAINER_NAME = "madpc"; protected PetiteContainer madpc; /** * Creates web application. Application is not initialized. * @see #WebApplication(boolean) */ public WebApplication() { } /** * Creates web application and optionally {@link #initWebApplication() initializes} it. */ public WebApplication(boolean init) { if (init) { initWebApplication(); } } /** * Initializes web application. Invoked very first. * By default, it creates a Logger and creates internal Petite container. * Also adds itself into it. */ protected void initWebApplication() { log = LoggerFactory.getLogger(WebApplication.class); log.debug("Initializing Madvoc web application"); madpc = new PetiteContainer(); madpc.addSelf(MADVOC_CONTAINER_NAME); } // ---------------------------------------------------------------- components /** * Resolves the name of the last base non-abstract subclass for provided component. * It iterates all subclasses up to the <code>Object</cde> and declares the last * non-abstract class as base component. Component name will be resolved from the * founded base component. */ private String resolveBaseComponentName(Class component) { Class lastComponent = component; while (true) { Class superClass = component.getSuperclass(); if (superClass.equals(Object.class)) { break; } component = superClass; if (!Modifier.isAbstract(component.getModifiers())) { lastComponent = component; } } return madpc.resolveBeanName(lastComponent); } /** * Registers component using its {@link #resolveBaseComponentName(Class) base name}. * Previously defined component will be removed. * @see #registerComponent(Object) */ public final void registerComponent(Class component) { String name = resolveBaseComponentName(component); registerComponent(name, component); } public final void registerComponent(String name, Class component) { if (log.isDebugEnabled()) { log.debug("Registering component '" + name + "' of type " + component.getName()); } madpc.removeBean(name); madpc.registerPetiteBean(component, name, null, null, false); } /** * Registers component instance using its {@link #resolveBaseComponentName(Class) base name}. * Previously defined component will be removed. * @see #registerComponent(Class) */ public final void registerComponent(Object componentInstance) { Class component = componentInstance.getClass(); String name = resolveBaseComponentName(component); registerComponent(name, componentInstance); } /** * Registers component instance and wires it with internal container. */ public final void registerComponent(String name, Object componentInstance) { if (log.isDebugEnabled()) { log.debug("Registering component '" + name + "' instance of " + componentInstance.getClass().getName()); } madpc.removeBean(name); madpc.addBean(name, componentInstance); } /** * Returns registered component. Should be used only in special cases. */ @SuppressWarnings({"unchecked"}) public <T> T getComponent(Class<T> component) { String name = resolveBaseComponentName(component); return (T) madpc.getBean(name); } /** * Returns registered component. */ public Object getComponent(String componentName) { return madpc.getBean(componentName); } /** * Registers default Madvoc components. * Invoked before {@link #init(MadvocConfig , ServletContext) madvoc initialization}. */ public void registerMadvocComponents() { log.debug("Registering Madvoc components"); registerComponent(ActionMethodParser.class); registerComponent(ActionMethodParamNameResolver.class); registerComponent(ActionPathRewriter.class); registerComponent(ActionPathMacroManager.class); registerComponent(ActionsManager.class); registerComponent(ContextInjectorComponent.class); registerComponent(InjectorsManager.class); registerComponent(InterceptorsManager.class); registerComponent(FiltersManager.class); registerComponent(MadvocConfig.class); registerComponent(MadvocController.class); registerComponent(ResultsManager.class); registerComponent(ResultMapper.class); registerComponent(ScopeDataResolver.class); } // ---------------------------------------------------------------- lifecycle /** * Initialized web application parameters. Provided properties object is always non-<code>null</code>. * Simple defines parameters for internal container. */ protected void defineParams(Properties properties) { log.debug("Defining Madvoc parameters"); madpc.defineParameters(properties); } protected void defineParams(Props props) { log.debug("Defining Madvoc parameters"); madpc.defineParameters(props); } /** * Initializes web application custom configuration. * When running web application out from container, * <code>servletContext</code> may be <code>null</code>. */ protected void init(MadvocConfig madvocConfig, ServletContext servletContext) { log.debug("Initializing Madvoc"); } /** * Hook for filters. */ protected void initFilters(FiltersManager filtersManager) { log.debug("Initializing Madvoc filters"); } /** * Hook for interceptors. */ protected void initInterceptors(InterceptorsManager interceptorsManager) { log.debug("Initializing Madvoc interceptors"); } /** * Hook for actions manager. Allows manual registration of the actions. */ protected void initActions(ActionsManager actionManager) { log.debug("Initializing Madvoc actions"); } /** * Hook for manually registered results. */ protected void initResults(ResultsManager actionManager) { log.debug("Initializing Madvoc results"); } /** * Called when Madvoc is up and ready. */ protected void ready() { log.info("Madvoc is ready"); } /** * Invoked on web application destroy. */ protected void destroy(MadvocConfig madvocConfig) { log.debug("Destroying Madvoc"); } // ---------------------------------------------------------------- configurator /** * Adds configurator to Madvoc container and invokes configuration. */ public void configure(MadvocConfigurator configurator) { log.debug("Configuring Madvoc"); registerComponent(configurator); configurator.configure(); } }