/* Copyright 2005-2006 Tim Fennell
*
* 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.sourceforge.stripes.config;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import net.sourceforge.stripes.controller.ActionBeanContextFactory;
import net.sourceforge.stripes.controller.ActionBeanPropertyBinder;
import net.sourceforge.stripes.controller.ActionResolver;
import net.sourceforge.stripes.controller.BeforeAfterMethodInterceptor;
import net.sourceforge.stripes.controller.DefaultActionBeanContextFactory;
import net.sourceforge.stripes.controller.DefaultActionBeanPropertyBinder;
import net.sourceforge.stripes.controller.Interceptor;
import net.sourceforge.stripes.controller.Intercepts;
import net.sourceforge.stripes.controller.LifecycleStage;
import net.sourceforge.stripes.controller.NameBasedActionResolver;
import net.sourceforge.stripes.controller.multipart.DefaultMultipartWrapperFactory;
import net.sourceforge.stripes.controller.multipart.MultipartWrapperFactory;
import net.sourceforge.stripes.exception.DefaultExceptionHandler;
import net.sourceforge.stripes.exception.ExceptionHandler;
import net.sourceforge.stripes.exception.StripesRuntimeException;
import net.sourceforge.stripes.format.DefaultFormatterFactory;
import net.sourceforge.stripes.format.FormatterFactory;
import net.sourceforge.stripes.localization.DefaultLocalePicker;
import net.sourceforge.stripes.localization.DefaultLocalizationBundleFactory;
import net.sourceforge.stripes.localization.LocalePicker;
import net.sourceforge.stripes.localization.LocalizationBundleFactory;
import net.sourceforge.stripes.tag.DefaultPopulationStrategy;
import net.sourceforge.stripes.tag.DefaultTagErrorRendererFactory;
import net.sourceforge.stripes.tag.PopulationStrategy;
import net.sourceforge.stripes.tag.TagErrorRendererFactory;
import net.sourceforge.stripes.util.ssl.DefaultSslConfiguration;
import net.sourceforge.stripes.util.ssl.SslConfiguration;
import net.sourceforge.stripes.validation.DefaultTypeConverterFactory;
import net.sourceforge.stripes.validation.TypeConverterFactory;
/**
*
Centralized location for defaults for all Configuration properties. This implementation does
* not lookup configuration information anywhere! It returns hard-coded defaults that will result
* in a working system without any user intervention.
*
* Despite it's name the DefaultConfiguration is not in fact the default Configuration
* implementation in Stripes! Instead it is the retainer of default configuration values. The
* Configuration implementation that is used when no alternative is configured is the
* {@link RuntimeConfiguration}, which is a direct subclass of DefaultConfiguration, and when no
* further configuration properties are supplied behaves identically to the DefaultConfiguration.
*
* The DefaultConfiguration is designed to be easily extended as needed. The init() method
* ensures that compoments are initialized in the correct order (taking dependencies into account),
* and should generally not be overridden. It invokes a number of initXXX() methods, one per
* configurable component. Subclasses should override any of the initXXX() methods desirable to
* return a fully initialized instance of the relevant component type, or null if the default is
* desired.
*
* @author Tim Fennell
*/
public class DefaultConfiguration implements Configuration {
private BootstrapPropertyResolver resolver;
private ActionResolver actionResolver;
private ActionBeanPropertyBinder actionBeanPropertyBinder;
private ActionBeanContextFactory actionBeanContextFactory;
private TypeConverterFactory typeConverterFactory;
private LocalizationBundleFactory localizationBundleFactory;
private LocalePicker localePicker;
private FormatterFactory formatterFactory;
private TagErrorRendererFactory tagErrorRendererFactory;
private PopulationStrategy populationStrategy;
private Map> interceptors;
private ExceptionHandler exceptionHandler;
private MultipartWrapperFactory multipartWrapperFactory;
/** Gratefully accepts the BootstrapPropertyResolver handed to the Configuration. */
public void setBootstrapPropertyResolver(BootstrapPropertyResolver resolver) {
this.resolver = resolver;
}
/**
* Creates and stores instances of the objects of the type that the Configuration is
* responsible for providing, except where subclasses have already provided instances.
*/
public void init() {
try {
this.actionResolver = initActionResolver();
if (this.actionResolver == null) {
this.actionResolver = new NameBasedActionResolver();
this.actionResolver.init(this);
}
this.actionBeanPropertyBinder = initActionBeanPropertyBinder();
if (this.actionBeanPropertyBinder == null) {
this.actionBeanPropertyBinder = new DefaultActionBeanPropertyBinder();
this.actionBeanPropertyBinder.init(this);
}
this.actionBeanContextFactory = initActionBeanContextFactory();
if (this.actionBeanContextFactory == null) {
this.actionBeanContextFactory = new DefaultActionBeanContextFactory();
this.actionBeanContextFactory.init(this);
}
this.typeConverterFactory = initTypeConverterFactory();
if (this.typeConverterFactory == null) {
this.typeConverterFactory = new DefaultTypeConverterFactory();
this.typeConverterFactory.init(this);
}
this.localizationBundleFactory = initLocalizationBundleFactory();
if (this.localizationBundleFactory == null) {
this.localizationBundleFactory = new DefaultLocalizationBundleFactory();
this.localizationBundleFactory.init(this);
}
this.localePicker = initLocalePicker();
if (this.localePicker == null) {
this.localePicker = new DefaultLocalePicker();
this.localePicker.init(this);
}
this.formatterFactory = initFormatterFactory();
if (this.formatterFactory == null) {
this.formatterFactory = new DefaultFormatterFactory();
this.formatterFactory.init(this);
}
this.tagErrorRendererFactory = initTagErrorRendererFactory();
if (this.tagErrorRendererFactory == null) {
this.tagErrorRendererFactory = new DefaultTagErrorRendererFactory();
this.tagErrorRendererFactory.init(this);
}
this.populationStrategy = initPopulationStrategy();
if (this.populationStrategy == null) {
this.populationStrategy = new DefaultPopulationStrategy();
this.populationStrategy.init(this);
}
this.exceptionHandler = initExceptionHandler();
if (this.exceptionHandler == null) {
this.exceptionHandler = new DefaultExceptionHandler();
this.exceptionHandler.init(this);
}
this.multipartWrapperFactory = initMultipartWrapperFactory();
if (this.multipartWrapperFactory == null) {
this.multipartWrapperFactory = new DefaultMultipartWrapperFactory();
this.multipartWrapperFactory.init(this);
}
this.interceptors = initInterceptors();
if (this.interceptors == null) {
this.interceptors = new HashMap>();
Class extends Interceptor> bam = BeforeAfterMethodInterceptor.class;
BeforeAfterMethodInterceptor interceptor = new BeforeAfterMethodInterceptor();
for (LifecycleStage stage : bam.getAnnotation(Intercepts.class).value()) {
Collection instances = new ArrayList();
instances.add(interceptor);
this.interceptors.put(stage, instances);
}
}
// BEGIN SSL MOD ------------------------------------------------------------
this.sslConfiguration = initSslConfiguration();
if (this.sslConfiguration == null) {
this.sslConfiguration = new DefaultSslConfiguration();
sslConfiguration.init(this);
}
// END SSL MOD --------------------------------------------------------------
}
catch (Exception e) {
throw new StripesRuntimeException
("Problem instantiating default configuration objects.", e);
}
}
/** Returns a reference to the resolver supplied at initialziation time. */
public BootstrapPropertyResolver getBootstrapPropertyResolver() {
return this.resolver;
}
/**
* Retrieves the ServletContext for the context within which the Stripes application is
* executing.
*
* @return the ServletContext in which the application is running
*/
public ServletContext getServletContext() {
return getBootstrapPropertyResolver().getFilterConfig().getServletContext();
}
/**
* Returns an instance of {@link NameBasedActionResolver} unless a subclass has
* overridden the default.
* @return ActionResolver an instance of the configured resolver
*/
public ActionResolver getActionResolver() {
return this.actionResolver;
}
/** Allows subclasses to initialize a non-default ActionResovler. */
protected ActionResolver initActionResolver() { return null; }
/**
* Returns an instance of {@link DefaultActionBeanPropertyBinder} unless a subclass has
* overridden the default.
* @return ActionBeanPropertyBinder an instance of the configured binder
*/
public ActionBeanPropertyBinder getActionBeanPropertyBinder() {
return this.actionBeanPropertyBinder;
}
/** Allows subclasses to initizlize a non-default ActionBeanPropertyBinder. */
protected ActionBeanPropertyBinder initActionBeanPropertyBinder() { return null; }
/**
* Returns the configured ActionBeanContextFactory. Unless a subclass has configured a custom
* one, the instance will be a DefaultActionBeanContextFactory.
*
* @return ActionBeanContextFactory an instance of a factory for creating ActionBeanContexts
*/
public ActionBeanContextFactory getActionBeanContextFactory() {
return this.actionBeanContextFactory;
}
/** Allows subclasses to initialize a non-default ActionBeanContextFactory. */
protected ActionBeanContextFactory initActionBeanContextFactory() { return null; }
/**
* Returns an instance of {@link DefaultTypeConverterFactory} unless a subclass has
* overridden the default..
* @return TypeConverterFactory an instance of the configured factory.
*/
public TypeConverterFactory getTypeConverterFactory() {
return this.typeConverterFactory;
}
/** Allows subclasses to initizlize a non-default TypeConverterFactory. */
protected TypeConverterFactory initTypeConverterFactory() { return null; }
/**
* Returns an instance of a LocalizationBundleFactory. By default this will be an instance of
* DefaultLocalizationBundleFactory unless another type has been configured.
*/
public LocalizationBundleFactory getLocalizationBundleFactory() {
return this.localizationBundleFactory;
}
/** Allows subclasses to initialize a non-default LocalizationBundleFactory. */
protected LocalizationBundleFactory initLocalizationBundleFactory() { return null; }
/**
* Returns an instance of a LocalePicker. Unless a subclass has picked another implementation
* will return an instance of DefaultLocalePicker.
*/
public LocalePicker getLocalePicker() { return this.localePicker; }
/** Allows subclasses to initialize a non-default LocalePicker. */
protected LocalePicker initLocalePicker() { return null; }
/**
* Returns an instance of a FormatterFactory. Unless a subclass has picked another implementation
* will return an instance of DefaultFormatterFactory.
*/
public FormatterFactory getFormatterFactory() { return this.formatterFactory; }
/** Allows subclasses to initialize a non-default FormatterFactory. */
protected FormatterFactory initFormatterFactory() { return null; }
/**
* Returns an instance of a TagErrorRendererFactory. Unless a subclass has picked another
* implementation, will return an instance of DefaultTagErrorRendererFactory.
*/
public TagErrorRendererFactory getTagErrorRendererFactory() {
return tagErrorRendererFactory;
}
/** Allows subclasses to initialize a non-default TagErrorRendererFactory instance to be used. */
protected TagErrorRendererFactory initTagErrorRendererFactory() { return null; }
/**
* Returns an instance of a PopulationsStrategy. Unless a sublcass has picked another
* implementation, will return an instance of
* {@link net.sourceforge.stripes.tag.DefaultPopulationStrategy}.
*/
public PopulationStrategy getPopulationStrategy() { return this.populationStrategy; }
/** Allows subclasses to initialize a non-default PopulationStrategy instance to be used. */
protected PopulationStrategy initPopulationStrategy() { return null; }
/**
* Returns an instance of an ExceptionHandler. Unless a sublcass has picked another
* implementation, will return an instance of
* {@link net.sourceforge.stripes.exception.DefaultExceptionHandler}.
*/
public ExceptionHandler getExceptionHandler() { return this.exceptionHandler; }
/** Allows subclasses to initialize a non-default ExceptionHandler instance to be used. */
protected ExceptionHandler initExceptionHandler() { return null; }
/**
* Returns an instance of MultipartWrapperFactory that can be used by Stripes to construct
* MultipartWrapper instances for dealing with multipart requests (those containing file
* uploads).
*
* @return MultipartWrapperFactory an instance of the wrapper factory
*/
public MultipartWrapperFactory getMultipartWrapperFactory() {
return this.multipartWrapperFactory;
}
/** Allows subclasses to initialize a non-default MultipartWrapperFactory. */
protected MultipartWrapperFactory initMultipartWrapperFactory() { return null; }
/**
* Returns a list of interceptors that should be executed around the lifecycle stage
* indicated. By default returns a single element list containing the
* {@link BeforeAfterMethodInterceptor}.
*/
public Collection getInterceptors(LifecycleStage stage) {
Collection interceptors = this.interceptors.get(stage);
if (interceptors == null) {
interceptors = Collections.emptyList();
}
return interceptors;
}
/** Allows subclasses to initialize a non-default Map of Interceptor instances. */
protected Map> initInterceptors() { return null; }
// BEGIN SSL MOD ------------------------------------------------------------
private SslConfiguration sslConfiguration;
protected SslConfiguration initSslConfiguration() {
return null;
}
/*
* (non-Javadoc)
*
* @see net.sourceforge.stripes.config.Configuration#getSslConfiguration()
*/
public SslConfiguration getSslConfiguration() {
return this.sslConfiguration;
}
// END SSL MOD --------------------------------------------------------------
}