001/*
002 * Copyright 2002-2019 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.beans.factory.config;
018
019import java.util.Properties;
020import java.util.prefs.BackingStoreException;
021import java.util.prefs.Preferences;
022
023import org.springframework.beans.factory.BeanDefinitionStoreException;
024import org.springframework.beans.factory.InitializingBean;
025import org.springframework.lang.Nullable;
026
027/**
028 * Subclass of PropertyPlaceholderConfigurer that supports JDK 1.4's
029 * Preferences API ({@code java.util.prefs}).
030 *
031 * <p>Tries to resolve placeholders as keys first in the user preferences,
032 * then in the system preferences, then in this configurer's properties.
033 * Thus, behaves like PropertyPlaceholderConfigurer if no corresponding
034 * preferences defined.
035 *
036 * <p>Supports custom paths for the system and user preferences trees. Also
037 * supports custom paths specified in placeholders ("myPath/myPlaceholderKey").
038 * Uses the respective root node if not specified.
039 *
040 * @author Juergen Hoeller
041 * @since 16.02.2004
042 * @see #setSystemTreePath
043 * @see #setUserTreePath
044 * @see java.util.prefs.Preferences
045 * @deprecated as of 5.2, along with {@link PropertyPlaceholderConfigurer}
046 */
047@Deprecated
048public class PreferencesPlaceholderConfigurer extends PropertyPlaceholderConfigurer implements InitializingBean {
049
050        @Nullable
051        private String systemTreePath;
052
053        @Nullable
054        private String userTreePath;
055
056        private Preferences systemPrefs = Preferences.systemRoot();
057
058        private Preferences userPrefs = Preferences.userRoot();
059
060
061        /**
062         * Set the path in the system preferences tree to use for resolving
063         * placeholders. Default is the root node.
064         */
065        public void setSystemTreePath(String systemTreePath) {
066                this.systemTreePath = systemTreePath;
067        }
068
069        /**
070         * Set the path in the system preferences tree to use for resolving
071         * placeholders. Default is the root node.
072         */
073        public void setUserTreePath(String userTreePath) {
074                this.userTreePath = userTreePath;
075        }
076
077
078        /**
079         * This implementation eagerly fetches the Preferences instances
080         * for the required system and user tree nodes.
081         */
082        @Override
083        public void afterPropertiesSet() {
084                if (this.systemTreePath != null) {
085                        this.systemPrefs = this.systemPrefs.node(this.systemTreePath);
086                }
087                if (this.userTreePath != null) {
088                        this.userPrefs = this.userPrefs.node(this.userTreePath);
089                }
090        }
091
092        /**
093         * This implementation tries to resolve placeholders as keys first
094         * in the user preferences, then in the system preferences, then in
095         * the passed-in properties.
096         */
097        @Override
098        protected String resolvePlaceholder(String placeholder, Properties props) {
099                String path = null;
100                String key = placeholder;
101                int endOfPath = placeholder.lastIndexOf('/');
102                if (endOfPath != -1) {
103                        path = placeholder.substring(0, endOfPath);
104                        key = placeholder.substring(endOfPath + 1);
105                }
106                String value = resolvePlaceholder(path, key, this.userPrefs);
107                if (value == null) {
108                        value = resolvePlaceholder(path, key, this.systemPrefs);
109                        if (value == null) {
110                                value = props.getProperty(placeholder);
111                        }
112                }
113                return value;
114        }
115
116        /**
117         * Resolve the given path and key against the given Preferences.
118         * @param path the preferences path (placeholder part before '/')
119         * @param key the preferences key (placeholder part after '/')
120         * @param preferences the Preferences to resolve against
121         * @return the value for the placeholder, or {@code null} if none found
122         */
123        @Nullable
124        protected String resolvePlaceholder(@Nullable String path, String key, Preferences preferences) {
125                if (path != null) {
126                        // Do not create the node if it does not exist...
127                        try {
128                                if (preferences.nodeExists(path)) {
129                                        return preferences.node(path).get(key, null);
130                                }
131                                else {
132                                        return null;
133                                }
134                        }
135                        catch (BackingStoreException ex) {
136                                throw new BeanDefinitionStoreException("Cannot access specified node path [" + path + "]", ex);
137                        }
138                }
139                else {
140                        return preferences.get(key, null);
141                }
142        }
143
144}