
net.sourceforge.stripes.config.RuntimeConfiguration Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of stripes Show documentation
Show all versions of stripes Show documentation
Stripes web framework jar, including tag library.
/* 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.lang.reflect.Type;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.sourceforge.stripes.controller.ActionBeanContextFactory;
import net.sourceforge.stripes.controller.ActionBeanPropertyBinder;
import net.sourceforge.stripes.controller.ActionResolver;
import net.sourceforge.stripes.controller.Interceptor;
import net.sourceforge.stripes.controller.LifecycleStage;
import net.sourceforge.stripes.controller.ObjectFactory;
import net.sourceforge.stripes.controller.multipart.MultipartWrapperFactory;
import net.sourceforge.stripes.exception.ExceptionHandler;
import net.sourceforge.stripes.exception.StripesRuntimeException;
import net.sourceforge.stripes.format.Formatter;
import net.sourceforge.stripes.format.FormatterFactory;
import net.sourceforge.stripes.localization.LocalePicker;
import net.sourceforge.stripes.localization.LocalizationBundleFactory;
import net.sourceforge.stripes.tag.PopulationStrategy;
import net.sourceforge.stripes.tag.TagErrorRendererFactory;
import net.sourceforge.stripes.util.Log;
import net.sourceforge.stripes.util.ReflectUtil;
import net.sourceforge.stripes.validation.TypeConverter;
import net.sourceforge.stripes.validation.TypeConverterFactory;
import net.sourceforge.stripes.validation.ValidationMetadataProvider;
/**
* Configuration class that uses the BootstrapPropertyResolver to look for configuration values,
* and when it cannot find a value, falls back on the DefaultConfiguration to supply default
* values. In general, the RuntimeConfiguration will operate in the following pattern:
*
*
* - Look for the value of a configuration property in the BootstrapProperties
* - If the value exists, the configuration will attempt to use it (usually to instantiate
* a class). If an exception occurs, the RuntimeConfiguration will throw an exception and
* not provide a value. In most cases this will be fatal!
* - If the value does not exist, the default from DefaultConfiguration will be used.
*
*
* @author Tim Fennell
*/
public class RuntimeConfiguration extends DefaultConfiguration {
/** Log implementation for use within this class. */
private static final Log log = Log.getInstance(RuntimeConfiguration.class);
/** The Configuration Key for enabling debug mode. */
public static final String DEBUG_MODE = "Stripes.DebugMode";
/** The Configuration Key for looking up the name of the ObjectFactory class */
public static final String OBJECT_FACTORY = "ObjectFactory.Class";
/** The Configuration Key for looking up the name of the ActionResolver class. */
public static final String ACTION_RESOLVER = "ActionResolver.Class";
/** The Configuration Key for looking up the name of the ActionResolver class. */
public static final String ACTION_BEAN_PROPERTY_BINDER = "ActionBeanPropertyBinder.Class";
/** The Configuration Key for looking up the name of an ActionBeanContextFactory class. */
public static final String ACTION_BEAN_CONTEXT_FACTORY = "ActionBeanContextFactory.Class";
/** The Configuration Key for looking up the name of the TypeConverterFactory class. */
public static final String TYPE_CONVERTER_FACTORY = "TypeConverterFactory.Class";
/** The Configuration Key for looking up the name of the LocalizationBundleFactory class. */
public static final String LOCALIZATION_BUNDLE_FACTORY = "LocalizationBundleFactory.Class";
/** The Configuration Key for looking up the name of the LocalizationBundleFactory class. */
public static final String LOCALE_PICKER = "LocalePicker.Class";
/** The Configuration Key for looking up the name of the FormatterFactory class. */
public static final String FORMATTER_FACTORY = "FormatterFactory.Class";
/** The Configuration Key for looking up the name of the TagErrorRendererFactory class */
public static final String TAG_ERROR_RENDERER_FACTORY = "TagErrorRendererFactory.Class";
/** The Configuration Key for looking up the name of the PopulationStrategy class */
public static final String POPULATION_STRATEGY = "PopulationStrategy.Class";
/** The Configuration Key for looking up the name of the ExceptionHandler class */
public static final String EXCEPTION_HANDLER = "ExceptionHandler.Class";
/** The Configuration Key for looking up the name of the MultipartWrapperFactory class */
public static final String MULTIPART_WRAPPER_FACTORY = "MultipartWrapperFactory.Class";
/** The Configuration Key for looking up the name of the ValidationMetadataProvider class */
public static final String VALIDATION_METADATA_PROVIDER = "ValidationMetadataProvider.Class";
/** The Configuration Key for looking up the comma separated list of core interceptor classes. */
public static final String CORE_INTERCEPTOR_LIST = "CoreInterceptor.Classes";
/** The Configuration Key for looking up the comma separated list of interceptor classes. */
public static final String INTERCEPTOR_LIST = "Interceptor.Classes";
/** Looks for a true/false value in config. */
@Override protected Boolean initDebugMode() {
try {
return Boolean.valueOf(getBootstrapPropertyResolver().getProperty(DEBUG_MODE)
.toLowerCase());
}
catch (Exception e) {
return null;
}
}
/** Looks for a class name in config and uses that to create the component. */
@Override protected ObjectFactory initObjectFactory() {
return initializeComponent(ObjectFactory.class, OBJECT_FACTORY);
}
/** Looks for a class name in config and uses that to create the component. */
@Override protected ActionResolver initActionResolver() {
return initializeComponent(ActionResolver.class, ACTION_RESOLVER);
}
/** Looks for a class name in config and uses that to create the component. */
@Override protected ActionBeanPropertyBinder initActionBeanPropertyBinder() {
return initializeComponent(ActionBeanPropertyBinder.class, ACTION_BEAN_PROPERTY_BINDER);
}
/** Looks for a class name in config and uses that to create the component. */
@Override protected ActionBeanContextFactory initActionBeanContextFactory() {
return initializeComponent(ActionBeanContextFactory.class, ACTION_BEAN_CONTEXT_FACTORY);
}
/** Looks for a class name in config and uses that to create the component. */
@Override protected TypeConverterFactory initTypeConverterFactory() {
return initializeComponent(TypeConverterFactory.class, TYPE_CONVERTER_FACTORY);
}
/** Looks for a class name in config and uses that to create the component. */
@Override protected LocalizationBundleFactory initLocalizationBundleFactory() {
return initializeComponent(LocalizationBundleFactory.class, LOCALIZATION_BUNDLE_FACTORY);
}
/** Looks for a class name in config and uses that to create the component. */
@Override protected LocalePicker initLocalePicker() {
return initializeComponent(LocalePicker.class, LOCALE_PICKER);
}
/** Looks for a class name in config and uses that to create the component. */
@Override protected FormatterFactory initFormatterFactory() {
return initializeComponent(FormatterFactory.class, FORMATTER_FACTORY);
}
/** Looks for a class name in config and uses that to create the component. */
@Override protected TagErrorRendererFactory initTagErrorRendererFactory() {
return initializeComponent(TagErrorRendererFactory.class, TAG_ERROR_RENDERER_FACTORY);
}
/** Looks for a class name in config and uses that to create the component. */
@Override protected PopulationStrategy initPopulationStrategy() {
return initializeComponent(PopulationStrategy.class, POPULATION_STRATEGY);
}
/** Looks for a class name in config and uses that to create the component. */
@Override protected ExceptionHandler initExceptionHandler() {
return initializeComponent(ExceptionHandler.class, EXCEPTION_HANDLER);
}
/** Looks for a class name in config and uses that to create the component. */
@Override protected MultipartWrapperFactory initMultipartWrapperFactory() {
return initializeComponent(MultipartWrapperFactory.class, MULTIPART_WRAPPER_FACTORY);
}
/** Looks for a class name in config and uses that to create the component. */
@Override protected ValidationMetadataProvider initValidationMetadataProvider() {
return initializeComponent(ValidationMetadataProvider.class, VALIDATION_METADATA_PROVIDER);
}
/**
* Looks for a list of class names separated by commas under the configuration key
* {@link #CORE_INTERCEPTOR_LIST}. White space surrounding the class names is trimmed,
* the classes instantiated and then stored under the lifecycle stage(s) they should
* intercept.
*
* @return a Map of {@link LifecycleStage} to Collection of {@link Interceptor}
*/
@Override
protected Map> initCoreInterceptors() {
List> coreInterceptorClasses = getBootstrapPropertyResolver().getClassPropertyList(CORE_INTERCEPTOR_LIST);
if (coreInterceptorClasses.size() == 0)
return super.initCoreInterceptors();
else
return initInterceptors(coreInterceptorClasses);
}
/**
* Looks for a list of class names separated by commas under the configuration key
* {@link #INTERCEPTOR_LIST}. White space surrounding the class names is trimmed,
* the classes instantiated and then stored under the lifecycle stage(s) they should
* intercept.
*
* @return a Map of {@link LifecycleStage} to Collection of {@link Interceptor}
*/
@Override
protected Map> initInterceptors() {
return initInterceptors(getBootstrapPropertyResolver().getClassPropertyList(INTERCEPTOR_LIST, Interceptor.class));
}
/**
* Splits a comma-separated list of class names and maps each {@link LifecycleStage} to the
* interceptors in the list that intercept it. Also automatically finds Interceptors in
* packages listed in {@link BootstrapPropertyResolver#PACKAGES} if searchExtensionPackages is true.
*
* @return a Map of {@link LifecycleStage} to Collection of {@link Interceptor}
*/
@SuppressWarnings("unchecked")
protected Map> initInterceptors(List classes) {
Map> map = new HashMap>();
for (Object type : classes) {
try {
Interceptor interceptor = getObjectFactory().newInstance(
(Class extends Interceptor>) type);
addInterceptor(map, interceptor);
}
catch (Exception e) {
throw new StripesRuntimeException("Could not instantiate configured Interceptor ["
+ type.getClass().getName() + "].", e);
}
}
return map;
}
/**
* Internal utility method that is used to implement the main pattern of this class: lookup the
* name of a class based on a property name, instantiate the named class and initialize it.
*
* @param componentType a Class object representing a subclass of ConfigurableComponent
* @param propertyName the name of the property to look up for the class name
* @return an instance of the component, or null if one was not configured.
*/
@SuppressWarnings("unchecked")
protected T initializeComponent(Class componentType,
String propertyName) {
Class clazz = getBootstrapPropertyResolver().getClassProperty(propertyName, componentType);
if (clazz != null) {
try {
T component;
ObjectFactory objectFactory = getObjectFactory();
if (objectFactory != null) {
component = objectFactory.newInstance((Class) clazz);
}
else {
component = (T) clazz.newInstance();
}
component.init(this);
return component;
}
catch (Exception e) {
throw new StripesRuntimeException("Could not instantiate configured "
+ componentType.getSimpleName() + " of type [" + clazz.getSimpleName()
+ "]. Please check "
+ "the configuration parameters specified in your web.xml.", e);
}
}
else {
return null;
}
}
/**
* Calls super.init() then adds Formatters and TypeConverters found in
* packages listed in {@link BootstrapPropertyResolver#PACKAGES} to their respective factories.
*/
@SuppressWarnings("unchecked")
@Override
public void init() {
super.init();
List> formatters = getBootstrapPropertyResolver().getClassPropertyList(Formatter.class);
for (Class extends Formatter> formatter : formatters) {
Type[] typeArguments = ReflectUtil.getActualTypeArguments(formatter, Formatter.class);
log.trace("Found Formatter [", formatter, "] - type parameters: ", typeArguments);
if ((typeArguments != null) && (typeArguments.length == 1)
&& !typeArguments[0].equals(Object.class)) {
if (typeArguments[0] instanceof Class) {
log.debug("Adding auto-discovered Formatter [", formatter, "] for [", typeArguments[0], "] (from type parameter)");
getFormatterFactory().add((Class>) typeArguments[0], (Class extends Formatter>>) formatter);
}
else {
log.warn("Type parameter for non-abstract Formatter [", formatter, "] is not a class.");
}
}
TargetTypes targetTypes = formatter.getAnnotation(TargetTypes.class);
if (targetTypes != null) {
for (Class> targetType : targetTypes.value()) {
log.debug("Adding auto-discovered Formatter [", formatter, "] for [", targetType, "] (from TargetTypes annotation)");
getFormatterFactory().add(targetType, (Class extends Formatter>>) formatter);
}
}
}
List> typeConverters = getBootstrapPropertyResolver().getClassPropertyList(TypeConverter.class);
for (Class extends TypeConverter> typeConverter : typeConverters) {
Type[] typeArguments = ReflectUtil.getActualTypeArguments(typeConverter, TypeConverter.class);
log.trace("Found TypeConverter [", typeConverter, "] - type parameters: ", typeArguments);
if ((typeArguments != null) && (typeArguments.length == 1)
&& !typeArguments[0].equals(Object.class)) {
if (typeArguments[0] instanceof Class) {
log.debug("Adding auto-discovered TypeConverter [", typeConverter, "] for [", typeArguments[0], "] (from type parameter)");
getTypeConverterFactory().add((Class>) typeArguments[0], (Class extends TypeConverter>>) typeConverter);
}
else {
log.warn("Type parameter for non-abstract TypeConverter [", typeConverter, "] is not a class.");
}
}
TargetTypes targetTypes = typeConverter.getAnnotation(TargetTypes.class);
if (targetTypes != null) {
for (Class> targetType : targetTypes.value()) {
log.debug("Adding auto-discovered TypeConverter [", typeConverter, "] for [", targetType, "] (from TargetTypes annotation)");
getTypeConverterFactory().add(targetType, (Class extends TypeConverter>>) typeConverter);
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy