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