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