001/*
002 * Copyright 2002-2016 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;
018
019import java.io.IOException;
020import java.io.InputStream;
021import java.net.URL;
022import java.util.Properties;
023
024import org.apache.commons.logging.Log;
025import org.apache.commons.logging.LogFactory;
026
027/**
028 * Static holder for local Spring properties, i.e. defined at the Spring library level.
029 *
030 * <p>Reads a {@code spring.properties} file from the root of the Spring library classpath,
031 * and also allows for programmatically setting properties through {@link #setProperty}.
032 * When checking a property, local entries are being checked first, then falling back
033 * to JVM-level system properties through a {@link System#getProperty} check.
034 *
035 * <p>This is an alternative way to set Spring-related system properties such as
036 * "spring.getenv.ignore" and "spring.beaninfo.ignore", in particular for scenarios
037 * where JVM system properties are locked on the target platform (e.g. WebSphere).
038 * See {@link #setFlag} for a convenient way to locally set such flags to "true".
039 *
040 * @author Juergen Hoeller
041 * @since 3.2.7
042 * @see org.springframework.core.env.AbstractEnvironment#IGNORE_GETENV_PROPERTY_NAME
043 * @see org.springframework.beans.CachedIntrospectionResults#IGNORE_BEANINFO_PROPERTY_NAME
044 * @see org.springframework.jdbc.core.StatementCreatorUtils#IGNORE_GETPARAMETERTYPE_PROPERTY_NAME
045 * @see org.springframework.test.context.cache.ContextCache#MAX_CONTEXT_CACHE_SIZE_PROPERTY_NAME
046 */
047public abstract class SpringProperties {
048
049        private static final String PROPERTIES_RESOURCE_LOCATION = "spring.properties";
050
051        private static final Log logger = LogFactory.getLog(SpringProperties.class);
052
053        private static final Properties localProperties = new Properties();
054
055
056        static {
057                try {
058                        ClassLoader cl = SpringProperties.class.getClassLoader();
059                        URL url = (cl != null ? cl.getResource(PROPERTIES_RESOURCE_LOCATION) :
060                                        ClassLoader.getSystemResource(PROPERTIES_RESOURCE_LOCATION));
061                        if (url != null) {
062                                logger.info("Found 'spring.properties' file in local classpath");
063                                InputStream is = url.openStream();
064                                try {
065                                        localProperties.load(is);
066                                }
067                                finally {
068                                        is.close();
069                                }
070                        }
071                }
072                catch (IOException ex) {
073                        if (logger.isInfoEnabled()) {
074                                logger.info("Could not load 'spring.properties' file from local classpath: " + ex);
075                        }
076                }
077        }
078
079
080        /**
081         * Programmatically set a local property, overriding an entry in the
082         * {@code spring.properties} file (if any).
083         * @param key the property key
084         * @param value the associated property value, or {@code null} to reset it
085         */
086        public static void setProperty(String key, String value) {
087                if (value != null) {
088                        localProperties.setProperty(key, value);
089                }
090                else {
091                        localProperties.remove(key);
092                }
093        }
094
095        /**
096         * Retrieve the property value for the given key, checking local Spring
097         * properties first and falling back to JVM-level system properties.
098         * @param key the property key
099         * @return the associated property value, or {@code null} if none found
100         */
101        public static String getProperty(String key) {
102                String value = localProperties.getProperty(key);
103                if (value == null) {
104                        try {
105                                value = System.getProperty(key);
106                        }
107                        catch (Throwable ex) {
108                                if (logger.isDebugEnabled()) {
109                                        logger.debug("Could not retrieve system property '" + key + "': " + ex);
110                                }
111                        }
112                }
113                return value;
114        }
115
116        /**
117         * Programmatically set a local flag to "true", overriding an
118         * entry in the {@code spring.properties} file (if any).
119         * @param key the property key
120         */
121        public static void setFlag(String key) {
122                localProperties.put(key, Boolean.TRUE.toString());
123        }
124
125        /**
126         * Retrieve the flag for the given property key.
127         * @param key the property key
128         * @return {@code true} if the property is set to "true",
129         * {@code} false otherwise
130         */
131        public static boolean getFlag(String key) {
132                return Boolean.parseBoolean(getProperty(key));
133        }
134
135}