From 97a20ed01cb5ec890517e4fcbd67b8d8ff381787 Mon Sep 17 00:00:00 2001 From: James Moger Date: Mon, 24 Oct 2011 21:51:46 -0400 Subject: [PATCH] Working edit settings RPC. Web.xml is not directly modified. --- .gitignore | 2 +- build.xml | 9 +++-- docs/02_rpc.mkd | 1 + src/com/gitblit/FileSettings.java | 22 +++++++++++++ src/com/gitblit/GitBlit.java | 8 ++--- src/com/gitblit/IStoredSettings.java | 11 +++++++ src/com/gitblit/RpcServlet.java | 2 +- src/com/gitblit/WebXmlSettings.java | 47 +++++++++++++++++++++++++++ src/com/gitblit/utils/RpcUtils.java | 3 +- tests/com/gitblit/tests/RpcTests.java | 28 +++++++++++++++- 10 files changed, 120 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index 86347ca9..3c0210d0 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,6 @@ /federation.properties /mailtest.properties /.settings/*.prefs -/src/WEB-INF/gitblit.properties +/src/WEB-INF/reference.properties /bin/ /.settings/ diff --git a/build.xml b/build.xml index 107fac37..4a5c8867 100644 --- a/build.xml +++ b/build.xml @@ -106,7 +106,7 @@ - + - @@ -326,6 +325,10 @@ + + + diff --git a/docs/02_rpc.mkd b/docs/02_rpc.mkd index 0150d168..82655085 100644 --- a/docs/02_rpc.mkd +++ b/docs/02_rpc.mkd @@ -31,6 +31,7 @@ The Gitblit RPC mechanism, like the Gitblit JGit servlet, syndication/feed servl LIST_FEDERATION_PROPOSALS-admin-List<FederationProposal> LIST_FEDERATION_SETS-admin-List<FederationSet> LIST_SETTINGS-admin-ServerSettings (see example below) +EDIT_SETTINGS-adminMap<String, String>- LIST_STATUS-admin-ServerStatus (see example below) diff --git a/src/com/gitblit/FileSettings.java b/src/com/gitblit/FileSettings.java index 56aac8b7..61100587 100644 --- a/src/com/gitblit/FileSettings.java +++ b/src/com/gitblit/FileSettings.java @@ -18,7 +18,11 @@ package com.gitblit; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.util.Map; import java.util.Properties; +import java.util.regex.Pattern; + +import com.gitblit.utils.FileUtils; /** * Dynamically loads and reloads a properties file by keeping track of the last @@ -74,6 +78,24 @@ public class FileSettings extends IStoredSettings { return properties; } + /** + * Updates the specified settings in the settings file. + */ + public synchronized boolean saveSettings(Map settings) { + String content = FileUtils.readContent(propertiesFile, "\n"); + for (Map.Entry setting:settings.entrySet()) { + String regex = "(?m)^(" + regExEscape(setting.getKey()) + "\\s*+=\\s*+)" + + "(?:[^\r\n\\\\]++|\\\\(?:\r?\n|\r|.))*+$"; + content = content.replaceAll(regex, setting.getKey() + " = " + setting.getValue()); + } + FileUtils.writeContent(propertiesFile, content); + return true; + } + + private String regExEscape(String input) { + return input.replace(".", "\\."); + } + /** * @return the last modification date of the properties file */ diff --git a/src/com/gitblit/GitBlit.java b/src/com/gitblit/GitBlit.java index ffef94a7..8386d2d4 100644 --- a/src/com/gitblit/GitBlit.java +++ b/src/com/gitblit/GitBlit.java @@ -25,7 +25,6 @@ import java.lang.reflect.Field; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -253,9 +252,8 @@ public class GitBlit implements ServletContextListener { * @param settings * @return true if the update succeeded */ - public boolean updateSettings(Collection settings) { - // TODO update the settings - return false; + public boolean updateSettings(Map updatedSettings) { + return settings.saveSettings(updatedSettings); } public ServerStatus getStatus() { @@ -1326,7 +1324,7 @@ public class GitBlit implements ServletContextListener { // Read bundled Gitblit properties to extract setting descriptions. // This copy is pristine and only used for populating the setting // models map. - InputStream is = servletContext.getResourceAsStream("/WEB-INF/gitblit.properties"); + InputStream is = servletContext.getResourceAsStream("/WEB-INF/reference.properties"); BufferedReader propertiesReader = new BufferedReader(new InputStreamReader(is)); StringBuilder description = new StringBuilder(); SettingModel setting = new SettingModel(); diff --git a/src/com/gitblit/IStoredSettings.java b/src/com/gitblit/IStoredSettings.java index a376c81a..2d8b6055 100644 --- a/src/com/gitblit/IStoredSettings.java +++ b/src/com/gitblit/IStoredSettings.java @@ -17,6 +17,7 @@ package com.gitblit; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Properties; import org.slf4j.Logger; @@ -194,4 +195,14 @@ public abstract class IStoredSettings { public void overrideSetting(String key, String value) { overrides.put(key, value); } + + /** + * 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 updatedSettings); } \ No newline at end of file diff --git a/src/com/gitblit/RpcServlet.java b/src/com/gitblit/RpcServlet.java index 7cf3a598..1136692a 100644 --- a/src/com/gitblit/RpcServlet.java +++ b/src/com/gitblit/RpcServlet.java @@ -191,7 +191,7 @@ public class RpcServlet extends JsonServlet { } else if (RpcRequest.EDIT_SETTINGS.equals(reqType)) { // update settings on the server if (GitBlit.getBoolean(Keys.web.enableRpcAdministration, false)) { - Collection settings = deserialize(request, response, + Map settings = deserialize(request, response, RpcUtils.SETTINGS_TYPE); GitBlit.self().updateSettings(settings); } else { diff --git a/src/com/gitblit/WebXmlSettings.java b/src/com/gitblit/WebXmlSettings.java index 4b0358d2..055c7d35 100644 --- a/src/com/gitblit/WebXmlSettings.java +++ b/src/com/gitblit/WebXmlSettings.java @@ -15,7 +15,13 @@ */ package com.gitblit; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; import java.util.Enumeration; +import java.util.Map; import java.util.Properties; import javax.servlet.ServletContext; @@ -32,8 +38,11 @@ public class WebXmlSettings extends IStoredSettings { private final Properties properties = new Properties(); + private final ServletContext context; + public WebXmlSettings(ServletContext context) { super(WebXmlSettings.class); + this.context = context; Enumeration keys = context.getInitParameterNames(); while (keys.hasMoreElements()) { String key = keys.nextElement().toString(); @@ -41,6 +50,17 @@ public class WebXmlSettings extends IStoredSettings { properties.put(key, decodeValue(value)); logger.debug(key + "=" + properties.getProperty(key)); } + // apply any web-configured overrides + File file = new File(context.getRealPath("/WEB-INF/web.properties")); + if (file.exists()) { + try { + InputStream is = new FileInputStream(file); + properties.load(is); + is.close(); + } catch (Throwable t) { + logger.error("Failed to load web.properties setting overrides", t); + } + } } private String decodeValue(String value) { @@ -53,6 +73,33 @@ public class WebXmlSettings extends IStoredSettings { return properties; } + @Override + public synchronized boolean saveSettings(Map settings) { + try { + Properties props = new Properties(); + // load pre-existing web-configuration + File file = new File(context.getRealPath("/WEB-INF/web.properties")); + if (file.exists()) { + InputStream is = new FileInputStream(file); + props.load(is); + is.close(); + } + + // put all new settings and persist + props.putAll(settings); + OutputStream os = new FileOutputStream(file); + props.store(os, null); + os.close(); + + // override current runtime settings + properties.putAll(settings); + return true; + } catch (Throwable t) { + logger.error("Failed to save settings!", t); + } + return false; + } + @Override public String toString() { return "WEB.XML"; diff --git a/src/com/gitblit/utils/RpcUtils.java b/src/com/gitblit/utils/RpcUtils.java index 6572cd9d..e5841518 100644 --- a/src/com/gitblit/utils/RpcUtils.java +++ b/src/com/gitblit/utils/RpcUtils.java @@ -30,7 +30,6 @@ import com.gitblit.models.FederationSet; import com.gitblit.models.RepositoryModel; import com.gitblit.models.ServerSettings; import com.gitblit.models.ServerStatus; -import com.gitblit.models.SettingModel; import com.gitblit.models.UserModel; import com.google.gson.reflect.TypeToken; @@ -45,7 +44,7 @@ public class RpcUtils { public static final Type NAMES_TYPE = new TypeToken>() { }.getType(); - public static final Type SETTINGS_TYPE = new TypeToken>() { + public static final Type SETTINGS_TYPE = new TypeToken>() { }.getType(); private static final Type REPOSITORIES_TYPE = new TypeToken>() { diff --git a/tests/com/gitblit/tests/RpcTests.java b/tests/com/gitblit/tests/RpcTests.java index 11a340a9..2860f32b 100644 --- a/tests/com/gitblit/tests/RpcTests.java +++ b/tests/com/gitblit/tests/RpcTests.java @@ -16,6 +16,7 @@ package com.gitblit.tests; import java.io.IOException; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -23,6 +24,7 @@ import junit.framework.TestCase; import com.gitblit.Constants.AccessRestrictionType; import com.gitblit.GitBlitException.UnauthorizedException; +import com.gitblit.Keys; import com.gitblit.models.FederationModel; import com.gitblit.models.FederationProposal; import com.gitblit.models.FederationSet; @@ -210,9 +212,33 @@ public class RpcTests extends TestCase { ServerSettings settings = RpcUtils.getSettings(url, account, password.toCharArray()); assertTrue("No settings were retrieved!", settings != null); } - + public void testServerStatus() throws Exception { ServerStatus status = RpcUtils.getStatus(url, account, password.toCharArray()); assertTrue("No status was retrieved!", status != null); } + + public void testUpdateSettings() throws Exception { + Map updated = new HashMap(); + + // grab current setting + ServerSettings settings = RpcUtils.getSettings(url, account, password.toCharArray()); + boolean showSizes = settings.get(Keys.web.showRepositorySizes).getBoolean(true); + showSizes = !showSizes; + + // update setting + updated.put(Keys.web.showRepositorySizes, String.valueOf(showSizes)); + boolean success = RpcUtils.updateSettings(updated, "http://localhost:8080/gb", account, + password.toCharArray()); + assertTrue("Failed to update server settings", success); + + // confirm setting change + settings = RpcUtils.getSettings(url, account, password.toCharArray()); + boolean newValue = settings.get(Keys.web.showRepositorySizes).getBoolean(false); + assertEquals(newValue, showSizes); + + // restore setting + newValue = !newValue; + updated.put(Keys.web.showRepositorySizes, String.valueOf(newValue)); + } } -- 2.39.5