org.settings4j.connector.PreferencesConnector.java Source code

Java tutorial

Introduction

Here is the source code for org.settings4j.connector.PreferencesConnector.java

Source

/*
 * #%L
 * settings4j
 * ===============================================================
 * Copyright (C) 2008 - 2016 Brabenetz Harald, Austria
 * ===============================================================
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
package org.settings4j.connector;

import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;

import org.apache.commons.lang3.Validate;

/**
 * Connector which uses the {@link Preferences} feature of Java.
 * <p>
 * Locations:
 * </p>
 * <ul>
 * <li>In W98/Me/NT/W2K/XP/W2003/Vista/W7-32/W7-64 this information is stored in the fragile, hard-to-back-up registry in HKEY_LOCAL_MACHINE\JavaSoft\Prefs for
 * system Preferences and HKEY_CURRENT_USER\JavaSoft\Prefs for user Preferences in a very fluffy format. Every capital letter is preceded with a / and any
 * fields containing accented letters are encoded in Base64.</li>
 * <li>In Windows, user Preferences show up at HKEY_CURRENT_USER\Software\JavaSoft\Prefs\com\mindprod\replicator and HKEY_USERS\
 * usernamexxx\Software\JavaSoft\Prefs\com\mindprod\replicator where the package name is com.mindprod.replicator.</li>
 * <li>In Windows, system Preferences show up at HKEY_LOCAL_MACHINE\Software\JavaSoft\Prefs\com\mindprod\replicator, where the package name is
 * com.mindprod.replicator</li>
 * <li>In Linux, preferences are stored in ordinary xml files. System Preferences are stored in etc/.java.</li>
 * <li>In Linux, user preferences are stored in ~/.java. The file for user preferences may have a goofy base64-encoded name something like this:<br>
 * /home/username/.java/.userPrefs/ com/mindprod/replicator/_!':!bw "t!#4!b@"p!'4!~!"w!()!bw"k!#4!cg"l!(!!b!"p!'}@"0!'8!cg==</li>
 * </ul>
 *
 * @author Harald.Brabenetz
 */
public class PreferencesConnector extends AbstractPropertyConnector {

    private final Preferences systemPrefs;

    private final Preferences userPrefs;

    /**
     * Default Constructor initialize the User and System {@link Preferences}.
     */
    public PreferencesConnector() {
        this(Preferences.systemRoot(), Preferences.userRoot());
    }

    /**
     * @param systemPrefs
     *        {@link Preferences#systemRoot()}
     * @param userPrefs
     *        {@link Preferences#userRoot()}
     */
    protected PreferencesConnector(final Preferences systemPrefs, final Preferences userPrefs) {
        super();
        this.systemPrefs = systemPrefs;
        this.userPrefs = userPrefs;
    }

    @Override
    public String getString(final String keyPath) {
        Validate.notNull(keyPath);
        final String normalizedKey = normalizeKey(keyPath);
        final String path = getPath(normalizedKey);
        final String key = getKey(normalizedKey);
        String value = getPreferenceValue(path, key, this.userPrefs);
        if (value == null) {
            value = getPreferenceValue(path, key, this.systemPrefs);
        }
        return value;
    }

    private String getPath(final String keyPath) {
        String path = null;
        final int endOfPath = keyPath.lastIndexOf('/');
        if (endOfPath != -1) {
            path = keyPath.substring(0, endOfPath);
        }
        return path;
    }

    /**
     * Resolve the given path and key against the given Preferences.
     *
     * @param path the preferences path (placeholder part before '/')
     * @param key the preferences key (placeholder part after '/')
     * @param preferences the Preferences to resolve against
     * @return the value for the placeholder, or <code>null</code> if none found
     */
    protected String getPreferenceValue(final String path, final String key, final Preferences preferences) {
        if (path != null) {
            // Do not create the node if it does not exist...
            try {
                if (preferences.nodeExists(path)) {
                    return preferences.node(path).get(key, null);
                }
                return null;
            } catch (final BackingStoreException e) {
                throw new RuntimeException("Cannot access specified node path [" + path + "]", e);
            }
        }
        return preferences.get(key, null);
    }

    /**
     * Stores the given Value into the User-Preferences.
     *
     * @param keyPath - The full KeyPath
     * @param value - The new Value
     */
    public void setString(final String keyPath, final String value) {
        Validate.notNull(keyPath);
        final String normalizedKey = normalizeKey(keyPath);
        final String path = getPath(normalizedKey);
        final String key = getKey(normalizedKey);
        setPreferenceValue(path, key, value, this.userPrefs);
    }

    /**
     * Stores the given Value into the System-Preferences.
     *
     * @param keyPath - The full KeyPath
     * @param value - The new Value
     */
    public void setSystemString(final String keyPath, final String value) {
        Validate.notNull(keyPath);
        final String normalizedKey = normalizeKey(keyPath);
        final String path = getPath(normalizedKey);
        final String key = getKey(normalizedKey);
        setPreferenceValue(path, key, value, this.systemPrefs);
    }

    /**
     * Resolve the given path and key against the given Preferences.
     *
     * @param path the preferences path (placeholder part before '/')
     * @param key the preferences key (placeholder part after '/')
     * @param value the Value to store.
     * @param preferences the Preferences to resolve against
     */
    protected void setPreferenceValue(final String path, final String key, final String value,
            final Preferences preferences) {
        if (path != null) {
            preferences.node(path).put(key, value);
        } else {
            preferences.put(key, value);
        }
        try {
            preferences.flush();
        } catch (final BackingStoreException e) {
            throw new RuntimeException("Cannot access specified node path [" + path + "]", e);
        }
    }

    private String getKey(final String keyPath) {
        String key = keyPath;
        final int endOfPath = keyPath.lastIndexOf('/');
        if (endOfPath != -1) {
            key = keyPath.substring(endOfPath + 1);
        }
        return key;
    }

    private String normalizeKey(final String key) {
        Validate.notNull(key);
        String normalizeKey = key;

        normalizeKey = normalizeKey.replace('\\', '/');

        if (normalizeKey.startsWith("/")) {
            normalizeKey = normalizeKey.substring(1);
        }
        return normalizeKey;
    }
}