M1 cut of environment, profiles and property work (SPR-7508)

Decomposed Environment interface into PropertySources, PropertyResolver
objects

    Environment interface and implementations are still present, but
    simpler.

    PropertySources container aggregates PropertySource objects;
    PropertyResolver provides search, conversion, placeholder
    replacement. Single implementation for now is
    PropertySourcesPlaceholderResolver

Renamed EnvironmentAwarePropertyPlaceholderConfigurer to
PropertySourcesPlaceholderConfigurer

    <context:property-placeholder/> now registers PSPC by default, else
    PPC if systemPropertiesMode* settings are involved

Refined configuration and behavior of default profiles

    See Environment interface Javadoc for details

Added Portlet implementations of relevant interfaces:

    * DefaultPortletEnvironment
    * PortletConfigPropertySource, PortletContextPropertySource
    * Integrated each appropriately throughout Portlet app contexts

Added protected 'createEnvironment()' method to AbstractApplicationContext

    Subclasses can override at will to supply a custom Environment
    implementation.  In practice throughout the framework, this is how
    Web- and Portlet-related ApplicationContexts override use of the
    DefaultEnvironment and swap in DefaultWebEnvironment or
    DefaultPortletEnvironment as appropriate.

Introduced "stub-and-replace" behavior for Servlet- and Portlet-based
PropertySource implementations

    Allows for early registration and ordering of the stub, then
    replacement with actual backing object at refresh() time.

    Added AbstractApplicationContext.initPropertySources() method to
    support stub-and-replace behavior. Called from within existing
    prepareRefresh() method so as to avoid impact with
    ApplicationContext implementations that copy and modify AAC's
    refresh() method (e.g.: Spring DM).

    Added methods to WebApplicationContextUtils and
    PortletApplicationContextUtils to support stub-and-replace behavior

Added comprehensive Javadoc for all new or modified types and members

Added XSD documentation for all new or modified elements and attributes

    Including nested <beans>, <beans profile="..."/>, and changes for
    certain attributes type from xsd:IDREF to xsd:string

Improved fix for detecting non-file based Resources in
PropertiesLoaderSupport (SPR-7547, SPR-7552)

    Technically unrelated to environment work, but grouped in with
    this changeset for convenience.

Deprecated (removed) context:property-placeholder
'system-properties-mode' attribute from spring-context-3.1.xsd

    Functionality is preserved for those using schemas up to and including
    spring-context-3.0.  For 3.1, system-properties-mode is no longer
    supported as it conflicts with the idea of managing a set of property
    sources within the context's Environment object. See Javadoc in
    PropertyPlaceholderConfigurer, AbstractPropertyPlaceholderConfigurer
    and PropertySourcesPlaceholderConfigurer for details.

Introduced CollectionUtils.toArray(Enumeration<E>, A[])

Work items remaining for 3.1 M2:

    Consider repackaging PropertySource* types; eliminate internal use
    of SystemPropertyUtils and deprecate

    Further work on composition of Environment interface; consider
    repurposing existing PlaceholderResolver interface to obviate need
    for resolve[Required]Placeholder() methods currently in Environment.

    Ensure configurability of placeholder prefix, suffix, and value
    separator when working against an AbstractPropertyResolver

    Add JNDI-based Environment / PropertySource implementatinos

    Consider support for @Profile at the @Bean level

    Provide consistent logging for the entire property resolution
    lifecycle; consider issuing all such messages against a dedicated
    logger with a single category.

    Add reference documentation to cover the featureset.
This commit is contained in:
Chris Beams
2011-01-03 09:04:34 +00:00
parent b130a36af7
commit b3ff9be78f
111 changed files with 3439 additions and 1715 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,12 +33,13 @@ import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.PropertyValues;
import org.springframework.core.env.DefaultWebEnvironment;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceEditor;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.StringUtils;
import org.springframework.web.portlet.context.DefaultPortletEnvironment;
import org.springframework.web.portlet.context.PortletContextResourceLoader;
/**
@@ -64,7 +65,7 @@ import org.springframework.web.portlet.context.PortletContextResourceLoader;
* @see #processAction
* @see FrameworkPortlet
*/
public abstract class GenericPortletBean extends GenericPortlet {
public abstract class GenericPortletBean extends GenericPortlet implements EnvironmentAware {
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
@@ -75,10 +76,7 @@ public abstract class GenericPortletBean extends GenericPortlet {
*/
private final Set<String> requiredProperties = new HashSet<String>();
/**
* TODO SPR-7508: think about making this overridable {@link EnvironmentAware}?
*/
private Environment environment = new DefaultWebEnvironment();
private Environment environment = new DefaultPortletEnvironment();
/**
@@ -167,6 +165,15 @@ public abstract class GenericPortletBean extends GenericPortlet {
protected void initPortletBean() throws PortletException {
}
/**
* {@inheritDoc}
* <p>Any environment set here overrides the {@link DefaultPortletEnvironment}
* provided by default.
*/
public void setEnvironment(Environment environment) {
this.environment = environment;
}
/**
* PropertyValues implementation created from PortletConfig init parameters.

View File

@@ -24,6 +24,7 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractRefreshableConfigApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.web.context.ServletContextAware;
@@ -150,6 +151,14 @@ public abstract class AbstractRefreshablePortletApplicationContext extends Abstr
beanFactory, this.servletContext, this.portletContext, this.portletConfig);
}
/**
* Create and return a new {@link DefaultPortletEnvironment}.
*/
@Override
protected ConfigurableEnvironment createEnvironment() {
return new DefaultPortletEnvironment();
}
/**
* This implementation supports file paths beneath the root of the PortletContext.
* @see PortletContextResource

View File

@@ -0,0 +1,79 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* 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 org.springframework.web.portlet.context;
import javax.portlet.PortletConfig;
import javax.portlet.PortletContext;
import javax.servlet.ServletContext;
import org.springframework.core.env.DefaultEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.PropertySource.StubPropertySource;
import org.springframework.web.context.support.DefaultWebEnvironment;
/**
* {@link Environment} implementation to be used by {@code Servlet}-based web
* applications. All Portlet-related {@code ApplicationContext} classes initialize an instance
* by default.
*
* <p>Contributes {@code ServletContext}-, {@code PortletContext}-, and {@code PortletConfig}-based
* {@link PropertySource} instances. See the {@link #DefaultPortletEnvironment()} constructor
* for details.
*
* @author Chris Beams
* @since 3.1
* @see DefaultEnvironment
* @see DefaultWebEnvironment
*/
public class DefaultPortletEnvironment extends DefaultEnvironment {
/** Portlet context init parameters property source name: {@value} */
public static final String PORTLET_CONTEXT_PROPERTY_SOURCE_NAME = "portletContextInitParams";
/** Portlet config init parameters property source name: {@value} */
public static final String PORTLET_CONFIG_PROPERTY_SOURCE_NAME = "portletConfigInitParams";
/**
* Create a new {@code Environment} populated with the property sources contributed by
* superclasses as well as:
* <ul>
* <li>{@value #PORTLET_CONFIG_PROPERTY_SOURCE_NAME}
* <li>{@value #PORTLET_CONTEXT_PROPERTY_SOURCE_NAME}
* <li>{@linkplain DefaultWebEnvironment#SERVLET_CONTEXT_PROPERTY_SOURCE_NAME "servletContextInitParams"}
* </ul>
* <p>Properties present in {@value #PORTLET_CONFIG_PROPERTY_SOURCE_NAME} will
* take precedence over those in {@value #PORTLET_CONTEXT_PROPERTY_SOURCE_NAME},
* which takes precedence over those in .
* Properties in either will take precedence over system properties and environment
* variables.
* <p>The property sources are added as stubs for now, and will be
* {@linkplain PortletApplicationContextUtils#initPortletPropertySources fully initialized}
* once the actual {@link PortletConfig}, {@link PortletContext}, and {@link ServletContext}
* objects are available.
* @see DefaultEnvironment#DefaultEnvironment
* @see PortletConfigPropertySource
* @see PortletContextPropertySource
* @see AbstractRefreshablePortletApplicationContext#initPropertySources
* @see PortletApplicationContextUtils#initPortletPropertySources
*/
public DefaultPortletEnvironment() {
this.getPropertySources().addFirst(new StubPropertySource(DefaultWebEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
this.getPropertySources().addFirst(new StubPropertySource(PORTLET_CONTEXT_PROPERTY_SOURCE_NAME));
this.getPropertySources().addFirst(new StubPropertySource(PORTLET_CONFIG_PROPERTY_SOURCE_NAME));
}
}

View File

@@ -21,6 +21,7 @@ import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.portlet.PortletConfig;
import javax.portlet.PortletContext;
import javax.portlet.PortletRequest;
@@ -30,6 +31,7 @@ import javax.servlet.ServletContext;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.util.Assert;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestAttributes;
@@ -37,6 +39,7 @@ import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.RequestScope;
import org.springframework.web.context.request.SessionScope;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.context.support.WebApplicationContextUtils;
/**
* Convenience methods for retrieving the root WebApplicationContext for a given
@@ -184,6 +187,29 @@ public abstract class PortletApplicationContextUtils {
}
}
/**
* Replace {@code Servlet}- and {@code Portlet}-based stub property sources
* with actual instances populated with the given context and config objects.
* @see org.springframework.core.env.PropertySource.StubPropertySource
* @see org.springframework.core.env.ConfigurableEnvironment#getPropertySources()
* @see org.springframework.web.context.support.WebApplicationContextUtils#initServletPropertySources(MutablePropertySources, ServletContext)
*/
public static void initPortletPropertySources(MutablePropertySources propertySources, ServletContext servletContext,
PortletContext portletContext, PortletConfig portletConfig) {
Assert.notNull(propertySources, "propertySources must not be null");
WebApplicationContextUtils.initServletPropertySources(propertySources, servletContext);
if(portletContext != null && propertySources.contains(DefaultPortletEnvironment.PORTLET_CONTEXT_PROPERTY_SOURCE_NAME)) {
propertySources.replace(DefaultPortletEnvironment.PORTLET_CONTEXT_PROPERTY_SOURCE_NAME,
new PortletContextPropertySource(DefaultPortletEnvironment.PORTLET_CONTEXT_PROPERTY_SOURCE_NAME, portletContext));
}
if(portletConfig != null && propertySources.contains(DefaultPortletEnvironment.PORTLET_CONFIG_PROPERTY_SOURCE_NAME)) {
propertySources.replace(DefaultPortletEnvironment.PORTLET_CONFIG_PROPERTY_SOURCE_NAME,
new PortletConfigPropertySource(DefaultPortletEnvironment.PORTLET_CONFIG_PROPERTY_SOURCE_NAME, portletConfig));
}
}
/**
* Return the current RequestAttributes instance as PortletRequestAttributes.
* @see RequestContextHolder#currentRequestAttributes()

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* 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 org.springframework.web.portlet.context;
import javax.portlet.PortletConfig;
import org.springframework.core.env.PropertySource;
import org.springframework.util.CollectionUtils;
/**
* {@link PropertySource} that reads init parameters from a {@link PortletConfig} object.
*
* @author Chris Beams
* @since 3.1
* @see PortletContextPropertySource
*/
public class PortletConfigPropertySource extends PropertySource<PortletConfig> {
public PortletConfigPropertySource(String name, PortletConfig portletConfig) {
super(name, portletConfig);
}
@Override
public String[] getPropertyNames() {
return CollectionUtils.toArray(this.source.getInitParameterNames(), EMPTY_NAMES_ARRAY);
}
@Override
public String getProperty(String name) {
return this.source.getInitParameter(name);
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* 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 org.springframework.web.portlet.context;
import javax.portlet.PortletContext;
import org.springframework.core.env.PropertySource;
import org.springframework.util.CollectionUtils;
/**
* {@link PropertySource} that reads init parameters from a {@link PortletContext} object.
*
* @author Chris Beams
* @since 3.1
* @see PortletConfigPropertySource
*/
public class PortletContextPropertySource extends PropertySource<PortletContext> {
public PortletContextPropertySource(String name, PortletContext portletContext) {
super(name, portletContext);
}
@Override
public String[] getPropertyNames() {
return CollectionUtils.toArray(this.source.getInitParameterNames(), EMPTY_NAMES_ARRAY);
}
@Override
public String getProperty(String name) {
return this.source.getInitParameter(name);
}
}

View File

@@ -23,7 +23,7 @@ import javax.servlet.ServletContext;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.core.env.DefaultWebEnvironment;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.web.context.WebApplicationContext;
@@ -61,10 +61,29 @@ public class StaticPortletApplicationContext extends StaticApplicationContext
public StaticPortletApplicationContext() {
setDisplayName("Root Portlet ApplicationContext");
setEnvironment(new DefaultWebEnvironment()); // TODO SPR-7508: create custom portlet env?
}
/**
* Return a new {@link DefaultPortletEnvironment}
*/
@Override
protected ConfigurableEnvironment createEnvironment() {
return new DefaultPortletEnvironment();
}
/**
* {@inheritDoc}
* <p>Replace {@code Portlet}- and {@code Servlet}-related property sources.
*/
@Override
protected void initPropertySources() {
super.initPropertySources();
PortletApplicationContextUtils.initPortletPropertySources(
this.getEnvironment().getPropertySources(), this.servletContext,
this.portletContext, this.portletConfig);
}
@Override
public void setParent(ApplicationContext parent) {
super.setParent(parent);