Java tutorial
/** * Copyright (C) 2005 - 2012 Eric Van Dewoestine * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.eclim.plugin.core.preference; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import org.apache.commons.lang.ArrayUtils; import org.eclim.Services; import org.eclim.logging.Logger; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ProjectScope; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.IScopeContext; import org.eclipse.core.runtime.preferences.InstanceScope; import com.google.gson.Gson; /** * Class for handling preferences for eclim. * * This class uses the word 'option' for a built in eclipse options (like the * jdt compiler source version), and the word 'preference' for eclim provided * key values. * * @author Eric Van Dewoestine */ public class Preferences { private static final Logger logger = Logger.getLogger(Preferences.class); public static final String USERNAME_PREFERENCE = "org.eclim.user.name"; public static final String USEREMAIL_PREFERENCE = "org.eclim.user.email"; public static final String PROJECT_COPYRIGHT_PREFERENCE = "org.eclim.project.copyright"; private static final String NODE_NAME = "org.eclim"; private static final String CORE = "core"; private static final String GLOBAL = "_global_"; private static Preferences instance = new Preferences(); private static Map<String, OptionHandler> optionHandlers = new HashMap<String, OptionHandler>(); private Map<String, Preference> preferences = new HashMap<String, Preference>(); private Map<String, Option> options = new HashMap<String, Option>(); // cache preference values private Map<String, Map<String, String>> preferenceValues = new HashMap<String, Map<String, String>>(); // cache option values private Map<String, Map<String, String>> optionValues = new HashMap<String, Map<String, String>>(); private Preferences() { } /** * Gets the Preferences instance. * * @return The Preferences singleton. */ public static Preferences getInstance() { return instance; } /** * Adds the supplied OptionHandler to manage eclipse options with the * specified prefix. * * @param prefix The prefix. * @param handler The OptionHandler. * @return The OptionHandler. */ public static OptionHandler addOptionHandler(String prefix, OptionHandler handler) { optionHandlers.put(prefix, handler); return handler; } /** * Adds an eclim preference to be made available. * * @param preference The preference to add. */ public void addPreference(Preference preference) { preferences.put(preference.getName(), preference); preferenceValues.clear(); } /** * Gets an array of configured preference names. * * @return Array of preference names. */ public String[] getPreferenceNames() { return preferences.keySet().toArray(new String[0]); } /** * Adds an eclipse option to be configurable via eclim. * * @param option The option. */ public void addOption(Option option) { options.put(option.getName(), option); optionValues.clear(); } /** * Gets an array of configured option names. * * @return Array of option names. */ public String[] getOptionNames() { return options.keySet().toArray(new String[0]); } /** * Clear cached option/preference values. * * @param project The project. */ public void clearProjectValueCache(IProject project) { preferenceValues.remove(project.getName()); optionValues.remove(project.getName()); } /** * Gets a map of all options/preferences. * * @return A map of key values. */ public Map<String, String> getValues() throws Exception { return getValues(null); } /** * Gets a map of all options/preferences. * * @param project The current project. * @return A map of key values. */ public Map<String, String> getValues(IProject project) throws Exception { String cacheKey = project != null ? project.getName() : GLOBAL; // eclim preferences Map<String, String> prefVals = preferenceValues.get(cacheKey); if (prefVals == null) { prefVals = new HashMap<String, String>(); preferenceValues.put(cacheKey, prefVals); IScopeContext context = InstanceScope.INSTANCE; // global IEclipsePreferences globalPrefs = context.getNode(NODE_NAME); initializeDefaultPreferences(globalPrefs); for (String key : globalPrefs.keys()) { prefVals.put(key, globalPrefs.get(key, null)); } // project if (project != null) { context = new ProjectScope(project); IEclipsePreferences projectPrefs = context.getNode(NODE_NAME); for (String key : projectPrefs.keys()) { prefVals.put(key, projectPrefs.get(key, null)); } } } // eclipse option Map<String, String> optVals = optionValues.get(cacheKey); if (optVals == null) { optVals = new HashMap<String, String>(); optionValues.put(cacheKey, optVals); for (OptionHandler handler : optionHandlers.values()) { String nature = handler.getNature(); if (CORE.equals(nature) || project == null || project.getNature(nature) != null) { Map<String, String> ops = project == null ? handler.getValues() : handler.getValues(project); if (ops != null) { optVals.putAll(ops); } } } } Map<String, String> all = new HashMap<String, String>(preferenceValues.size() + optionValues.size()); all.putAll(optVals); all.putAll(prefVals); return all; } /** * Gets the value of an option/preference. * * @param name The name of the option/preference. * @return The value or null if not found. */ public String getValue(String name) throws Exception { return getValues(null).get(name); } /** * Gets the value of a project option/preference. * * @param project The project. * @param name The name of the option/preference. * @return The value or null if not found. */ public String getValue(IProject project, String name) throws Exception { return getValues(project).get(name); } /** * Gets the integer value of an option/preference. * * @param name The name of the option/preference. * @return The value or -1 if not found. */ public int getIntValue(String name) throws Exception { return getIntValue(null, name); } /** * Gets the integer value of a project option/preference. * * @param project The project. * @param name The name of the option/preference. * @return The value or -1 if not found. */ public int getIntValue(IProject project, String name) throws Exception { String value = getValues(project).get(name); return value != null ? Integer.parseInt(value) : -1; } /** * Gets the array value of an option/preference. * * @param name The name of the option/preference. * @return The array value or null if not found */ public String[] getArrayValue(String name) throws Exception { return getArrayValue(null, name); } /** * Gets the array value of a project option/preference. * * @param project The project. * @param name The name of the option/preference. * @return The array value or and empty array if not found. */ public String[] getArrayValue(IProject project, String name) throws Exception { String value = getValues(project).get(name); if (value != null && value.trim().length() != 0) { return new Gson().fromJson(value, String[].class); } return ArrayUtils.EMPTY_STRING_ARRAY; } /** * Gets the global Option/Preference objects. * * @return Array of Option. */ public Option[] getOptions() throws Exception { return getOptions(null); } /** * Gets the Option/Preference objects. * * @param project The project scope or null for global. * @return Array of Option. */ public Option[] getOptions(IProject project) throws Exception { ArrayList<OptionInstance> results = new ArrayList<OptionInstance>(); Map<String, String> options = new HashMap<String, String>(); // global IScopeContext context = InstanceScope.INSTANCE; IEclipsePreferences globalPrefs = context.getNode(NODE_NAME); initializeDefaultPreferences(globalPrefs); for (String key : globalPrefs.keys()) { options.put(key, globalPrefs.get(key, null)); } // project if (project != null) { context = new ProjectScope(project); IEclipsePreferences projectPrefs = context.getNode(NODE_NAME); for (String key : projectPrefs.keys()) { options.put(key, projectPrefs.get(key, null)); } } for (OptionHandler handler : optionHandlers.values()) { String nature = handler.getNature(); if (CORE.equals(nature) || project == null || project.getNature(nature) != null) { Map<String, String> ops = project == null ? handler.getValues() : handler.getValues(project); if (ops != null) { options.putAll(ops); } } } for (String key : options.keySet()) { String value = options.get(key); Option option = this.options.get(key); if (option == null) { option = this.preferences.get(key); } if (option != null && value != null) { String nature = option.getNature(); if (CORE.equals(nature) || project == null || project.getNature(nature) != null) { OptionInstance instance = new OptionInstance(option, value); results.add(instance); } } } return results.toArray(new Option[results.size()]); } /** * Sets the supplied option/preference value. * * @param name The option/preference name. * @param value The option/preference value. */ public void setValue(String name, String value) throws Exception { setValue(null, name, value); } /** * Set the supplied value. * * @param project The project to set the value for or null for global. * @param name The name of the option/preference. * @param value The value of the option/preference. */ public void setValue(IProject project, String name, String value) throws IllegalArgumentException, Exception { if (name.startsWith(NODE_NAME)) { setPreference(NODE_NAME, project, name, value); } else { validateValue(options.get(name), name, value); OptionHandler handler = null; for (Object k : optionHandlers.keySet()) { String key = (String) k; if (name.startsWith(key)) { handler = (OptionHandler) optionHandlers.get(key); break; } } if (handler != null) { if (project == null) { handler.setOption(name, value); } else { handler.setOption(project, name, value); } optionValues.clear(); } else { logger.warn("No handler found for option '{}'", name); } } } /** * Sets an eclim preference value. * * @param nodeName The name of the preferences node to write the preference * to. * @param project The project to set the value for or null to set globally. * @param name The name of the preference. * @param value The value of the preference. */ public void setPreference(String nodeName, IProject project, String name, String value) throws IllegalArgumentException, Exception { IScopeContext context = InstanceScope.INSTANCE; IEclipsePreferences globalPrefs = context.getNode(nodeName); initializeDefaultPreferences(globalPrefs); Option pref = preferences.get(name); if (pref == null) { pref = options.get(name); } // set global if (project == null) { validateValue(pref, name, value); globalPrefs.put(name, value); globalPrefs.flush(); } else { context = new ProjectScope(project); IEclipsePreferences projectPrefs = context.getNode(nodeName); // if project value is the same as the global, then remove it. if (value.equals(globalPrefs.get(name, null))) { projectPrefs.remove(name); projectPrefs.flush(); // if project value differs from global, then persist it. } else { validateValue(pref, name, value); projectPrefs.put(name, value); projectPrefs.flush(); } } preferenceValues.clear(); } /** * Initializes the default preferences. * Note: should only be run against the global preferences (not project, etc.). * * @param preferences The eclipse preferences. */ private void initializeDefaultPreferences(IEclipsePreferences preferences) throws Exception { String node = preferences.name(); for (Preference preference : this.preferences.values()) { String name = preference.getName(); if (name.startsWith(node) && preferences.get(name, null) == null) { preferences.put(preference.getName(), preference.getDefaultValue()); } } preferences.flush(); } /** * Validates that the supplied value is valid for the specified * option/preference. * * @param option The option/preference instance. * @param name The name of the option/preference. * @param value The value of the option/preference. */ private void validateValue(Option option, String name, String value) throws IllegalArgumentException { if (option != null) { Validator validator = option.getValidator(); if (validator == null || validator.isValid(value)) { return; } throw new IllegalArgumentException( Services.getMessage("setting.invalid", name, validator.getMessage(name, value))); } throw new IllegalArgumentException(Services.getMessage("setting.not.found", name)); } }