001/*
002 * Copyright 2002-2018 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.core.env;
018
019import java.util.Map;
020
021/**
022 * Configuration interface to be implemented by most if not all {@link Environment} types.
023 * Provides facilities for setting active and default profiles and manipulating underlying
024 * property sources. Allows clients to set and validate required properties, customize the
025 * conversion service and more through the {@link ConfigurablePropertyResolver}
026 * superinterface.
027 *
028 * <h2>Manipulating property sources</h2>
029 * <p>Property sources may be removed, reordered, or replaced; and additional
030 * property sources may be added using the {@link MutablePropertySources}
031 * instance returned from {@link #getPropertySources()}. The following examples
032 * are against the {@link StandardEnvironment} implementation of
033 * {@code ConfigurableEnvironment}, but are generally applicable to any implementation,
034 * though particular default property sources may differ.
035 *
036 * <h4>Example: adding a new property source with highest search priority</h4>
037 * <pre class="code">
038 * ConfigurableEnvironment environment = new StandardEnvironment();
039 * MutablePropertySources propertySources = environment.getPropertySources();
040 * Map&lt;String, String&gt; myMap = new HashMap&lt;&gt;();
041 * myMap.put("xyz", "myValue");
042 * propertySources.addFirst(new MapPropertySource("MY_MAP", myMap));
043 * </pre>
044 *
045 * <h4>Example: removing the default system properties property source</h4>
046 * <pre class="code">
047 * MutablePropertySources propertySources = environment.getPropertySources();
048 * propertySources.remove(StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME)
049 * </pre>
050 *
051 * <h4>Example: mocking the system environment for testing purposes</h4>
052 * <pre class="code">
053 * MutablePropertySources propertySources = environment.getPropertySources();
054 * MockPropertySource mockEnvVars = new MockPropertySource().withProperty("xyz", "myValue");
055 * propertySources.replace(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, mockEnvVars);
056 * </pre>
057 *
058 * When an {@link Environment} is being used by an {@code ApplicationContext}, it is
059 * important that any such {@code PropertySource} manipulations be performed
060 * <em>before</em> the context's {@link
061 * org.springframework.context.support.AbstractApplicationContext#refresh() refresh()}
062 * method is called. This ensures that all property sources are available during the
063 * container bootstrap process, including use by {@linkplain
064 * org.springframework.context.support.PropertySourcesPlaceholderConfigurer property
065 * placeholder configurers}.
066 *
067 * @author Chris Beams
068 * @since 3.1
069 * @see StandardEnvironment
070 * @see org.springframework.context.ConfigurableApplicationContext#getEnvironment
071 */
072public interface ConfigurableEnvironment extends Environment, ConfigurablePropertyResolver {
073
074        /**
075         * Specify the set of profiles active for this {@code Environment}. Profiles are
076         * evaluated during container bootstrap to determine whether bean definitions
077         * should be registered with the container.
078         * <p>Any existing active profiles will be replaced with the given arguments; call
079         * with zero arguments to clear the current set of active profiles. Use
080         * {@link #addActiveProfile} to add a profile while preserving the existing set.
081         * @throws IllegalArgumentException if any profile is null, empty or whitespace-only
082         * @see #addActiveProfile
083         * @see #setDefaultProfiles
084         * @see org.springframework.context.annotation.Profile
085         * @see AbstractEnvironment#ACTIVE_PROFILES_PROPERTY_NAME
086         */
087        void setActiveProfiles(String... profiles);
088
089        /**
090         * Add a profile to the current set of active profiles.
091         * @throws IllegalArgumentException if the profile is null, empty or whitespace-only
092         * @see #setActiveProfiles
093         */
094        void addActiveProfile(String profile);
095
096        /**
097         * Specify the set of profiles to be made active by default if no other profiles
098         * are explicitly made active through {@link #setActiveProfiles}.
099         * @throws IllegalArgumentException if any profile is null, empty or whitespace-only
100         * @see AbstractEnvironment#DEFAULT_PROFILES_PROPERTY_NAME
101         */
102        void setDefaultProfiles(String... profiles);
103
104        /**
105         * Return the {@link PropertySources} for this {@code Environment} in mutable form,
106         * allowing for manipulation of the set of {@link PropertySource} objects that should
107         * be searched when resolving properties against this {@code Environment} object.
108         * The various {@link MutablePropertySources} methods such as
109         * {@link MutablePropertySources#addFirst addFirst},
110         * {@link MutablePropertySources#addLast addLast},
111         * {@link MutablePropertySources#addBefore addBefore} and
112         * {@link MutablePropertySources#addAfter addAfter} allow for fine-grained control
113         * over property source ordering. This is useful, for example, in ensuring that
114         * certain user-defined property sources have search precedence over default property
115         * sources such as the set of system properties or the set of system environment
116         * variables.
117         * @see AbstractEnvironment#customizePropertySources
118         */
119        MutablePropertySources getPropertySources();
120
121        /**
122         * Return the value of {@link System#getProperties()} if allowed by the current
123         * {@link SecurityManager}, otherwise return a map implementation that will attempt
124         * to access individual keys using calls to {@link System#getProperty(String)}.
125         * <p>Note that most {@code Environment} implementations will include this system
126         * properties map as a default {@link PropertySource} to be searched. Therefore, it is
127         * recommended that this method not be used directly unless bypassing other property
128         * sources is expressly intended.
129         * <p>Calls to {@link Map#get(Object)} on the Map returned will never throw
130         * {@link IllegalAccessException}; in cases where the SecurityManager forbids access
131         * to a property, {@code null} will be returned and an INFO-level log message will be
132         * issued noting the exception.
133         */
134        Map<String, Object> getSystemProperties();
135
136        /**
137         * Return the value of {@link System#getenv()} if allowed by the current
138         * {@link SecurityManager}, otherwise return a map implementation that will attempt
139         * to access individual keys using calls to {@link System#getenv(String)}.
140         * <p>Note that most {@link Environment} implementations will include this system
141         * environment map as a default {@link PropertySource} to be searched. Therefore, it
142         * is recommended that this method not be used directly unless bypassing other
143         * property sources is expressly intended.
144         * <p>Calls to {@link Map#get(Object)} on the Map returned will never throw
145         * {@link IllegalAccessException}; in cases where the SecurityManager forbids access
146         * to a property, {@code null} will be returned and an INFO-level log message will be
147         * issued noting the exception.
148         */
149        Map<String, Object> getSystemEnvironment();
150
151        /**
152         * Append the given parent environment's active profiles, default profiles and
153         * property sources to this (child) environment's respective collections of each.
154         * <p>For any identically-named {@code PropertySource} instance existing in both
155         * parent and child, the child instance is to be preserved and the parent instance
156         * discarded. This has the effect of allowing overriding of property sources by the
157         * child as well as avoiding redundant searches through common property source types,
158         * e.g. system environment and system properties.
159         * <p>Active and default profile names are also filtered for duplicates, to avoid
160         * confusion and redundant storage.
161         * <p>The parent environment remains unmodified in any case. Note that any changes to
162         * the parent environment occurring after the call to {@code merge} will not be
163         * reflected in the child. Therefore, care should be taken to configure parent
164         * property sources and profile information prior to calling {@code merge}.
165         * @param parent the environment to merge with
166         * @since 3.1.2
167         * @see org.springframework.context.support.AbstractApplicationContext#setParent
168         */
169        void merge(ConfigurableEnvironment parent);
170
171}