]> source.dussan.org Git - gitblit.git/commitdiff
Revised settings RPC to be Map<String, SettingModel>.
authorJames Moger <james.moger@gitblit.com>
Fri, 21 Oct 2011 21:34:12 +0000 (17:34 -0400)
committerJames Moger <james.moger@gitblit.com>
Fri, 21 Oct 2011 21:34:12 +0000 (17:34 -0400)
Added setting metadata. Added server status rpc. Improved setting tab in
Manager.

15 files changed:
build.xml
docs/02_rpc.mkd
src/com/gitblit/Constants.java
src/com/gitblit/GitBlit.java
src/com/gitblit/RpcServlet.java
src/com/gitblit/client/EditUserDialog.java
src/com/gitblit/client/GitblitModel.java
src/com/gitblit/client/GitblitPanel.java
src/com/gitblit/client/SettingCellRenderer.java [new file with mode: 0644]
src/com/gitblit/client/SettingPanel.java [new file with mode: 0644]
src/com/gitblit/client/SettingsModel.java
src/com/gitblit/models/ServerStatus.java [new file with mode: 0644]
src/com/gitblit/models/SettingModel.java [new file with mode: 0644]
src/com/gitblit/utils/RpcUtils.java
tests/com/gitblit/tests/RpcTests.java

index 92174d4c209f9169272bcac7b82546860dde34f8..107fac373cf25d813e0fea6d2194394c5b409742 100644 (file)
--- a/build.xml
+++ b/build.xml
                        </fileset>\r
                </copy>\r
 \r
+               <!-- copy gitblit.properties to the WEB-INF folder.\r
+                    this file is only used for parsing setting descriptions. -->\r
+               <copy todir="${basedir}/src/WEB-INF" overwrite="true"\r
+                       file="${basedir}/distrib/gitblit.properties" />\r
+\r
                <!-- Compile the build tool and execute it.\r
                         This downloads missing compile-time dependencies from Maven. -->\r
 \r
                \r
                <delete dir="${project.war.dir}" />             \r
 \r
-               <!-- Copy web.xml and users.properties to WEB-INF -->\r
+               <!-- Copy web.xml, users.properties, and gitblit.properties to WEB-INF -->\r
                <copy todir="${project.war.dir}/WEB-INF">\r
                        <fileset dir="${basedir}/distrib">\r
                                <include name="users.properties" />\r
+                               <include name="gitblit.properties" />\r
                        </fileset>\r
                        <fileset dir="${basedir}/src/WEB-INF">\r
                                <include name="web.xml" />\r
index fbc5e44a9d68ce0b71741667704559a82522c1dd..b01eb6798d0fdebc8ba37f78c6a2f0ec2e196583 100644 (file)
@@ -30,10 +30,10 @@ The Gitblit RPC mechanism, like the Gitblit JGit servlet, syndication/feed servl
 <tr><td>LIST_FEDERATION_RESULTS</td><td>-</td><td><em>admin</em></td><td>-</td><td>List&lt;FederationModel&gt;</td></tr>\r
 <tr><td>LIST_FEDERATION_PROPOSALS</td><td>-</td><td><em>admin</em></td><td>-</td><td>List&lt;FederationProposal&gt;</td></tr>\r
 <tr><td>LIST_FEDERATION_SETS</td><td>-</td><td><em>admin</em></td><td>-</td><td>List&lt;FederationSet&gt;</td></tr>\r
-<tr><td>LIST_SETTINGS</td><td>-</td><td><em>admin</em></td><td>-</td><td>Properties</td></tr>\r
+<tr><td>LIST_SETTINGS</td><td>-</td><td><em>admin</em></td><td>-</td><td>Map&lt;String, SettingModel&gt;</td></tr>\r
 </table>\r
 \r
-### RPC Response Codes\r
+### RPC/HTTP Response Codes\r
 <table>\r
 <tr><th>code</th><th>name</th><th>description</th></tr>\r
 <tr><td>200</td><td>success</td><td>Gitblit processed the request successfully</td></tr>\r
@@ -47,7 +47,7 @@ The Gitblit RPC mechanism, like the Gitblit JGit servlet, syndication/feed servl
 ### Gitblit Manager\r
 \r
 [Gitblit Manager](http://code.google.com/p/gitblit/downloads/detail?name=%MANAGER%) is an example Java/Swing application that allows remote administration of a Gitblit server.  \r
-This application exercises most methods from the utility class `com.gitblit.utils.RpcUtils`.\r
+This application exercises many, but not all, methods from the utility class `com.gitblit.utils.RpcUtils`.\r
 \r
 ### EGit "Import from Gitblit" Feature (Planning)\r
 \r
@@ -153,4 +153,32 @@ The original repository name is specified in the *name* url parameter.  The new
     ]\r
   }\r
 ]\r
+</pre>\r
+\r
+### Example: LIST_SETTINGS\r
+**url**: https://localhost/rpc?req=LIST_SETTINGS  \r
+**response body**: Map&lt;String, SettingModel&gt;\r
+<pre>\r
+{\r
+  "web.siteName": {\r
+    "name": "web.siteName",\r
+    "currentValue": "",\r
+    "defaultValue": "",\r
+    "description": "Gitblit Web Settings\nIf blank Gitblit is displayed.",\r
+    "since": "0.5.0",\r
+    "caseSensitive": false,\r
+    "restartRequired": false,\r
+    "spaceDelimited": false\r
+  },\r
+  "web.summaryCommitCount": {\r
+    "name": "web.summaryCommitCount",\r
+    "currentValue": "16",\r
+    "defaultValue": "16",\r
+    "description": "The number of commits to display on the summary page\nValue must exceed 0 else default of 16 is used",\r
+    "since": "0.5.0",\r
+    "caseSensitive": false,\r
+    "restartRequired": false,\r
+    "spaceDelimited": false\r
+  }\r
+}\r
 </pre>
\ No newline at end of file
index d6495e6fb35359a6ab6d5de2b93528e10ee1b076..f3ff6c446a10999f19bfab25b43978f4c225f3cc 100644 (file)
@@ -204,7 +204,8 @@ public class Constants {
                LIST_REPOSITORIES, CREATE_REPOSITORY, EDIT_REPOSITORY, DELETE_REPOSITORY,\r
                LIST_USERS, CREATE_USER, EDIT_USER, DELETE_USER, LIST_REPOSITORY_MEMBERS,\r
                SET_REPOSITORY_MEMBERS, LIST_FEDERATION_REGISTRATIONS, LIST_FEDERATION_RESULTS,\r
-               LIST_FEDERATION_PROPOSALS, LIST_FEDERATION_SETS, LIST_SETTINGS;\r
+               LIST_FEDERATION_PROPOSALS, LIST_FEDERATION_SETS, LIST_SETTINGS,\r
+               LIST_SERVER_STATUS;\r
 \r
                public static RpcRequest fromName(String name) {\r
                        for (RpcRequest type : values()) {\r
index 51d5612e317bfa824c8732a7e531b43db12b3bc8..238c01f7faefc9f2a26b84ebb5e82ea94176b5d4 100644 (file)
  */\r
 package com.gitblit;\r
 \r
+import java.io.BufferedReader;\r
 import java.io.File;\r
 import java.io.FileFilter;\r
 import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.io.InputStreamReader;\r
 import java.lang.reflect.Field;\r
 import java.text.MessageFormat;\r
 import java.util.ArrayList;\r
@@ -27,6 +30,7 @@ import java.util.HashMap;
 import java.util.List;\r
 import java.util.Map;\r
 import java.util.Map.Entry;\r
+import java.util.TreeMap;\r
 import java.util.concurrent.ConcurrentHashMap;\r
 import java.util.concurrent.Executors;\r
 import java.util.concurrent.ScheduledExecutorService;\r
@@ -35,6 +39,7 @@ import java.util.concurrent.atomic.AtomicInteger;
 \r
 import javax.mail.Message;\r
 import javax.mail.MessagingException;\r
+import javax.servlet.ServletContext;\r
 import javax.servlet.ServletContextEvent;\r
 import javax.servlet.ServletContextListener;\r
 import javax.servlet.http.Cookie;\r
@@ -63,6 +68,8 @@ import com.gitblit.models.FederationSet;
 import com.gitblit.models.Metric;\r
 import com.gitblit.models.ObjectCache;\r
 import com.gitblit.models.RepositoryModel;\r
+import com.gitblit.models.ServerStatus;\r
+import com.gitblit.models.SettingModel;\r
 import com.gitblit.models.UserModel;\r
 import com.gitblit.utils.ByteFormat;\r
 import com.gitblit.utils.FederationUtils;\r
@@ -106,6 +113,8 @@ public class GitBlit implements ServletContextListener {
 \r
        private RepositoryResolver<Void> repositoryResolver;\r
 \r
+       private ServletContext servletContext;\r
+\r
        private File repositoriesFolder;\r
 \r
        private boolean exportAll = true;\r
@@ -114,6 +123,10 @@ public class GitBlit implements ServletContextListener {
 \r
        private IStoredSettings settings;\r
 \r
+       private Map<String, SettingModel> settingModels;\r
+\r
+       private ServerStatus serverStatus;\r
+\r
        private MailExecutor mailExecutor;\r
 \r
        public GitBlit() {\r
@@ -233,6 +246,13 @@ public class GitBlit implements ServletContextListener {
                return self().settings.getBoolean(Keys.web.debugMode, false);\r
        }\r
 \r
+       public ServerStatus getStatus() {\r
+               // update heap memory status\r
+               serverStatus.heapAllocated = Runtime.getRuntime().totalMemory();\r
+               serverStatus.heapFree = Runtime.getRuntime().freeMemory();\r
+               return serverStatus;\r
+       }\r
+\r
        /**\r
         * Returns the list of non-Gitblit clone urls. This allows Gitblit to\r
         * advertise alternative urls for Git client repository access.\r
@@ -1252,6 +1272,86 @@ public class GitBlit implements ServletContextListener {
                }\r
        }\r
 \r
+       /**\r
+        * Returns the descriptions/comments of the Gitblit config settings.\r
+        * \r
+        * @return Map<String, SettingModel>\r
+        */\r
+       public Map<String, SettingModel> getSettingModels() {\r
+               // ensure that the current values are updated in the setting models\r
+               for (String key : settings.getAllKeys(null)) {\r
+                       if (settingModels.containsKey(key)) {\r
+                               settingModels.get(key).currentValue = settings.getString(key, "");\r
+                       }\r
+               }\r
+               return settingModels;\r
+       }\r
+\r
+       /**\r
+        * Parse the properties file and aggregate all the comments by the setting\r
+        * key. A setting model tracks the current value, the default value, the\r
+        * description of the setting and and directives about the setting.\r
+        * \r
+        * @return Map<String, SettingModel>\r
+        */\r
+       private Map<String, SettingModel> loadSettingModels() {\r
+               Map<String, SettingModel> map = new TreeMap<String, SettingModel>();\r
+               try {\r
+                       // Read bundled Gitblit properties to extract setting descriptions.\r
+                       // This copy is pristine and only used for populating the setting\r
+                       // models map.\r
+                       InputStream is = servletContext.getResourceAsStream("/WEB-INF/gitblit.properties");\r
+                       BufferedReader propertiesReader = new BufferedReader(new InputStreamReader(is));\r
+                       StringBuilder description = new StringBuilder();\r
+                       SettingModel setting = new SettingModel();\r
+                       String line = null;\r
+                       while ((line = propertiesReader.readLine()) != null) {\r
+                               if (line.length() == 0) {\r
+                                       description.setLength(0);\r
+                                       setting = new SettingModel();\r
+                               } else {\r
+                                       if (line.charAt(0) == '#') {\r
+                                               if (line.length() > 1) {\r
+                                                       String text = line.substring(1).trim();\r
+                                                       if (SettingModel.CASE_SENSITIVE.equals(text)) {\r
+                                                               setting.caseSensitive = true;\r
+                                                       } else if (SettingModel.RESTART_REQUIRED.equals(text)) {\r
+                                                               setting.restartRequired = true;\r
+                                                       } else if (SettingModel.SPACE_DELIMITED.equals(text)) {\r
+                                                               setting.spaceDelimited = true;\r
+                                                       } else if (text.startsWith(SettingModel.SINCE)) {\r
+                                                               try {\r
+                                                                       setting.since = text.split(" ")[1];\r
+                                                               } catch (Exception e) {\r
+                                                                       setting.since = text;\r
+                                                               }\r
+                                                       } else {\r
+                                                               description.append(text);\r
+                                                               description.append('\n');\r
+                                                       }\r
+                                               }\r
+                                       } else {\r
+                                               String[] kvp = line.split("=", 2);\r
+                                               String key = kvp[0].trim();\r
+                                               setting.name = key;\r
+                                               setting.defaultValue = kvp[1].trim();\r
+                                               setting.currentValue = setting.defaultValue;\r
+                                               setting.description = description.toString().trim();\r
+                                               map.put(key, setting);\r
+                                               description.setLength(0);\r
+                                               setting = new SettingModel();\r
+                                       }\r
+                               }\r
+                       }\r
+                       propertiesReader.close();\r
+               } catch (NullPointerException e) {\r
+                       logger.error("Failed to find resource copy of gitblit.properties");\r
+               } catch (IOException e) {\r
+                       logger.error("Failed to load resource copy of gitblit.properties");\r
+               }\r
+               return map;\r
+       }\r
+\r
        /**\r
         * Configure the Gitblit singleton with the specified settings source. This\r
         * source may be file settings (Gitblit GO) or may be web.xml settings\r
@@ -1265,6 +1365,7 @@ public class GitBlit implements ServletContextListener {
                repositoriesFolder = new File(settings.getString(Keys.git.repositoriesFolder, "git"));\r
                logger.info("Git repositories folder " + repositoriesFolder.getAbsolutePath());\r
                repositoryResolver = new FileResolver<Void>(repositoriesFolder, exportAll);\r
+               serverStatus = new ServerStatus();\r
                String realm = settings.getString(Keys.realm.userService, "users.properties");\r
                IUserService loginService = null;\r
                try {\r
@@ -1307,6 +1408,8 @@ public class GitBlit implements ServletContextListener {
         */\r
        @Override\r
        public void contextInitialized(ServletContextEvent contextEvent) {\r
+               servletContext = contextEvent.getServletContext();\r
+               settingModels = loadSettingModels();\r
                if (settings == null) {\r
                        // Gitblit WAR is running in a servlet container\r
                        WebXmlSettings webxmlSettings = new WebXmlSettings(contextEvent.getServletContext());\r
index 53426dadb527245bfa137a8bda11e3575537d89c..6a8c2c5977c22b1f098bd3d3f4bb326fc6be5ae7 100644 (file)
@@ -22,7 +22,6 @@ import java.util.Collection;
 import java.util.HashMap;\r
 import java.util.List;\r
 import java.util.Map;\r
-import java.util.Properties;\r
 \r
 import javax.servlet.ServletException;\r
 import javax.servlet.http.HttpServletRequest;\r
@@ -183,15 +182,10 @@ public class RpcServlet extends JsonServlet {
                        }\r
                } else if (RpcRequest.LIST_SETTINGS.equals(reqType)) {\r
                        // return the server's settings\r
-                       Properties settings = new Properties();\r
-                       List<String> keys = GitBlit.getAllKeys(null);\r
-                       for (String key : keys) {\r
-                               String value = GitBlit.getString(key, null);\r
-                               if (value != null) {\r
-                                       settings.put(key, value);\r
-                               }\r
-                       }\r
-                       result = settings;\r
+                       result = GitBlit.self().getSettingModels();\r
+               } else if (RpcRequest.LIST_SERVER_STATUS.equals(reqType)) {\r
+                       // return the server's status information\r
+                       result = GitBlit.self().getStatus();\r
                }\r
 \r
                // send the result of the request\r
index eacef2491703f9f711c6673e66cd7343471ec2a1..0a1ddd93f22a071dadf580276c8ff09f78e84ebd 100644 (file)
@@ -29,6 +29,7 @@ import java.util.ArrayList;
 import java.util.Arrays;\r
 import java.util.HashSet;\r
 import java.util.List;\r
+import java.util.Map;\r
 import java.util.Set;\r
 \r
 import javax.swing.ImageIcon;\r
@@ -45,9 +46,9 @@ import javax.swing.JTextField;
 import javax.swing.KeyStroke;\r
 \r
 import com.gitblit.Constants.AccessRestrictionType;\r
-import com.gitblit.IStoredSettings;\r
 import com.gitblit.Keys;\r
 import com.gitblit.models.RepositoryModel;\r
+import com.gitblit.models.SettingModel;\r
 import com.gitblit.models.UserModel;\r
 import com.gitblit.utils.StringUtils;\r
 \r
@@ -57,7 +58,7 @@ public class EditUserDialog extends JDialog {
 \r
        private final UserModel user;\r
 \r
-       private final IStoredSettings settings;\r
+       private final Map<String, SettingModel> settings;\r
 \r
        private boolean isCreate;\r
        \r
@@ -77,13 +78,13 @@ public class EditUserDialog extends JDialog {
 \r
        private Set<String> usernames;\r
 \r
-       public EditUserDialog(IStoredSettings settings) {\r
+       public EditUserDialog(Map<String, SettingModel> settings) {\r
                this(new UserModel(""), settings);\r
                this.isCreate = true;\r
                setTitle(Translation.get("gb.newUser"));                \r
        }\r
 \r
-       public EditUserDialog(UserModel anUser, IStoredSettings settings) {\r
+       public EditUserDialog(UserModel anUser, Map<String, SettingModel> settings) {\r
                super();\r
                this.user = new UserModel("");\r
                this.settings = settings;\r
@@ -196,7 +197,7 @@ public class EditUserDialog extends JDialog {
                        }\r
                }\r
 \r
-               int minLength = settings.getInteger(Keys.realm.minPasswordLength, 5);\r
+               int minLength = settings.get(Keys.realm.minPasswordLength).getInteger(5);\r
                if (minLength < 4) {\r
                        minLength = 4;\r
                }\r
@@ -216,7 +217,7 @@ public class EditUserDialog extends JDialog {
                        return false;\r
                }\r
                user.username = uname;\r
-               String type = settings.getString(Keys.realm.passwordStorage, "md5");\r
+               String type = settings.get(Keys.realm.passwordStorage).getString("md5");\r
                if (type.equalsIgnoreCase("md5")) {\r
                        // store MD5 digest of password\r
                        user.password = StringUtils.MD5_TYPE + StringUtils.getMD5(new String(pw));\r
index 22d67f62e21d3e063cb85a2998f3e08c794dbdd3..55e74b9c16e3c6b2b496749f925eecf3d5a0501d 100644 (file)
@@ -24,10 +24,11 @@ import java.util.Map;
 \r
 import com.gitblit.GitBlitException.ForbiddenException;\r
 import com.gitblit.GitBlitException.UnauthorizedException;\r
-import com.gitblit.IStoredSettings;\r
 import com.gitblit.Keys;\r
 import com.gitblit.models.FederationModel;\r
 import com.gitblit.models.RepositoryModel;\r
+import com.gitblit.models.ServerStatus;\r
+import com.gitblit.models.SettingModel;\r
 import com.gitblit.models.UserModel;\r
 import com.gitblit.utils.RpcUtils;\r
 \r
@@ -43,7 +44,7 @@ public class GitblitModel implements Serializable {
 \r
        private volatile boolean isAdmin;\r
 \r
-       private volatile IStoredSettings settings;\r
+       private volatile Map<String, SettingModel> settings;\r
 \r
        private final List<RepositoryModel> allRepositories;\r
 \r
@@ -51,6 +52,8 @@ public class GitblitModel implements Serializable {
 \r
        private final List<FederationModel> federationRegistrations;\r
 \r
+       private ServerStatus status;\r
+\r
        public GitblitModel(String url, String account, char[] password) {\r
                this.url = url;\r
                this.account = account;\r
@@ -66,8 +69,8 @@ public class GitblitModel implements Serializable {
 \r
                try {\r
                        settings = RpcUtils.getSettings(url, account, password);\r
+                       status = RpcUtils.getStatus(url, account, password);\r
                        refreshUsers();\r
-                       refreshFederationRegistrations();\r
                        isAdmin = true;\r
                } catch (UnauthorizedException e) {\r
                } catch (ForbiddenException e) {\r
@@ -84,10 +87,14 @@ public class GitblitModel implements Serializable {
                return account != null && account.equalsIgnoreCase(model.owner);\r
        }\r
 \r
-       public IStoredSettings getSettings() {\r
+       public Map<String, SettingModel> getSettings() {\r
                return settings;\r
        }\r
 \r
+       public String getSettingDescription(String key) {\r
+               return settings.get(key).description;\r
+       }\r
+\r
        public List<RepositoryModel> refreshRepositories() throws IOException {\r
                Map<String, RepositoryModel> repositories = RpcUtils\r
                                .getRepositories(url, account, password);\r
@@ -135,7 +142,7 @@ public class GitblitModel implements Serializable {
        }\r
 \r
        public List<String> getFederationSets() {\r
-               return settings.getStrings(Keys.federation.sets);\r
+               return settings.get(Keys.federation.sets).getStrings();\r
        }\r
 \r
        public List<RepositoryModel> getRepositories() {\r
index f0d04b731272af70f998c5c539b6dabe2ca88872..8635b0069cce1d8ced8ed1a95f3057747ad8845d 100644 (file)
@@ -52,6 +52,7 @@ import javax.swing.table.TableRowSorter;
 import com.gitblit.Constants.RpcRequest;\r
 import com.gitblit.client.ClosableTabComponent.CloseTabListener;\r
 import com.gitblit.models.RepositoryModel;\r
+import com.gitblit.models.SettingModel;\r
 import com.gitblit.models.UserModel;\r
 import com.gitblit.utils.StringUtils;\r
 \r
@@ -116,7 +117,6 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
                tabs = new JTabbedPane(JTabbedPane.BOTTOM);\r
                tabs.addTab(Translation.get("gb.repositories"), createRepositoriesPanel());\r
                tabs.addTab(Translation.get("gb.users"), createUsersPanel());\r
-               tabs.addTab(Translation.get("gb.federation"), new JPanel());\r
                tabs.addTab(Translation.get("gb.settings"), createSettingsPanel());\r
 \r
                setLayout(new BorderLayout());\r
@@ -380,9 +380,11 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
        }\r
 \r
        private JPanel createSettingsPanel() {\r
+               final SettingPanel settingPanel = new SettingPanel();\r
                settingsModel = new SettingsModel();\r
                defaultSettingsSorter = new TableRowSorter<SettingsModel>(settingsModel);\r
                settingsTable = Utils.newTable(settingsModel);\r
+               settingsTable.setDefaultRenderer(SettingModel.class, new SettingCellRenderer());\r
                String name = settingsTable.getColumnName(UsersModel.Columns.Name.ordinal());\r
                settingsTable.setRowHeight(nameRenderer.getFont().getSize() + 8);\r
                settingsTable.getColumn(name).setCellRenderer(nameRenderer);\r
@@ -398,6 +400,14 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
                                boolean selected = settingsTable.getSelectedRow() > -1;\r
                                boolean singleSelection = settingsTable.getSelectedRows().length == 1;\r
                                // TODO enable/disable setting buttons\r
+                               if (singleSelection) {\r
+                                       int viewRow = settingsTable.getSelectedRow();\r
+                                       int modelRow = settingsTable.convertRowIndexToModel(viewRow);\r
+                                       SettingModel setting = settingsModel.get(modelRow);\r
+                                       settingPanel.setSetting(setting);\r
+                               } else {\r
+                                       settingPanel.clear();\r
+                               }\r
                        }\r
                });\r
 \r
@@ -420,6 +430,7 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
                JPanel settingsTablePanel = new JPanel(new BorderLayout(margin, margin));\r
                settingsTablePanel.add(settingFilterPanel, BorderLayout.NORTH);\r
                settingsTablePanel.add(new JScrollPane(settingsTable), BorderLayout.CENTER);\r
+               settingsTablePanel.add(settingPanel, BorderLayout.SOUTH);\r
 \r
                JPanel settingsControls = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0));\r
                // TODO update setting?\r
diff --git a/src/com/gitblit/client/SettingCellRenderer.java b/src/com/gitblit/client/SettingCellRenderer.java
new file mode 100644 (file)
index 0000000..d164fb1
--- /dev/null
@@ -0,0 +1,67 @@
+/*\r
+ * Copyright 2011 gitblit.com.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package com.gitblit.client;\r
+\r
+import java.awt.Color;\r
+import java.awt.Component;\r
+import java.awt.Font;\r
+\r
+import javax.swing.JTable;\r
+import javax.swing.table.DefaultTableCellRenderer;\r
+\r
+import com.gitblit.models.SettingModel;\r
+\r
+/**\r
+ * SettingModel cell renderer that indicates if a setting is the default or\r
+ * modified.\r
+ * \r
+ * @author James Moger\r
+ * \r
+ */\r
+public class SettingCellRenderer extends DefaultTableCellRenderer {\r
+\r
+       private static final long serialVersionUID = 1L;\r
+\r
+       private final Font defaultFont;\r
+\r
+       private final Font modifiedFont;\r
+\r
+       public SettingCellRenderer() {\r
+               defaultFont = getFont();\r
+               modifiedFont = defaultFont.deriveFont(Font.BOLD);\r
+       }\r
+\r
+       public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,\r
+                       boolean hasFocus, int row, int column) {\r
+               super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);\r
+               if (value instanceof SettingModel) {\r
+                       SettingModel setting = (SettingModel) value;\r
+                       if (setting.isDefaultValue()) {\r
+                               this.setFont(defaultFont);\r
+                               if (!isSelected) {\r
+                                       this.setForeground(Color.BLACK);\r
+                               }\r
+                       } else {\r
+                               this.setFont(modifiedFont);\r
+                               if (!isSelected) {\r
+                                       this.setForeground(Color.BLUE);\r
+                               }\r
+                       }\r
+                       this.setText(setting.getString(""));\r
+               }\r
+               return this;\r
+       }\r
+}
\ No newline at end of file
diff --git a/src/com/gitblit/client/SettingPanel.java b/src/com/gitblit/client/SettingPanel.java
new file mode 100644 (file)
index 0000000..8d07dc8
--- /dev/null
@@ -0,0 +1,114 @@
+/*\r
+ * Copyright 2011 gitblit.com.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package com.gitblit.client;\r
+\r
+import java.awt.BorderLayout;\r
+import java.awt.Color;\r
+import java.awt.Font;\r
+import java.awt.GridLayout;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import javax.swing.JLabel;\r
+import javax.swing.JPanel;\r
+import javax.swing.JScrollPane;\r
+import javax.swing.JTextArea;\r
+import javax.swing.SwingConstants;\r
+\r
+import com.gitblit.models.SettingModel;\r
+import com.gitblit.utils.StringUtils;\r
+\r
+/**\r
+ * This panel displays the metadata for a particular setting.\r
+ * \r
+ * @author James Moger\r
+ */\r
+public class SettingPanel extends JPanel {\r
+\r
+       private static final long serialVersionUID = 1L;\r
+       private JTextArea descriptionArea;\r
+       private JLabel settingName;\r
+       private JLabel settingDefault;\r
+       private JLabel sinceVersion;\r
+       private JLabel directives;\r
+\r
+       public SettingPanel() {\r
+               super();\r
+               initialize();\r
+       }\r
+\r
+       private void initialize() {\r
+               descriptionArea = new JTextArea();\r
+               descriptionArea.setRows(6);\r
+               descriptionArea.setFont(new Font("monospaced", Font.PLAIN, 11));\r
+\r
+               settingName = new JLabel(" ");\r
+               settingName.setFont(settingName.getFont().deriveFont(Font.BOLD));\r
+\r
+               settingDefault = new JLabel(" ");\r
+\r
+               sinceVersion = new JLabel(" ", SwingConstants.RIGHT);\r
+               sinceVersion.setForeground(new Color(0, 0x80, 0));\r
+\r
+               directives = new JLabel(" ", SwingConstants.RIGHT);\r
+               directives.setFont(directives.getFont().deriveFont(Font.ITALIC));\r
+\r
+               JPanel settingParameters = new JPanel(new GridLayout(2, 2, 0, 0));\r
+               settingParameters.add(settingName);\r
+               settingParameters.add(sinceVersion);\r
+               settingParameters.add(settingDefault, BorderLayout.CENTER);\r
+               settingParameters.add(directives);\r
+\r
+               JPanel settingPanel = new JPanel(new BorderLayout(5, 5));\r
+               settingPanel.add(settingParameters, BorderLayout.NORTH);\r
+               settingPanel.add(new JScrollPane(descriptionArea), BorderLayout.CENTER);\r
+               setLayout(new BorderLayout(0, 0));\r
+               add(settingPanel, BorderLayout.CENTER);\r
+       }\r
+\r
+       public void setSetting(SettingModel setting) {\r
+               settingName.setText(setting.name);\r
+               if (setting.since == null) {\r
+                       sinceVersion.setText("custom");\r
+               } else {                        \r
+                       sinceVersion.setText("since " + setting.since);\r
+               }\r
+               settingDefault.setText("default: " + setting.defaultValue);\r
+\r
+               List<String> values = new ArrayList<String>();\r
+               if (setting.caseSensitive) {\r
+                       values.add("CASE-SENSITIVE");\r
+               }\r
+               if (setting.spaceDelimited) {\r
+                       values.add("SPACE-DELIMITED");\r
+               }\r
+               if (setting.restartRequired) {\r
+                       values.add("RESTART REQUIRED");\r
+               }\r
+               directives.setText(StringUtils.flattenStrings(values, ", "));\r
+\r
+               descriptionArea.setText(setting.description);\r
+               descriptionArea.setCaretPosition(0);\r
+       }\r
+\r
+       public void clear() {\r
+               settingName.setText(" ");\r
+               settingDefault.setText(" ");\r
+               sinceVersion.setText(" ");\r
+               directives.setText(" ");\r
+               descriptionArea.setText("");\r
+       }\r
+}\r
index 2c7bff8de75128b58a53d2400e19abe72af129fa..af3c1b60935d9b6591806f07f047082aa5148f63 100644 (file)
@@ -18,13 +18,14 @@ package com.gitblit.client;
 import java.util.ArrayList;\r
 import java.util.Collections;\r
 import java.util.List;\r
+import java.util.Map;\r
 \r
 import javax.swing.table.AbstractTableModel;\r
 \r
-import com.gitblit.IStoredSettings;\r
+import com.gitblit.models.SettingModel;\r
 \r
 /**\r
- * Table model of IStoredSettings.\r
+ * Table model of Map<String, SettingModel>.\r
  * \r
  * @author James Moger\r
  * \r
@@ -33,7 +34,7 @@ public class SettingsModel extends AbstractTableModel {
 \r
        private static final long serialVersionUID = 1L;\r
 \r
-       IStoredSettings settings;\r
+       Map<String, SettingModel> settings;\r
 \r
        List<String> keys;\r
 \r
@@ -50,16 +51,16 @@ public class SettingsModel extends AbstractTableModel {
                this(null);\r
        }\r
 \r
-       public SettingsModel(IStoredSettings settings) {\r
+       public SettingsModel(Map<String, SettingModel> settings) {\r
                setSettings(settings);\r
        }\r
 \r
-       public void setSettings(IStoredSettings settings) {\r
+       public void setSettings(Map<String, SettingModel> settings) {\r
                this.settings = settings;\r
                if (settings == null) {\r
                        keys = new ArrayList<String>();\r
                } else {\r
-                       keys = new ArrayList<String>(settings.getAllKeys(null));\r
+                       keys = new ArrayList<String>(settings.keySet());\r
                        Collections.sort(keys);\r
                }\r
        }\r
@@ -92,19 +93,28 @@ public class SettingsModel extends AbstractTableModel {
         * @return the Object.class\r
         */\r
        public Class<?> getColumnClass(int columnIndex) {\r
+               if (Columns.Value.ordinal() == columnIndex) {\r
+                       return SettingModel.class;\r
+               }\r
                return String.class;\r
        }\r
 \r
        @Override\r
        public Object getValueAt(int rowIndex, int columnIndex) {\r
                String key = keys.get(rowIndex);\r
+               SettingModel setting = settings.get(key);\r
                Columns col = Columns.values()[columnIndex];\r
                switch (col) {\r
                case Name:\r
                        return key;\r
                case Value:\r
-                       return settings.getString(key, "");\r
+                       return setting;\r
                }\r
                return null;\r
        }\r
+\r
+       public SettingModel get(int modelRow) {\r
+               String key = keys.get(modelRow);\r
+               return settings.get(key);\r
+       }\r
 }\r
diff --git a/src/com/gitblit/models/ServerStatus.java b/src/com/gitblit/models/ServerStatus.java
new file mode 100644 (file)
index 0000000..b1dc52d
--- /dev/null
@@ -0,0 +1,69 @@
+/*\r
+ * Copyright 2011 gitblit.com.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package com.gitblit.models;\r
+\r
+import java.io.Serializable;\r
+import java.util.Date;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+/**\r
+ * ServerStatus encapsulates runtime status information about the server\r
+ * including the system environment.\r
+ * \r
+ * @author James Moger\r
+ * \r
+ */\r
+public class ServerStatus implements Serializable {\r
+\r
+       private static final long serialVersionUID = 1L;\r
+\r
+       public final Date bootDate;\r
+       \r
+       public final long heapSize;\r
+\r
+       public final Map<String, String> systemProperties;\r
+       \r
+       public volatile long heapAllocated;\r
+       \r
+       public volatile long heapFree;\r
+\r
+       public ServerStatus() {\r
+               bootDate = new Date();\r
+               \r
+               heapSize = Runtime.getRuntime().maxMemory();\r
+               \r
+               systemProperties = new HashMap<String, String>();\r
+               put("file.encoding");\r
+               put("java.home");\r
+               put("java.io.tmpdir");\r
+               put("java.runtime.name");\r
+               put("java.runtime.version");\r
+               put("java.vendor");\r
+               put("java.version");\r
+               put("java.vm.info");\r
+               put("java.vm.name");\r
+               put("java.vm.vendor");\r
+               put("java.vm.version");\r
+               put("os.arch");\r
+               put("os.name");\r
+               put("os.version");\r
+       }\r
+\r
+       private void put(String key) {\r
+               systemProperties.put(key, System.getProperty(key));\r
+       }\r
+}\r
diff --git a/src/com/gitblit/models/SettingModel.java b/src/com/gitblit/models/SettingModel.java
new file mode 100644 (file)
index 0000000..8a5c0c6
--- /dev/null
@@ -0,0 +1,144 @@
+/*\r
+ * Copyright 2011 gitblit.com.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package com.gitblit.models;\r
+\r
+import java.io.Serializable;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import com.gitblit.utils.StringUtils;\r
+\r
+/**\r
+ * SettingModel represents a setting and all its metadata: name, current value,\r
+ * default value, description, and directives.\r
+ * \r
+ * @author James Moger\r
+ */\r
+public class SettingModel implements Serializable {\r
+\r
+       public static final String SPACE_DELIMITED = "SPACE-DELIMITED";\r
+\r
+       public static final String CASE_SENSITIVE = "CASE-SENSITIVE";\r
+\r
+       public static final String RESTART_REQUIRED = "RESTART REQUIRED";\r
+\r
+       public static final String SINCE = "SINCE";\r
+\r
+       public String name;\r
+       public volatile String currentValue;\r
+       public String defaultValue;\r
+       public String description;\r
+       public String since;\r
+       public boolean caseSensitive;\r
+       public boolean restartRequired;\r
+       public boolean spaceDelimited;\r
+\r
+       private static final long serialVersionUID = 1L;\r
+\r
+       public SettingModel() {\r
+       }\r
+\r
+       /**\r
+        * Returns true if the current value is the default value.\r
+        * \r
+        * @return true if current value is the default value\r
+        */\r
+       public boolean isDefaultValue() {\r
+               return (currentValue != null && currentValue.equals(defaultValue))\r
+                               || currentValue.trim().length() == 0;\r
+       }\r
+\r
+       /**\r
+        * Returns the boolean value for the currentValue. If the currentValue can\r
+        * not be interpreted as a boolean, the defaultValue is returned.\r
+        * \r
+        * @param defaultValue\r
+        * @return key value or defaultValue\r
+        */\r
+       public boolean getBoolean(boolean defaultValue) {\r
+               if (!StringUtils.isEmpty(currentValue)) {\r
+                       return Boolean.parseBoolean(currentValue.trim());\r
+               }\r
+               return defaultValue;\r
+       }\r
+\r
+       /**\r
+        * Returns the integer value for the currentValue. If the currentValue can\r
+        * not be interpreted as an integer, the defaultValue is returned.\r
+        * \r
+        * @param defaultValue\r
+        * @return key value or defaultValue\r
+        */\r
+       public int getInteger(int defaultValue) {\r
+               try {\r
+                       if (!StringUtils.isEmpty(currentValue)) {\r
+                               return Integer.parseInt(currentValue.trim());\r
+                       }\r
+               } catch (NumberFormatException e) {\r
+               }\r
+               return defaultValue;\r
+       }\r
+\r
+       /**\r
+        * Returns the char value for currentValue. If the currentValue can not be\r
+        * interpreted as a char, the defaultValue is returned.\r
+        * \r
+        * @param defaultValue\r
+        * @return key value or defaultValue\r
+        */\r
+       public char getChar(char defaultValue) {\r
+               if (!StringUtils.isEmpty(currentValue)) {\r
+                       return currentValue.trim().charAt(0);\r
+               }\r
+               return defaultValue;\r
+       }\r
+\r
+       /**\r
+        * Returns the string value for currentValue. If the currentValue is null,\r
+        * the defaultValue is returned.\r
+        * \r
+        * @param defaultValue\r
+        * @return key value or defaultValue\r
+        */\r
+       public String getString(String defaultValue) {\r
+               if (currentValue != null) {\r
+                       return currentValue.trim();\r
+               }\r
+               return defaultValue;\r
+       }\r
+\r
+       /**\r
+        * Returns a list of space-separated strings from the specified key.\r
+        * \r
+        * @return list of strings\r
+        */\r
+       public List<String> getStrings() {\r
+               return getStrings(" ");\r
+       }\r
+\r
+       /**\r
+        * Returns a list of strings from the currentValue using the specified\r
+        * string separator.\r
+        * \r
+        * @param separator\r
+        * @return list of strings\r
+        */\r
+       public List<String> getStrings(String separator) {\r
+               List<String> strings = new ArrayList<String>();\r
+               strings = StringUtils.getStringsFromValue(currentValue, separator);\r
+               return strings;\r
+       }\r
+}\r
index eb28c0f943532e8928b2a93d2d94b77e713a0788..440dabdb88dbb11a91ddfe515c17eda67b94bf0d 100644 (file)
@@ -21,15 +21,15 @@ import java.util.ArrayList;
 import java.util.Collection;\r
 import java.util.List;\r
 import java.util.Map;\r
-import java.util.Properties;\r
 \r
 import com.gitblit.Constants;\r
 import com.gitblit.Constants.RpcRequest;\r
-import com.gitblit.IStoredSettings;\r
 import com.gitblit.models.FederationModel;\r
 import com.gitblit.models.FederationProposal;\r
 import com.gitblit.models.FederationSet;\r
 import com.gitblit.models.RepositoryModel;\r
+import com.gitblit.models.ServerStatus;\r
+import com.gitblit.models.SettingModel;\r
 import com.gitblit.models.UserModel;\r
 import com.google.gson.reflect.TypeToken;\r
 \r
@@ -59,6 +59,9 @@ public class RpcUtils {
        private static final Type SETS_TYPE = new TypeToken<Collection<FederationSet>>() {\r
        }.getType();\r
 \r
+       private static final Type SETTINGS_TYPE = new TypeToken<Map<String, SettingModel>>() {\r
+       }.getType();\r
+\r
        /**\r
         * \r
         * @param remoteURL\r
@@ -338,17 +341,33 @@ public class RpcUtils {
         * @param serverUrl\r
         * @param account\r
         * @param password\r
-        * @return an IStoredSettings object\r
+        * @return an Map<String, SettingModel> object\r
         * @throws IOException\r
         */\r
-       public static IStoredSettings getSettings(String serverUrl, String account, char[] password)\r
-                       throws IOException {\r
+       public static Map<String, SettingModel> getSettings(String serverUrl, String account,\r
+                       char[] password) throws IOException {\r
                String url = asLink(serverUrl, RpcRequest.LIST_SETTINGS);\r
-               Properties props = JsonUtils.retrieveJson(url, Properties.class, account, password);\r
-               RpcSettings settings = new RpcSettings(props);\r
+               Map<String, SettingModel> settings = JsonUtils.retrieveJson(url, SETTINGS_TYPE, account,\r
+                               password);\r
                return settings;\r
        }\r
 \r
+       /**\r
+        * Retrieves the server status object.\r
+        * \r
+        * @param serverUrl\r
+        * @param account\r
+        * @param password\r
+        * @return an ServerStatus object\r
+        * @throws IOException\r
+        */\r
+       public static ServerStatus getStatus(String serverUrl, String account, char[] password)\r
+                       throws IOException {\r
+               String url = asLink(serverUrl, RpcRequest.LIST_SERVER_STATUS);\r
+               ServerStatus status = JsonUtils.retrieveJson(url, ServerStatus.class, account, password);\r
+               return status;\r
+       }\r
+\r
        /**\r
         * Do the specified administrative action on the Gitblit server.\r
         * \r
@@ -369,31 +388,4 @@ public class RpcUtils {
                int resultCode = JsonUtils.sendJsonString(url, json, account, password);\r
                return resultCode == 200;\r
        }\r
-       \r
-       /**\r
-        * Settings implementation that wraps a retrieved properties instance. This\r
-        * class is used for RPC communication.\r
-        * \r
-        * @author James Moger\r
-        * \r
-        */\r
-       private static class RpcSettings extends IStoredSettings {\r
-               \r
-               private final Properties properties = new Properties();\r
-\r
-               public RpcSettings(Properties props) {\r
-                       super(RpcSettings.class);\r
-                       properties.putAll(props);\r
-               }\r
-\r
-               @Override\r
-               protected Properties read() {\r
-                       return properties;\r
-               }\r
-\r
-               @Override\r
-               public String toString() {\r
-                       return "RpcSettings";\r
-               }\r
-       }\r
 }\r
index 450b5978a22c4fff56c533cd51feb3dfcd369e55..3c2f61f985bb7b4c5156d4a03b77fa7c94e0516f 100644 (file)
@@ -23,11 +23,12 @@ import junit.framework.TestCase;
 \r
 import com.gitblit.Constants.AccessRestrictionType;\r
 import com.gitblit.GitBlitException.UnauthorizedException;\r
-import com.gitblit.IStoredSettings;\r
 import com.gitblit.models.FederationModel;\r
 import com.gitblit.models.FederationProposal;\r
 import com.gitblit.models.FederationSet;\r
 import com.gitblit.models.RepositoryModel;\r
+import com.gitblit.models.ServerStatus;\r
+import com.gitblit.models.SettingModel;\r
 import com.gitblit.models.UserModel;\r
 import com.gitblit.utils.RpcUtils;\r
 \r
@@ -206,7 +207,12 @@ public class RpcTests extends TestCase {
        }\r
 \r
        public void testSettings() throws Exception {\r
-               IStoredSettings settings = RpcUtils.getSettings(url, account, password.toCharArray());\r
-               assertTrue("No settings were retrieved!", settings.getAllKeys(null).size() > 0);\r
+               Map<String, SettingModel> settings = RpcUtils.getSettings(url, account, password.toCharArray());\r
+               assertTrue("No settings were retrieved!", settings != null);\r
+       }\r
+       \r
+       public void testServerStatus() throws Exception {\r
+               ServerStatus status = RpcUtils.getStatus(url, account, password.toCharArray());\r
+               assertTrue("No status was retrieved!", status != null);\r
        }\r
 }\r