001/*
002 * Copyright 2002-2013 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 */
016package org.springframework.web.util;
017
018import javax.servlet.ServletContext;
019
020import org.springframework.util.PropertyPlaceholderHelper;
021import org.springframework.util.SystemPropertyUtils;
022
023/**
024 * Helper class for resolving placeholders in texts. Usually applied to file paths.
025 *
026 * <p>A text may contain {@code ${...}} placeholders, to be resolved as servlet context
027 * init parameters or system properties: e.g. {@code ${user.dir}}. Default values can
028 * be supplied using the ":" separator between key and value.
029 *
030 * @author Juergen Hoeller
031 * @author Marten Deinum
032 * @since 3.2.2
033 * @see SystemPropertyUtils
034 * @see ServletContext#getInitParameter(String)
035 */
036public abstract class ServletContextPropertyUtils {
037
038    private static final PropertyPlaceholderHelper strictHelper =
039            new PropertyPlaceholderHelper(SystemPropertyUtils.PLACEHOLDER_PREFIX,
040                                        SystemPropertyUtils.PLACEHOLDER_SUFFIX, SystemPropertyUtils.VALUE_SEPARATOR, false);
041
042    private static final PropertyPlaceholderHelper nonStrictHelper =
043            new PropertyPlaceholderHelper(SystemPropertyUtils.PLACEHOLDER_PREFIX,
044                                        SystemPropertyUtils.PLACEHOLDER_SUFFIX, SystemPropertyUtils.VALUE_SEPARATOR, true);
045
046
047        /**
048         * Resolve ${...} placeholders in the given text, replacing them with corresponding
049         * servlet context init parameter or system property values.
050     * @param text the String to resolve
051     * @param servletContext the servletContext to use for lookups.
052         * @return the resolved String
053         * @see SystemPropertyUtils#PLACEHOLDER_PREFIX
054         * @see SystemPropertyUtils#PLACEHOLDER_SUFFIX
055     * @see SystemPropertyUtils#resolvePlaceholders(String, boolean)
056         * @throws IllegalArgumentException if there is an unresolvable placeholder
057         */
058        public static String resolvePlaceholders(String text, ServletContext servletContext) {
059                return resolvePlaceholders(text, servletContext, false);
060        }
061
062        /**
063         * Resolve ${...} placeholders in the given text, replacing them with corresponding
064         * servlet context init parameter or system property values. Unresolvable placeholders
065         * with no default value are ignored and passed through unchanged if the flag is set to true.
066         * @param text the String to resolve
067     * @param servletContext the servletContext to use for lookups.
068         * @param ignoreUnresolvablePlaceholders flag to determine is unresolved placeholders are ignored
069         * @return the resolved String
070         * @see SystemPropertyUtils#PLACEHOLDER_PREFIX
071         * @see SystemPropertyUtils#PLACEHOLDER_SUFFIX
072     * @see SystemPropertyUtils#resolvePlaceholders(String, boolean)
073         * @throws IllegalArgumentException if there is an unresolvable placeholder and the flag is false
074         */
075        public static String resolvePlaceholders(String text, ServletContext servletContext, boolean ignoreUnresolvablePlaceholders) {
076                PropertyPlaceholderHelper helper = (ignoreUnresolvablePlaceholders ? nonStrictHelper : strictHelper);
077                return helper.replacePlaceholders(text, new ServletContextPlaceholderResolver(text, servletContext));
078        }
079
080
081        private static class ServletContextPlaceholderResolver implements PropertyPlaceholderHelper.PlaceholderResolver {
082
083        private final String text;
084
085        private final ServletContext servletContext;
086
087        public ServletContextPlaceholderResolver(String text, ServletContext servletContext) {
088            this.text = text;
089            this.servletContext = servletContext;
090        }
091
092        @Override
093                public String resolvePlaceholder(String placeholderName) {
094            try {
095                String propVal = this.servletContext.getInitParameter(placeholderName);
096                                if (propVal == null) {
097                                        // Fall back to system properties.
098                                        propVal = System.getProperty(placeholderName);
099                                        if (propVal == null) {
100                                                // Fall back to searching the system environment.
101                                                propVal = System.getenv(placeholderName);
102                                        }
103                                }
104                                return propVal;
105                        }
106            catch (Throwable ex) {
107                System.err.println("Could not resolve placeholder '" + placeholderName + "' in [" +
108                        this.text + "] as ServletContext init-parameter or system property: " + ex);
109                return null;
110            }
111        }
112    }
113
114}