diff options
author | James Moger <james.moger@gitblit.com> | 2014-03-21 12:41:35 -0400 |
---|---|---|
committer | James Moger <james.moger@gitblit.com> | 2014-03-27 09:47:26 -0400 |
commit | 53a83f67aef203379e43a9ed89ccfcb16c16200e (patch) | |
tree | 27b762d9092f02f9e7bbc6a0749367125b2cf29c | |
parent | a0cefee11b3d7019a6406616ab533c73f7149304 (diff) | |
download | gitblit-53a83f67aef203379e43a9ed89ccfcb16c16200e.tar.gz gitblit-53a83f67aef203379e43a9ed89ccfcb16c16200e.zip |
Implement setting removal for configuration settings
-rw-r--r-- | src/main/java/com/gitblit/FileSettings.java | 17 | ||||
-rw-r--r-- | src/main/java/com/gitblit/IStoredSettings.java | 768 | ||||
-rw-r--r-- | src/main/java/com/gitblit/WebXmlSettings.java | 30 | ||||
-rw-r--r-- | src/main/java/com/gitblit/models/ServerSettings.java | 4 | ||||
-rw-r--r-- | src/test/java/com/gitblit/tests/mock/MemorySettings.java | 5 |
5 files changed, 451 insertions, 373 deletions
diff --git a/src/main/java/com/gitblit/FileSettings.java b/src/main/java/com/gitblit/FileSettings.java index d31fc2fb..21a20435 100644 --- a/src/main/java/com/gitblit/FileSettings.java +++ b/src/main/java/com/gitblit/FileSettings.java @@ -103,6 +103,23 @@ public class FileSettings extends IStoredSettings { return properties;
}
+ @Override
+ public boolean saveSettings() {
+ String content = FileUtils.readContent(propertiesFile, "\n");
+ for (String key : removals) {
+ String regex = "(?m)^(" + regExEscape(key) + "\\s*+=\\s*+)"
+ + "(?:[^\r\n\\\\]++|\\\\(?:\r?\n|\r|.))*+$";
+ content = content.replaceAll(regex, "");
+ }
+ removals.clear();
+
+ FileUtils.writeContent(propertiesFile, content);
+ // manually set the forceReload flag because not all JVMs support real
+ // millisecond resolution of lastModified. (issue-55)
+ forceReload = true;
+ return true;
+ }
+
/**
* Updates the specified settings in the settings file.
*/
diff --git a/src/main/java/com/gitblit/IStoredSettings.java b/src/main/java/com/gitblit/IStoredSettings.java index 13dca6b6..6d99832e 100644 --- a/src/main/java/com/gitblit/IStoredSettings.java +++ b/src/main/java/com/gitblit/IStoredSettings.java @@ -1,374 +1,396 @@ -/*
- * Copyright 2011 gitblit.com.
- *
- * 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.
- */
-package com.gitblit;
-
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.gitblit.utils.StringUtils;
-
-/**
- * Base class for stored settings implementations.
- *
- * @author James Moger
- *
- */
-public abstract class IStoredSettings {
-
- protected final Logger logger;
-
- protected final Properties overrides = new Properties();
-
- public IStoredSettings(Class<? extends IStoredSettings> clazz) {
- logger = LoggerFactory.getLogger(clazz);
- }
-
- protected abstract Properties read();
-
- private Properties getSettings() {
- Properties props = read();
- props.putAll(overrides);
- return props;
- }
-
- /**
- * Returns the list of keys whose name starts with the specified prefix. If
- * the prefix is null or empty, all key names are returned.
- *
- * @param startingWith
- * @return list of keys
- */
- public List<String> getAllKeys(String startingWith) {
- List<String> keys = new ArrayList<String>();
- Properties props = getSettings();
- if (StringUtils.isEmpty(startingWith)) {
- keys.addAll(props.stringPropertyNames());
- } else {
- startingWith = startingWith.toLowerCase();
- for (Object o : props.keySet()) {
- String key = o.toString();
- if (key.toLowerCase().startsWith(startingWith)) {
- keys.add(key);
- }
- }
- }
- return keys;
- }
-
- /**
- * Returns the boolean value for the specified key. If the key does not
- * exist or the value for the key can not be interpreted as a boolean, the
- * defaultValue is returned.
- *
- * @param key
- * @param defaultValue
- * @return key value or defaultValue
- */
- public boolean getBoolean(String name, boolean defaultValue) {
- Properties props = getSettings();
- if (props.containsKey(name)) {
- String value = props.getProperty(name);
- if (!StringUtils.isEmpty(value)) {
- return Boolean.parseBoolean(value.trim());
- }
- }
- return defaultValue;
- }
-
- /**
- * Returns the integer value for the specified key. If the key does not
- * exist or the value for the key can not be interpreted as an integer, the
- * defaultValue is returned.
- *
- * @param key
- * @param defaultValue
- * @return key value or defaultValue
- */
- public int getInteger(String name, int defaultValue) {
- Properties props = getSettings();
- if (props.containsKey(name)) {
- try {
- String value = props.getProperty(name);
- if (!StringUtils.isEmpty(value)) {
- return Integer.parseInt(value.trim());
- }
- } catch (NumberFormatException e) {
- logger.warn("Failed to parse integer for " + name + " using default of "
- + defaultValue);
- }
- }
- return defaultValue;
- }
-
- /**
- * Returns the long value for the specified key. If the key does not
- * exist or the value for the key can not be interpreted as an long, the
- * defaultValue is returned.
- *
- * @param key
- * @param defaultValue
- * @return key value or defaultValue
- */
- public long getLong(String name, long defaultValue) {
- Properties props = getSettings();
- if (props.containsKey(name)) {
- try {
- String value = props.getProperty(name);
- if (!StringUtils.isEmpty(value)) {
- return Long.parseLong(value.trim());
- }
- } catch (NumberFormatException e) {
- logger.warn("Failed to parse long for " + name + " using default of "
- + defaultValue);
- }
- }
- return defaultValue;
- }
-
- /**
- * Returns an int filesize from a string value such as 50m or 50mb
- * @param name
- * @param defaultValue
- * @return an int filesize or defaultValue if the key does not exist or can
- * not be parsed
- */
- public int getFilesize(String name, int defaultValue) {
- String val = getString(name, null);
- if (StringUtils.isEmpty(val)) {
- return defaultValue;
- }
- return com.gitblit.utils.FileUtils.convertSizeToInt(val, defaultValue);
- }
-
- /**
- * Returns an long filesize from a string value such as 50m or 50mb
- * @param n
- * @param defaultValue
- * @return a long filesize or defaultValue if the key does not exist or can
- * not be parsed
- */
- public long getFilesize(String key, long defaultValue) {
- String val = getString(key, null);
- if (StringUtils.isEmpty(val)) {
- return defaultValue;
- }
- return com.gitblit.utils.FileUtils.convertSizeToLong(val, defaultValue);
- }
-
- /**
- * Returns the char value for the specified key. If the key does not exist
- * or the value for the key can not be interpreted as a char, the
- * defaultValue is returned.
- *
- * @param key
- * @param defaultValue
- * @return key value or defaultValue
- */
- public char getChar(String name, char defaultValue) {
- Properties props = getSettings();
- if (props.containsKey(name)) {
- String value = props.getProperty(name);
- if (!StringUtils.isEmpty(value)) {
- return value.trim().charAt(0);
- }
- }
- return defaultValue;
- }
-
- /**
- * Returns the string value for the specified key. If the key does not exist
- * or the value for the key can not be interpreted as a string, the
- * defaultValue is returned.
- *
- * @param key
- * @param defaultValue
- * @return key value or defaultValue
- */
- public String getString(String name, String defaultValue) {
- Properties props = getSettings();
- if (props.containsKey(name)) {
- String value = props.getProperty(name);
- if (value != null) {
- return value.trim();
- }
- }
- return defaultValue;
- }
-
- /**
- * Returns the string value for the specified key. If the key does not
- * exist an exception is thrown.
- *
- * @param key
- * @return key value
- */
- public String getRequiredString(String name) {
- Properties props = getSettings();
- if (props.containsKey(name)) {
- String value = props.getProperty(name);
- if (value != null) {
- return value.trim();
- }
- }
- throw new RuntimeException("Property (" + name + ") does not exist");
- }
-
- /**
- * Returns a list of space-separated strings from the specified key.
- *
- * @param name
- * @return list of strings
- */
- public List<String> getStrings(String name) {
- return getStrings(name, " ");
- }
-
- /**
- * Returns a list of strings from the specified key using the specified
- * string separator.
- *
- * @param name
- * @param separator
- * @return list of strings
- */
- public List<String> getStrings(String name, String separator) {
- List<String> strings = new ArrayList<String>();
- Properties props = getSettings();
- if (props.containsKey(name)) {
- String value = props.getProperty(name);
- strings = StringUtils.getStringsFromValue(value, separator);
- }
- return strings;
- }
-
- /**
- * Returns a list of space-separated integers from the specified key.
- *
- * @param name
- * @return list of strings
- */
- public List<Integer> getIntegers(String name) {
- return getIntegers(name, " ");
- }
-
- /**
- * Returns a list of integers from the specified key using the specified
- * string separator.
- *
- * @param name
- * @param separator
- * @return list of integers
- */
- public List<Integer> getIntegers(String name, String separator) {
- List<Integer> ints = new ArrayList<Integer>();
- Properties props = getSettings();
- if (props.containsKey(name)) {
- String value = props.getProperty(name);
- List<String> strings = StringUtils.getStringsFromValue(value, separator);
- for (String str : strings) {
- try {
- int i = Integer.parseInt(str);
- ints.add(i);
- } catch (NumberFormatException e) {
- }
- }
- }
- return ints;
- }
-
- /**
- * Returns a map of strings from the specified key.
- *
- * @param name
- * @return map of string, string
- */
- public Map<String, String> getMap(String name) {
- Map<String, String> map = new LinkedHashMap<String, String>();
- for (String string : getStrings(name)) {
- String[] kvp = string.split("=", 2);
- String key = kvp[0];
- String value = kvp[1];
- map.put(key, value);
- }
- return map;
- }
-
- /**
- * Override the specified key with the specified value.
- *
- * @param key
- * @param value
- */
- public void overrideSetting(String key, String value) {
- overrides.put(key, value);
- }
-
- /**
- * Override the specified key with the specified value.
- *
- * @param key
- * @param value
- */
- public void overrideSetting(String key, int value) {
- overrides.put(key, "" + value);
- }
-
- /**
- * Override the specified key with the specified value.
- *
- * @param key
- * @param value
- */
- public void overrideSetting(String key, boolean value) {
- overrides.put(key, "" + value);
- }
-
- /**
- * Tests for the existence of a setting.
- *
- * @param key
- * @return true if the setting exists
- */
- public boolean hasSettings(String key) {
- return getString(key, null) != null;
- }
-
- /**
- * Updates the values for the specified keys and persists the entire
- * configuration file.
- *
- * @param map
- * of key, value pairs
- * @return true if successful
- */
- public abstract boolean saveSettings(Map<String, String> updatedSettings);
-
- /**
- * Merge all settings from the settings parameter into this instance.
- *
- * @param settings
- */
- public void merge(IStoredSettings settings) {
- getSettings().putAll(settings.getSettings());
- overrides.putAll(settings.overrides);
- }
+/* + * Copyright 2011 gitblit.com. + * + * 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. + */ +package com.gitblit; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.TreeSet; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.gitblit.utils.StringUtils; + +/** + * Base class for stored settings implementations. + * + * @author James Moger + * + */ +public abstract class IStoredSettings { + + protected final Logger logger; + + protected final Properties overrides = new Properties(); + + protected final Set<String> removals = new TreeSet<String>(); + + public IStoredSettings(Class<? extends IStoredSettings> clazz) { + logger = LoggerFactory.getLogger(clazz); + } + + protected abstract Properties read(); + + private Properties getSettings() { + Properties props = read(); + props.putAll(overrides); + return props; + } + + /** + * Returns the list of keys whose name starts with the specified prefix. If + * the prefix is null or empty, all key names are returned. + * + * @param startingWith + * @return list of keys + */ + public List<String> getAllKeys(String startingWith) { + List<String> keys = new ArrayList<String>(); + Properties props = getSettings(); + if (StringUtils.isEmpty(startingWith)) { + keys.addAll(props.stringPropertyNames()); + } else { + startingWith = startingWith.toLowerCase(); + for (Object o : props.keySet()) { + String key = o.toString(); + if (key.toLowerCase().startsWith(startingWith)) { + keys.add(key); + } + } + } + return keys; + } + + /** + * Returns the boolean value for the specified key. If the key does not + * exist or the value for the key can not be interpreted as a boolean, the + * defaultValue is returned. + * + * @param key + * @param defaultValue + * @return key value or defaultValue + */ + public boolean getBoolean(String name, boolean defaultValue) { + Properties props = getSettings(); + if (props.containsKey(name)) { + String value = props.getProperty(name); + if (!StringUtils.isEmpty(value)) { + return Boolean.parseBoolean(value.trim()); + } + } + return defaultValue; + } + + /** + * Returns the integer value for the specified key. If the key does not + * exist or the value for the key can not be interpreted as an integer, the + * defaultValue is returned. + * + * @param key + * @param defaultValue + * @return key value or defaultValue + */ + public int getInteger(String name, int defaultValue) { + Properties props = getSettings(); + if (props.containsKey(name)) { + try { + String value = props.getProperty(name); + if (!StringUtils.isEmpty(value)) { + return Integer.parseInt(value.trim()); + } + } catch (NumberFormatException e) { + logger.warn("Failed to parse integer for " + name + " using default of " + + defaultValue); + } + } + return defaultValue; + } + + /** + * Returns the long value for the specified key. If the key does not + * exist or the value for the key can not be interpreted as an long, the + * defaultValue is returned. + * + * @param key + * @param defaultValue + * @return key value or defaultValue + */ + public long getLong(String name, long defaultValue) { + Properties props = getSettings(); + if (props.containsKey(name)) { + try { + String value = props.getProperty(name); + if (!StringUtils.isEmpty(value)) { + return Long.parseLong(value.trim()); + } + } catch (NumberFormatException e) { + logger.warn("Failed to parse long for " + name + " using default of " + + defaultValue); + } + } + return defaultValue; + } + + /** + * Returns an int filesize from a string value such as 50m or 50mb + * @param name + * @param defaultValue + * @return an int filesize or defaultValue if the key does not exist or can + * not be parsed + */ + public int getFilesize(String name, int defaultValue) { + String val = getString(name, null); + if (StringUtils.isEmpty(val)) { + return defaultValue; + } + return com.gitblit.utils.FileUtils.convertSizeToInt(val, defaultValue); + } + + /** + * Returns an long filesize from a string value such as 50m or 50mb + * @param n + * @param defaultValue + * @return a long filesize or defaultValue if the key does not exist or can + * not be parsed + */ + public long getFilesize(String key, long defaultValue) { + String val = getString(key, null); + if (StringUtils.isEmpty(val)) { + return defaultValue; + } + return com.gitblit.utils.FileUtils.convertSizeToLong(val, defaultValue); + } + + /** + * Returns the char value for the specified key. If the key does not exist + * or the value for the key can not be interpreted as a char, the + * defaultValue is returned. + * + * @param key + * @param defaultValue + * @return key value or defaultValue + */ + public char getChar(String name, char defaultValue) { + Properties props = getSettings(); + if (props.containsKey(name)) { + String value = props.getProperty(name); + if (!StringUtils.isEmpty(value)) { + return value.trim().charAt(0); + } + } + return defaultValue; + } + + /** + * Returns the string value for the specified key. If the key does not exist + * or the value for the key can not be interpreted as a string, the + * defaultValue is returned. + * + * @param key + * @param defaultValue + * @return key value or defaultValue + */ + public String getString(String name, String defaultValue) { + Properties props = getSettings(); + if (props.containsKey(name)) { + String value = props.getProperty(name); + if (value != null) { + return value.trim(); + } + } + return defaultValue; + } + + /** + * Returns the string value for the specified key. If the key does not + * exist an exception is thrown. + * + * @param key + * @return key value + */ + public String getRequiredString(String name) { + Properties props = getSettings(); + if (props.containsKey(name)) { + String value = props.getProperty(name); + if (value != null) { + return value.trim(); + } + } + throw new RuntimeException("Property (" + name + ") does not exist"); + } + + /** + * Returns a list of space-separated strings from the specified key. + * + * @param name + * @return list of strings + */ + public List<String> getStrings(String name) { + return getStrings(name, " "); + } + + /** + * Returns a list of strings from the specified key using the specified + * string separator. + * + * @param name + * @param separator + * @return list of strings + */ + public List<String> getStrings(String name, String separator) { + List<String> strings = new ArrayList<String>(); + Properties props = getSettings(); + if (props.containsKey(name)) { + String value = props.getProperty(name); + strings = StringUtils.getStringsFromValue(value, separator); + } + return strings; + } + + /** + * Returns a list of space-separated integers from the specified key. + * + * @param name + * @return list of strings + */ + public List<Integer> getIntegers(String name) { + return getIntegers(name, " "); + } + + /** + * Returns a list of integers from the specified key using the specified + * string separator. + * + * @param name + * @param separator + * @return list of integers + */ + public List<Integer> getIntegers(String name, String separator) { + List<Integer> ints = new ArrayList<Integer>(); + Properties props = getSettings(); + if (props.containsKey(name)) { + String value = props.getProperty(name); + List<String> strings = StringUtils.getStringsFromValue(value, separator); + for (String str : strings) { + try { + int i = Integer.parseInt(str); + ints.add(i); + } catch (NumberFormatException e) { + } + } + } + return ints; + } + + /** + * Returns a map of strings from the specified key. + * + * @param name + * @return map of string, string + */ + public Map<String, String> getMap(String name) { + Map<String, String> map = new LinkedHashMap<String, String>(); + for (String string : getStrings(name)) { + String[] kvp = string.split("=", 2); + String key = kvp[0]; + String value = kvp[1]; + map.put(key, value); + } + return map; + } + + /** + * Override the specified key with the specified value. + * + * @param key + * @param value + */ + public void overrideSetting(String key, String value) { + overrides.put(key, value); + } + + /** + * Override the specified key with the specified value. + * + * @param key + * @param value + */ + public void overrideSetting(String key, int value) { + overrides.put(key, "" + value); + } + + /** + * Override the specified key with the specified value. + * + * @param key + * @param value + */ + public void overrideSetting(String key, boolean value) { + overrides.put(key, "" + value); + } + + /** + * Tests for the existence of a setting. + * + * @param key + * @return true if the setting exists + */ + public boolean hasSettings(String key) { + return getString(key, null) != null; + } + + /** + * Remove a setting. + * + * @param key + */ + public void removeSetting(String key) { + getSettings().remove(key); + overrides.remove(key); + removals.add(key); + } + + /** + * Saves the current settings. + * + * @param map + */ + public abstract boolean saveSettings(); + + /** + * Updates the values for the specified keys and persists the entire + * configuration file. + * + * @param map + * of key, value pairs + * @return true if successful + */ + public abstract boolean saveSettings(Map<String, String> updatedSettings); + + /** + * Merge all settings from the settings parameter into this instance. + * + * @param settings + */ + public void merge(IStoredSettings settings) { + getSettings().putAll(settings.getSettings()); + overrides.putAll(settings.overrides); + } }
\ No newline at end of file diff --git a/src/main/java/com/gitblit/WebXmlSettings.java b/src/main/java/com/gitblit/WebXmlSettings.java index 7ae26975..228c27db 100644 --- a/src/main/java/com/gitblit/WebXmlSettings.java +++ b/src/main/java/com/gitblit/WebXmlSettings.java @@ -80,6 +80,36 @@ public class WebXmlSettings extends IStoredSettings { }
@Override
+ public synchronized boolean saveSettings() {
+ try {
+ Properties props = new Properties();
+ // load pre-existing web-configuration
+ if (overrideFile.exists()) {
+ InputStream is = new FileInputStream(overrideFile);
+ props.load(is);
+ is.close();
+ }
+
+ // put all new settings and persist
+ for (String key : removals) {
+ props.remove(key);
+ }
+ removals.clear();
+ OutputStream os = new FileOutputStream(overrideFile);
+ props.store(os, null);
+ os.close();
+
+ // override current runtime settings
+ properties.clear();
+ properties.putAll(props);
+ return true;
+ } catch (Throwable t) {
+ logger.error("Failed to save settings!", t);
+ }
+ return false;
+ }
+
+ @Override
public synchronized boolean saveSettings(Map<String, String> settings) {
try {
Properties props = new Properties();
diff --git a/src/main/java/com/gitblit/models/ServerSettings.java b/src/main/java/com/gitblit/models/ServerSettings.java index 07e703b0..4e9216a3 100644 --- a/src/main/java/com/gitblit/models/ServerSettings.java +++ b/src/main/java/com/gitblit/models/ServerSettings.java @@ -58,4 +58,8 @@ public class ServerSettings implements Serializable { public boolean hasKey(String key) {
return settings.containsKey(key);
}
+
+ public SettingModel remove(String key) {
+ return settings.remove(key);
+ }
}
diff --git a/src/test/java/com/gitblit/tests/mock/MemorySettings.java b/src/test/java/com/gitblit/tests/mock/MemorySettings.java index e3f971f0..673d3f2f 100644 --- a/src/test/java/com/gitblit/tests/mock/MemorySettings.java +++ b/src/test/java/com/gitblit/tests/mock/MemorySettings.java @@ -48,6 +48,11 @@ public class MemorySettings extends IStoredSettings { } @Override + public boolean saveSettings() { + return false; + } + + @Override public boolean saveSettings(Map<String, String> updatedSettings) { return false; } |