001    /*
002     * Cumulus4j - Securing your data in the cloud - http://cumulus4j.org
003     * Copyright (C) 2011 NightLabs Consulting GmbH
004     *
005     * This program is free software: you can redistribute it and/or modify
006     * it under the terms of the GNU Affero General Public License as
007     * published by the Free Software Foundation, either version 3 of the
008     * License, or (at your option) any later version.
009     *
010     * This program is distributed in the hope that it will be useful,
011     * but WITHOUT ANY WARRANTY; without even the implied warranty of
012     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013     * GNU Affero General Public License for more details.
014     *
015     * You should have received a copy of the GNU Affero General Public License
016     * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017     */
018    package org.cumulus4j.keymanager.back.shared;
019    
020    import java.util.Map;
021    import java.util.Properties;
022    
023    /**
024     * Helper class to work with system properties.
025     * 
026     * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de
027     */
028    public final class SystemPropertyUtil {
029    
030            private static final int MAX_REPLACE_ITERATIONS = 10000;
031    
032            private SystemPropertyUtil() {
033            }
034    
035            /**
036             * Resolve system properties like "&#36;{java.io.tmpdir}" in a
037             * <code>String</code>. Note, that this method works recursively, i.e. you
038             * can specify a system property "
039             * <code>aaa = someString/&#36;{bbb}/other</code>" and a system property "
040             * <code>bbb = xxx</code>" and the string "<code>yyy/&#36;{aaa}/zzz</code>
041             * " will be resolved to "<code>yyy/someString/xxx/other/zzz</code>".
042             * 
043             * @param raw
044             *            the raw <code>String</code>, e.g.
045             *            "&#36;{java.io.tmpdir}/mydirectory".
046             * @return the resolved <code>String</code>, e.g. "/tmp/mydirectory".
047             */
048            public static String resolveSystemProperties(String raw) {
049                    return resolveProperties(raw, System.getProperties());
050            }
051    
052            /**
053             * General core of <code>resolveSystemProperties</code> simplifying the
054             * creation of test functions.
055             * 
056             * @param raw
057             *            the raw <code>String</code>, e.g.
058             *            "&#36;{java.io.tmpdir}/mydirectory".
059             * @param properties
060             *            Properties to resolve
061             * @return the resolved <code>String</code>, e.g. "/tmp/mydirectory".
062             */
063            public static String resolveProperties(String raw, Properties properties) {
064                    String result = raw;
065    
066                    // Counter to prevent running forever if an invalid string was
067                    // specified.
068                    for (int i = 0; (result.indexOf('$') >= 0)
069                                    && (i < MAX_REPLACE_ITERATIONS); i++) {
070                            for (Map.Entry<?, ?> prop : properties.entrySet()) {
071                                    String target = "${" + String.valueOf(prop.getKey()) + "}";
072                                    result = result
073                                                    .replace(target, String.valueOf(prop.getValue()));
074                            }
075                    }
076    
077                    if (result.indexOf('$') >= 0) {
078                            throw new IllegalArgumentException(
079                                            "Property replacement failed for string " + raw);
080                    }
081    
082                    return result;
083            }
084    }