From 15ac99f59cde189dee0e4a552a8005a1dbf6592d Mon Sep 17 00:00:00 2001 From: Chris Beams Date: Thu, 6 Jan 2011 07:43:29 +0000 Subject: [PATCH] Introduce and integrate JndiPropertySource DefaultWebEnvironment automatically adds a JndiPropertySource if a "jndiPropertySourceEnabled" property is detected in any of the other other default property sources. --- .../jndi/JndiPropertySource.java | 108 ++++++++++++++++++ .../support/DefaultWebEnvironment.java | 20 ++++ .../support/DefaultWebEnvironmentTests.java | 33 ++++++ org.springframework.web/template.mf | 1 + 4 files changed, 162 insertions(+) create mode 100644 org.springframework.context/src/main/java/org/springframework/jndi/JndiPropertySource.java diff --git a/org.springframework.context/src/main/java/org/springframework/jndi/JndiPropertySource.java b/org.springframework.context/src/main/java/org/springframework/jndi/JndiPropertySource.java new file mode 100644 index 00000000000..b2f608e9d64 --- /dev/null +++ b/org.springframework.context/src/main/java/org/springframework/jndi/JndiPropertySource.java @@ -0,0 +1,108 @@ +/* + * 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.jndi; + +import java.util.Properties; + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; + +import org.springframework.core.env.PropertySource; + +/** + * {@link PropertySource} implementation that reads properties from + * a JNDI {@link Context}. + * + * @author Chris Beams + * @author Juergen Hoeller + * @since 3.1 + * @see Context#lookup(String) + * @see org.springframework.web.context.support.DefaultWebEnvironment + */ +public class JndiPropertySource extends PropertySource { + + /** JNDI context property source name: {@value} */ + public static final String JNDI_PROPERTY_SOURCE_NAME = "jndiPropertySource"; + + /** + * Name of property used to determine if a {@link JndiPropertySource} + * should be registered by default: {@value} + */ + public static final String JNDI_PROPERTY_SOURCE_ENABLED_FLAG = "jndiPropertySourceEnabled"; + + /** + * Create a new {@code JndiPropertySource} with the default name + * {@value #JNDI_PROPERTY_SOURCE_NAME} and create a new {@link InitialContext} + * as the source object. + * @throws JndiLookupFailureException if a new {@link InitialContext} + * cannot be created. + */ + public JndiPropertySource() throws JndiLookupFailureException { + this(JNDI_PROPERTY_SOURCE_NAME, createInitialContext(null)); + } + + /** + * Create a new {@code JndiPropertySource} with the given name and + * create a new {@link InitialContext} as the source object. + * @throws JndiLookupFailureException if a new {@link InitialContext} + * cannot be created. + */ + public JndiPropertySource(String name) throws JndiLookupFailureException { + this(name, createInitialContext(null)); + } + + /** + * Create a new {@code JndiPropertySource} with the given name and + * use the given jndiEnvironment properties to create a new + * {@link InitialContext} as the source object. + * @throws JndiLookupFailureException if a new {@link InitialContext} + * cannot be created. + */ + public JndiPropertySource(String name, Properties jndiEnvironment) throws JndiLookupFailureException { + this(name, createInitialContext(jndiEnvironment)); + } + + /** + * Create a new {@code JndiPropertySource} with the given name and + * JNDI {@link Context}. + */ + public JndiPropertySource(String name, Context source) { + super(name, source); + } + + /** + * Look up and return the given name from the source JNDI {@link Context}. + */ + @Override + public Object getProperty(String name) throws JndiLookupFailureException { + try { + return this.source.lookup(name); + } catch (NamingException ex) { + throw new JndiLookupFailureException("unable to look up name" + name, ex); + } + } + + private static Context createInitialContext(Properties jndiEnvironment) { + try { + return new InitialContext(jndiEnvironment); + } catch (NamingException ex) { + throw new JndiLookupFailureException("unable to create InitialContext", ex); + } + } + +} diff --git a/org.springframework.web/src/main/java/org/springframework/web/context/support/DefaultWebEnvironment.java b/org.springframework.web/src/main/java/org/springframework/web/context/support/DefaultWebEnvironment.java index 4e942bb05d0..48835b6adcf 100644 --- a/org.springframework.web/src/main/java/org/springframework/web/context/support/DefaultWebEnvironment.java +++ b/org.springframework.web/src/main/java/org/springframework/web/context/support/DefaultWebEnvironment.java @@ -20,8 +20,11 @@ import javax.servlet.ServletConfig; 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.core.env.PropertySources; +import org.springframework.jndi.JndiPropertySource; /** * {@link Environment} implementation to be used by {@code Servlet}-based web @@ -31,6 +34,11 @@ import org.springframework.core.env.PropertySource.StubPropertySource; *

Contributes {@code ServletConfig}- and {@code ServletContext}-based {@link PropertySource} * instances. See the {@link #DefaultWebEnvironment()} constructor for details. * + *

After initial bootstrapping, property sources will be searched for the presence of a + * "jndiPropertySourceEnabled" property; if found, a {@link JndiPropertySource} will be added + * to this environment's {@link PropertySources}, with precedence higher than system properties + * and environment variables, but lower than that of ServletContext and ServletConfig init params. + * * @author Chris Beams * @since 3.1 * @see DefaultEnvironment @@ -50,6 +58,7 @@ public class DefaultWebEnvironment extends DefaultEnvironment { *

*

Properties present in {@value #SERVLET_CONFIG_PROPERTY_SOURCE_NAME} will * take precedence over those in {@value #SERVLET_CONTEXT_PROPERTY_SOURCE_NAME}. @@ -58,14 +67,25 @@ public class DefaultWebEnvironment extends DefaultEnvironment { *

The {@code Servlet}-related property sources are added as stubs for now, and will be * {@linkplain WebApplicationContextUtils#initServletPropertySources fully initialized} * once the actual {@link ServletConfig} and {@link ServletContext} objects are available. + * + *

If the {@link JndiPropertySource#JNDI_PROPERTY_SOURCE_ENABLED_FLAG "jndiPropertySourceEnabled"} + * property is present in any of the default property sources, a {@link JndiPropertySource} will + * be added as well, with precedence lower than servlet property sources, but higher than system + * properties and environment variables. * @see DefaultEnvironment#DefaultEnvironment * @see ServletConfigPropertySource * @see ServletContextPropertySource + * @see org.springframework.jndi.JndiPropertySource * @see org.springframework.context.support.AbstractApplicationContext#initPropertySources * @see WebApplicationContextUtils#initServletPropertySources */ public DefaultWebEnvironment() { this.getPropertySources().addFirst(new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME)); this.getPropertySources().addFirst(new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME)); + + Boolean jndiPropertySourceEnabled = this.getProperty(JndiPropertySource.JNDI_PROPERTY_SOURCE_ENABLED_FLAG, boolean.class); + if (jndiPropertySourceEnabled != null && jndiPropertySourceEnabled != false) { + this.getPropertySources().addAfter(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME, new JndiPropertySource()); + } } } diff --git a/org.springframework.web/src/test/java/org/springframework/web/context/support/DefaultWebEnvironmentTests.java b/org.springframework.web/src/test/java/org/springframework/web/context/support/DefaultWebEnvironmentTests.java index 50732a0b5fe..e7e1950a30f 100644 --- a/org.springframework.web/src/test/java/org/springframework/web/context/support/DefaultWebEnvironmentTests.java +++ b/org.springframework.web/src/test/java/org/springframework/web/context/support/DefaultWebEnvironmentTests.java @@ -25,6 +25,7 @@ import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.DefaultEnvironment; import org.springframework.core.env.MutablePropertySources; import org.springframework.core.env.PropertySource; +import org.springframework.jndi.JndiPropertySource; public class DefaultWebEnvironmentTests { @@ -38,4 +39,36 @@ public class DefaultWebEnvironmentTests { assertThat(sources.precedenceOf(PropertySource.named(DefaultEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME)), equalTo(3)); assertThat(sources.size(), is(4)); } + + @Test + public void propertySourceOrder_jndiPropertySourceEnabled() { + System.setProperty(JndiPropertySource.JNDI_PROPERTY_SOURCE_ENABLED_FLAG, "true"); + ConfigurableEnvironment env = new DefaultWebEnvironment(); + MutablePropertySources sources = env.getPropertySources(); + + assertThat(sources.precedenceOf(PropertySource.named(DefaultWebEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME)), equalTo(0)); + assertThat(sources.precedenceOf(PropertySource.named(DefaultWebEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME)), equalTo(1)); + assertThat(sources.precedenceOf(PropertySource.named(JndiPropertySource.JNDI_PROPERTY_SOURCE_NAME)), equalTo(2)); + assertThat(sources.precedenceOf(PropertySource.named(DefaultEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME)), equalTo(3)); + assertThat(sources.precedenceOf(PropertySource.named(DefaultEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME)), equalTo(4)); + assertThat(sources.size(), is(5)); + + System.clearProperty(JndiPropertySource.JNDI_PROPERTY_SOURCE_ENABLED_FLAG); + } + + @Test + public void propertySourceOrder_jndiPropertySourceEnabledIsFalse() { + System.setProperty(JndiPropertySource.JNDI_PROPERTY_SOURCE_ENABLED_FLAG, "false"); + ConfigurableEnvironment env = new DefaultWebEnvironment(); + MutablePropertySources sources = env.getPropertySources(); + + assertThat(sources.precedenceOf(PropertySource.named(DefaultWebEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME)), equalTo(0)); + assertThat(sources.precedenceOf(PropertySource.named(DefaultWebEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME)), equalTo(1)); + //assertThat(sources.precedenceOf(PropertySource.named(JndiPropertySource.JNDI_PROPERTY_SOURCE_NAME)), equalTo(2)); + assertThat(sources.precedenceOf(PropertySource.named(DefaultEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME)), equalTo(2)); + assertThat(sources.precedenceOf(PropertySource.named(DefaultEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME)), equalTo(3)); + assertThat(sources.size(), is(4)); + + System.clearProperty(JndiPropertySource.JNDI_PROPERTY_SOURCE_ENABLED_FLAG); + } } diff --git a/org.springframework.web/template.mf b/org.springframework.web/template.mf index c804a98d369..d6816d10346 100644 --- a/org.springframework.web/template.mf +++ b/org.springframework.web/template.mf @@ -26,6 +26,7 @@ Import-Template: org.springframework.beans.*;version=${spring.osgi.range}, org.springframework.context.*;version=${spring.osgi.range}, org.springframework.core.*;version=${spring.osgi.range}, + org.springframework.jndi.*;version=${spring.osgi.range};resolution:=optional, org.springframework.oxm.*;version=${spring.osgi.range};resolution:=optional, org.springframework.remoting.*;version=${spring.osgi.range};resolution:=optional, org.springframework.ui.*;version=${spring.osgi.range},