]> source.dussan.org Git - gitblit.git/commitdiff
RPC Client: Create/Edit Repository & User. Partially working.
authorJames Moger <james.moger@gitblit.com>
Thu, 13 Oct 2011 02:14:10 +0000 (22:14 -0400)
committerJames Moger <james.moger@gitblit.com>
Thu, 13 Oct 2011 02:14:10 +0000 (22:14 -0400)
Added new request type to retrieve Gitblit settings to implement the
password preferences (minLength, storage type) and federation sets.

14 files changed:
docs/02_rpc.mkd
src/com/gitblit/Constants.java
src/com/gitblit/RpcServlet.java
src/com/gitblit/client/EditRepositoryDialog.java [new file with mode: 0644]
src/com/gitblit/client/EditUserDialog.java [new file with mode: 0644]
src/com/gitblit/client/GitblitClient.java
src/com/gitblit/client/GitblitClientLauncher.java
src/com/gitblit/client/GitblitPanel.java
src/com/gitblit/client/JPalette.java [new file with mode: 0644]
src/com/gitblit/client/NameRenderer.java
src/com/gitblit/utils/JsonUtils.java
src/com/gitblit/utils/RpcUtils.java
src/com/gitblit/wicket/GitBlitWebApp.properties
tests/com/gitblit/tests/RpcTests.java

index c3c59e62a6a3555b2dd577e7fc4aeef141350949..4a547d00803c7007f76a563c3a586769fa496b31 100644 (file)
@@ -30,6 +30,7 @@ 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 FederationModel</td></tr>\r
 <tr><td>LIST_FEDERATION_PROPOSALS</td><td>-</td><td><em>admin</em></td><td>-</td><td>List FederationProposal </td></tr>\r
 <tr><td>LIST_FEDERATION_SETS</td><td>-</td><td><em>admin</em></td><td>-</td><td>List FederationSet </td></tr>\r
+<tr><td>LIST_SETTINGS</td><td>-</td><td><em>admin</em></td><td>-</td><td>Properties</td></tr>\r
 </table>\r
 \r
 ### RPC Client\r
index 52af3e916add9495bbfa0cbb0afbe37c0f4786d4..6300fa2ed8cb9f74bb459f1a5860f27d1b9b8e1b 100644 (file)
@@ -204,7 +204,7 @@ 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;\r
+               LIST_FEDERATION_PROPOSALS, LIST_FEDERATION_SETS, LIST_SETTINGS;\r
 \r
                public static RpcRequest fromName(String name) {\r
                        for (RpcRequest type : values()) {\r
index 4dee31901bf6e4fc87de1a1efe747d6355b4e5dc..de5d94e08d366763ec7d8ee2fa452fd8a58f7b7c 100644 (file)
@@ -22,6 +22,7 @@ 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
@@ -163,6 +164,17 @@ public class RpcServlet extends JsonServlet {
                        } else {\r
                                response.sendError(HttpServletResponse.SC_FORBIDDEN);\r
                        }\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
                }\r
 \r
                // send the result of the request\r
diff --git a/src/com/gitblit/client/EditRepositoryDialog.java b/src/com/gitblit/client/EditRepositoryDialog.java
new file mode 100644 (file)
index 0000000..756128a
--- /dev/null
@@ -0,0 +1,224 @@
+/*\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.Dimension;\r
+import java.awt.FlowLayout;\r
+import java.awt.Font;\r
+import java.awt.GridLayout;\r
+import java.awt.Insets;\r
+import java.awt.event.ActionEvent;\r
+import java.awt.event.ActionListener;\r
+import java.util.List;\r
+\r
+import javax.swing.ImageIcon;\r
+import javax.swing.JButton;\r
+import javax.swing.JCheckBox;\r
+import javax.swing.JComboBox;\r
+import javax.swing.JComponent;\r
+import javax.swing.JDialog;\r
+import javax.swing.JLabel;\r
+import javax.swing.JOptionPane;\r
+import javax.swing.JPanel;\r
+import javax.swing.JTextField;\r
+\r
+import com.gitblit.Constants.AccessRestrictionType;\r
+import com.gitblit.Constants.FederationStrategy;\r
+import com.gitblit.models.RepositoryModel;\r
+import com.gitblit.models.UserModel;\r
+import com.gitblit.utils.StringUtils;\r
+\r
+public class EditRepositoryDialog extends JDialog {\r
+\r
+       private static final long serialVersionUID = 1L;\r
+\r
+       private final RepositoryModel repository;\r
+\r
+       private boolean canceled = true;\r
+\r
+       private JTextField nameField;\r
+\r
+       private JTextField descriptionField;\r
+\r
+       private JCheckBox useTickets;\r
+\r
+       private JCheckBox useDocs;\r
+\r
+       private JCheckBox showRemoteBranches;\r
+\r
+       private JCheckBox showReadme;\r
+\r
+       private JCheckBox isFrozen;\r
+\r
+       private JComboBox accessRestriction;\r
+\r
+       private JComboBox federationStrategy;\r
+\r
+       private JComboBox owner;\r
+\r
+       private JPalette<String> usersPalette;\r
+\r
+       private JPalette<String> setsPalette;\r
+\r
+       public EditRepositoryDialog(List<UserModel> allusers) {\r
+               this(new RepositoryModel(), allusers);\r
+               setTitle("Create Repository");\r
+       }\r
+\r
+       public EditRepositoryDialog(RepositoryModel aRepository, List<UserModel> allUsers) {\r
+               super();\r
+               this.repository = new RepositoryModel();\r
+               initialize(aRepository, allUsers);\r
+               setModal(true);\r
+               setTitle("Edit Repository: " + aRepository.name);\r
+               setIconImage(new ImageIcon(getClass().getResource("/gitblt-favicon.png")).getImage());\r
+       }\r
+\r
+       private void initialize(RepositoryModel anRepository, List<UserModel> allUsers) {\r
+               nameField = new JTextField(anRepository.name == null ? "" : anRepository.name, 35);\r
+               descriptionField = new JTextField(anRepository.description == null ? ""\r
+                               : anRepository.description, 35);\r
+\r
+               owner = new JComboBox(allUsers.toArray());\r
+               if (!StringUtils.isEmpty(anRepository.owner)) {\r
+                       UserModel currentOwner = null;\r
+                       for (UserModel user : allUsers) {\r
+                               if (user.username.equalsIgnoreCase(anRepository.owner)) {\r
+                                       currentOwner = user;\r
+                                       break;\r
+                               }\r
+                       }\r
+                       owner.setSelectedItem(currentOwner);\r
+               }\r
+\r
+               useTickets = new JCheckBox("distributed Ticgit issues", anRepository.useTickets);\r
+               useDocs = new JCheckBox("enumerates Markdown documentation in repository",\r
+                               anRepository.useDocs);\r
+               showRemoteBranches = new JCheckBox("show remote branches", anRepository.showRemoteBranches);\r
+               showReadme = new JCheckBox("show a \"readme\" Markdown file on the summary page",\r
+                               anRepository.showReadme);\r
+               isFrozen = new JCheckBox("deny push operations", anRepository.isFrozen);\r
+\r
+               accessRestriction = new JComboBox(AccessRestrictionType.values());\r
+               accessRestriction.setSelectedItem(anRepository.accessRestriction);\r
+\r
+               federationStrategy = new JComboBox(FederationStrategy.values());\r
+               federationStrategy.setSelectedItem(anRepository.federationStrategy);\r
+\r
+               JPanel fieldsPanel = new JPanel(new GridLayout(0, 1));\r
+               fieldsPanel.add(newFieldPanel("name", nameField));\r
+               fieldsPanel.add(newFieldPanel("description", descriptionField));\r
+               fieldsPanel.add(newFieldPanel("owner", owner));\r
+\r
+               fieldsPanel.add(newFieldPanel("enable tickets", useTickets));\r
+               fieldsPanel.add(newFieldPanel("enable docs", useDocs));\r
+               fieldsPanel.add(newFieldPanel("show remote branches", showRemoteBranches));\r
+               fieldsPanel.add(newFieldPanel("show readme", showReadme));\r
+               fieldsPanel.add(newFieldPanel("is frozen", isFrozen));\r
+\r
+               usersPalette = new JPalette<String>();\r
+               JPanel accessPanel = new JPanel(new BorderLayout(5, 5));\r
+               accessPanel.add(newFieldPanel("access restriction", accessRestriction), BorderLayout.NORTH);\r
+               accessPanel.add(newFieldPanel("permitted users", usersPalette), BorderLayout.CENTER);\r
+\r
+               setsPalette = new JPalette<String>();\r
+               JPanel federationPanel = new JPanel(new BorderLayout(5, 5));\r
+               federationPanel.add(newFieldPanel("federation strategy", federationStrategy),\r
+                               BorderLayout.NORTH);\r
+               federationPanel.add(newFieldPanel("federation sets", setsPalette), BorderLayout.CENTER);\r
+\r
+               JPanel panel = new JPanel(new BorderLayout(5, 5));\r
+               panel.add(fieldsPanel, BorderLayout.NORTH);\r
+               panel.add(accessPanel, BorderLayout.CENTER);\r
+               panel.add(federationPanel, BorderLayout.SOUTH);\r
+\r
+               JButton createButton = new JButton("Save");\r
+               createButton.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent event) {\r
+                               if (validateFields()) {\r
+                                       canceled = false;\r
+                                       setVisible(false);\r
+                               }\r
+                       }\r
+               });\r
+\r
+               JButton cancelButton = new JButton("Cancel");\r
+               cancelButton.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent event) {\r
+                               canceled = true;\r
+                               setVisible(false);\r
+                       }\r
+               });\r
+\r
+               JPanel controls = new JPanel();\r
+               controls.add(cancelButton);\r
+               controls.add(createButton);\r
+\r
+               final Insets _insets = new Insets(5, 5, 5, 5);\r
+               JPanel centerPanel = new JPanel(new BorderLayout(5, 5)) {\r
+\r
+                       private static final long serialVersionUID = 1L;\r
+\r
+                       @Override\r
+                       public Insets getInsets() {\r
+                               return _insets;\r
+                       }\r
+               };\r
+               centerPanel.add(panel, BorderLayout.CENTER);\r
+               centerPanel.add(controls, BorderLayout.SOUTH);\r
+\r
+               getContentPane().setLayout(new BorderLayout(5, 5));\r
+               getContentPane().add(centerPanel, BorderLayout.CENTER);\r
+               pack();\r
+               setLocationRelativeTo(null);\r
+       }\r
+\r
+       private JPanel newFieldPanel(String label, JComponent comp) {\r
+               JLabel fieldLabel = new JLabel(label);\r
+               fieldLabel.setFont(fieldLabel.getFont().deriveFont(Font.BOLD));\r
+               fieldLabel.setPreferredSize(new Dimension(150, 20));\r
+               JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 0));\r
+               panel.add(fieldLabel);\r
+               panel.add(comp);\r
+               return panel;\r
+       }\r
+\r
+       private boolean validateFields() {\r
+               // TODO validate input and populate model\r
+               return true;\r
+       }\r
+\r
+       private void showValidationError(String message) {\r
+               JOptionPane.showMessageDialog(EditRepositoryDialog.this, message, "Validation Error",\r
+                               JOptionPane.ERROR_MESSAGE);\r
+       }\r
+\r
+       public void setUsers(List<String> all, List<String> selected) {\r
+               usersPalette.setObjects(all, selected);\r
+       }\r
+\r
+       public void setFederationSets(List<String> all, List<String> selected) {\r
+               setsPalette.setObjects(all, selected);\r
+       }\r
+\r
+       public RepositoryModel getRepository() {\r
+               if (canceled) {\r
+                       return null;\r
+               }\r
+               return repository;\r
+       }\r
+}\r
diff --git a/src/com/gitblit/client/EditUserDialog.java b/src/com/gitblit/client/EditUserDialog.java
new file mode 100644 (file)
index 0000000..5fce8c5
--- /dev/null
@@ -0,0 +1,237 @@
+/*\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.Dimension;\r
+import java.awt.FlowLayout;\r
+import java.awt.Font;\r
+import java.awt.GridLayout;\r
+import java.awt.Insets;\r
+import java.awt.event.ActionEvent;\r
+import java.awt.event.ActionListener;\r
+import java.text.MessageFormat;\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.List;\r
+\r
+import javax.swing.ImageIcon;\r
+import javax.swing.JButton;\r
+import javax.swing.JCheckBox;\r
+import javax.swing.JComponent;\r
+import javax.swing.JDialog;\r
+import javax.swing.JLabel;\r
+import javax.swing.JOptionPane;\r
+import javax.swing.JPanel;\r
+import javax.swing.JPasswordField;\r
+import javax.swing.JTextField;\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.UserModel;\r
+import com.gitblit.utils.StringUtils;\r
+\r
+public class EditUserDialog extends JDialog {\r
+\r
+       private static final long serialVersionUID = 1L;\r
+\r
+       private final UserModel user;\r
+\r
+       private final IStoredSettings settings;\r
+\r
+       private boolean canceled = true;\r
+\r
+       private JTextField usernameField;\r
+\r
+       private JPasswordField passwordField;\r
+\r
+       private JPasswordField confirmPasswordField;\r
+\r
+       private JCheckBox canAdminCheckbox;\r
+\r
+       private JCheckBox notFederatedCheckbox;\r
+\r
+       private JPalette<String> repositoryPalette;\r
+\r
+       public EditUserDialog(IStoredSettings settings) {\r
+               this(new UserModel(""), settings);\r
+               setTitle("Create User");\r
+       }\r
+\r
+       public EditUserDialog(UserModel anUser, IStoredSettings settings) {\r
+               super();\r
+               this.user = new UserModel("");\r
+               this.settings = settings;\r
+               initialize(anUser);\r
+               setModal(true);\r
+               setTitle("Edit User: " + anUser.username);\r
+               setIconImage(new ImageIcon(getClass().getResource("/gitblt-favicon.png")).getImage());\r
+       }\r
+\r
+       private void initialize(UserModel anUser) {\r
+               usernameField = new JTextField(anUser.username == null ? "" : anUser.username, 25);\r
+               passwordField = new JPasswordField(anUser.password == null ? "" : anUser.password, 25);\r
+               confirmPasswordField = new JPasswordField(anUser.password == null ? "" : anUser.password,\r
+                               25);\r
+               canAdminCheckbox = new JCheckBox("can administer Gitblit server", anUser.canAdmin);\r
+               notFederatedCheckbox = new JCheckBox(\r
+                               "block federated Gitblit instances from pulling this account",\r
+                               anUser.excludeFromFederation);\r
+\r
+               JPanel fieldsPanel = new JPanel(new GridLayout(0, 1));\r
+               fieldsPanel.add(newFieldPanel("username", usernameField));\r
+               fieldsPanel.add(newFieldPanel("password", passwordField));\r
+               fieldsPanel.add(newFieldPanel("confirm password", confirmPasswordField));\r
+               fieldsPanel.add(newFieldPanel("can admin", canAdminCheckbox));\r
+               fieldsPanel.add(newFieldPanel("exclude from federation", notFederatedCheckbox));\r
+\r
+               repositoryPalette = new JPalette<String>();\r
+               JPanel panel = new JPanel(new BorderLayout());\r
+               panel.add(fieldsPanel, BorderLayout.NORTH);\r
+               panel.add(newFieldPanel("restricted repositories", repositoryPalette), BorderLayout.CENTER);\r
+\r
+               JButton createButton = new JButton("Save");\r
+               createButton.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent event) {\r
+                               if (validateFields()) {\r
+                                       canceled = false;\r
+                                       setVisible(false);\r
+                               }\r
+                       }\r
+               });\r
+\r
+               JButton cancelButton = new JButton("Cancel");\r
+               cancelButton.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent event) {\r
+                               canceled = true;\r
+                               setVisible(false);\r
+                       }\r
+               });\r
+\r
+               JPanel controls = new JPanel();\r
+               controls.add(cancelButton);\r
+               controls.add(createButton);\r
+\r
+               final Insets _insets = new Insets(5, 5, 5, 5);\r
+               JPanel centerPanel = new JPanel(new BorderLayout(5, 5)) {\r
+\r
+                       private static final long serialVersionUID = 1L;\r
+\r
+                       @Override\r
+                       public Insets getInsets() {\r
+                               return _insets;\r
+                       }\r
+               };\r
+               centerPanel.add(panel, BorderLayout.CENTER);\r
+               centerPanel.add(controls, BorderLayout.SOUTH);\r
+\r
+               getContentPane().setLayout(new BorderLayout(5, 5));\r
+               getContentPane().add(centerPanel, BorderLayout.CENTER);\r
+               pack();\r
+               setLocationRelativeTo(null);\r
+       }\r
+\r
+       private JPanel newFieldPanel(String label, JComponent comp) {\r
+               JLabel fieldLabel = new JLabel(label);\r
+               fieldLabel.setFont(fieldLabel.getFont().deriveFont(Font.BOLD));\r
+               fieldLabel.setPreferredSize(new Dimension(150, 20));\r
+               JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 0));\r
+               panel.add(fieldLabel);\r
+               panel.add(comp);\r
+               return panel;\r
+       }\r
+\r
+       private boolean validateFields() {\r
+               String uname = usernameField.getText();\r
+               if (StringUtils.isEmpty(uname)) {\r
+                       showValidationError("Please enter a username!");\r
+                       return false;\r
+               }\r
+\r
+               // TODO verify username uniqueness on create\r
+               \r
+               // if (isCreate) {\r
+               // UserModel model = GitBlit.self().getUserModel(username);\r
+               // if (model != null) {\r
+               // error(MessageFormat.format("Username ''{0}'' is unavailable.",\r
+               // username));\r
+               // return;\r
+               // }\r
+               // }\r
+\r
+               int minLength = settings.getInteger(Keys.realm.minPasswordLength, 5);\r
+               if (minLength < 4) {\r
+                       minLength = 4;\r
+               }\r
+               char[] pw = passwordField.getPassword();\r
+               if (pw == null || pw.length < minLength) {\r
+                       showValidationError(MessageFormat.format(\r
+                                       "Password is too short. Minimum length is {0} characters.", minLength));\r
+                       return false;\r
+               }\r
+               char[] cpw = confirmPasswordField.getPassword();\r
+               if (cpw == null || cpw.length != pw.length) {\r
+                       showValidationError("Please confirm the password!");\r
+                       return false;\r
+               }\r
+               if (!Arrays.equals(pw, cpw)) {\r
+                       showValidationError("Passwords do not match!");\r
+                       return false;\r
+               }\r
+               user.username = uname;\r
+               String type = settings.getString(Keys.realm.passwordStorage, "md5");\r
+               if (type.equalsIgnoreCase("md5")) {\r
+                       // store MD5 digest of password\r
+                       user.password = StringUtils.MD5_TYPE + StringUtils.getMD5(new String(pw));\r
+               } else {\r
+                       user.password = new String(pw);\r
+               }\r
+               user.canAdmin = canAdminCheckbox.isSelected();\r
+               user.excludeFromFederation = notFederatedCheckbox.isSelected();\r
+\r
+               user.repositories.clear();\r
+               user.repositories.addAll(repositoryPalette.getSelections());\r
+               return true;\r
+       }\r
+\r
+       private void showValidationError(String message) {\r
+               JOptionPane.showMessageDialog(EditUserDialog.this, message, "Validation Error",\r
+                               JOptionPane.ERROR_MESSAGE);\r
+       }\r
+\r
+       public void setRepositories(List<RepositoryModel> repositories, List<String> selected) {\r
+               List<String> restricted = new ArrayList<String>();\r
+               for (RepositoryModel repo : repositories) {\r
+                       if (repo.accessRestriction.exceeds(AccessRestrictionType.NONE)) {\r
+                               restricted.add(repo.name);\r
+                       }\r
+               }\r
+               StringUtils.sortRepositorynames(restricted);\r
+               if (selected != null) {\r
+                       StringUtils.sortRepositorynames(selected);\r
+               }\r
+               repositoryPalette.setObjects(restricted, selected);\r
+       }\r
+\r
+       public UserModel getUser() {\r
+               if (canceled) {\r
+                       return null;\r
+               }\r
+               return user;\r
+       }\r
+}\r
index 51d8e7eb594f5bdaae0dbd9f4ead8118fb03520d..65a8c36a5fb02482be3be9cd45db5343d4d74a4d 100644 (file)
@@ -148,13 +148,13 @@ public class GitblitClient extends JFrame {
                }\r
                reg = new GitblitRegistration(nameField.getText(), url, accountField.getText(),\r
                                passwordField.getPassword());\r
-               login(reg);\r
+               boolean success = login(reg);\r
                registrations.add(0, reg);\r
                rebuildRecentMenu();\r
-               return true;\r
+               return success;\r
        }\r
 \r
-       private void login(GitblitRegistration reg) {\r
+       private boolean login(GitblitRegistration reg) {\r
                try {\r
                        GitblitPanel panel = new GitblitPanel(reg);\r
                        panel.login();\r
@@ -163,10 +163,12 @@ public class GitblitClient extends JFrame {
                        serverTabs.setSelectedIndex(idx);\r
                        serverTabs.setTabComponentAt(idx, new ClosableTabComponent(reg.name, null, serverTabs,\r
                                        panel));\r
+                       return true;\r
                } catch (IOException e) {\r
                        JOptionPane.showMessageDialog(GitblitClient.this, e.getMessage(), "Error",\r
                                        JOptionPane.ERROR_MESSAGE);\r
                }\r
+               return false;\r
        }\r
 \r
        private void rebuildRecentMenu() {\r
index 19e9efd84b526e6f39c765b80a1c291125179eed..24832d198ddecdbe3a3b8e97eff934e897d3cb2e 100644 (file)
@@ -25,6 +25,7 @@ import java.io.IOException;
 import java.util.Collections;\r
 import java.util.List;\r
 \r
+import com.gitblit.Constants;\r
 import com.gitblit.Launcher;\r
 import com.gitblit.build.Build;\r
 import com.gitblit.build.Build.DownloadListener;\r
@@ -82,6 +83,8 @@ public class GitblitClientLauncher {
                                        if (g != null) {\r
                                                // Splash is 320x120\r
                                                FontMetrics fm = g.getFontMetrics();\r
+                                               \r
+                                               // paint startup status\r
                                                g.setColor(Color.darkGray);\r
                                                int h = fm.getHeight() + fm.getMaxDescent();\r
                                                int x = 5;\r
@@ -93,6 +96,11 @@ public class GitblitClientLauncher {
                                                g.setColor(Color.WHITE);\r
                                                int xw = fm.stringWidth(string);\r
                                                g.drawString(string, x + ((w - xw) / 2), y - 5);\r
+                                               \r
+                                               // paint version\r
+                                               String ver = "v" + Constants.VERSION;\r
+                                               int vw = g.getFontMetrics().stringWidth(ver);\r
+                                               g.drawString(ver, 320 - vw - 5, 34);\r
                                                g.dispose();\r
                                                splash.update();\r
                                        }\r
index 5482593d4e3dfc96225288f521644d83a4af201c..d29f2a90366b2358f313bb502d49d2b3a7efc8e0 100644 (file)
@@ -20,6 +20,7 @@ import java.awt.Color;
 import java.awt.Component;\r
 import java.awt.Desktop;\r
 import java.awt.Dimension;\r
+import java.awt.GridLayout;\r
 import java.awt.Insets;\r
 import java.awt.event.ActionEvent;\r
 import java.awt.event.ActionListener;\r
@@ -27,6 +28,7 @@ import java.io.IOException;
 import java.net.URI;\r
 import java.text.MessageFormat;\r
 import java.util.ArrayList;\r
+import java.util.Collections;\r
 import java.util.Date;\r
 import java.util.List;\r
 import java.util.Map;\r
@@ -34,6 +36,7 @@ import java.util.Map;
 import javax.swing.JButton;\r
 import javax.swing.JLabel;\r
 import javax.swing.JList;\r
+import javax.swing.JOptionPane;\r
 import javax.swing.JPanel;\r
 import javax.swing.JScrollPane;\r
 import javax.swing.JTabbedPane;\r
@@ -41,6 +44,7 @@ import javax.swing.JTable;
 import javax.swing.JTextField;\r
 import javax.swing.RowFilter;\r
 import javax.swing.SwingConstants;\r
+import javax.swing.SwingWorker;\r
 import javax.swing.event.ListSelectionEvent;\r
 import javax.swing.event.ListSelectionListener;\r
 import javax.swing.table.DefaultTableCellRenderer;\r
@@ -49,7 +53,11 @@ import javax.swing.table.TableCellRenderer;
 import javax.swing.table.TableColumn;\r
 import javax.swing.table.TableRowSorter;\r
 \r
+import com.gitblit.Constants.RpcRequest;\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.client.ClosableTabComponent.CloseTabListener;\r
 import com.gitblit.models.FederationModel;\r
 import com.gitblit.models.RepositoryModel;\r
@@ -72,13 +80,17 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
 \r
        private final Insets insets = new Insets(margin, margin, margin, margin);\r
 \r
-       private String url;\r
+       private final String url;\r
 \r
-       private String account;\r
+       private final String account;\r
 \r
-       private char[] password;\r
+       private final char[] password;\r
 \r
-       private boolean isAdmin;\r
+       private volatile boolean isAdmin;\r
+\r
+       private volatile List<UserModel> allUsers;\r
+\r
+       private volatile IStoredSettings settings;\r
 \r
        private JTabbedPane tabs;\r
 \r
@@ -104,6 +116,8 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
 \r
        private TableRowSorter<RepositoriesModel> defaultSorter;\r
 \r
+       private List<RepositoryModel> allRepositories;\r
+\r
        public GitblitPanel(GitblitRegistration reg) {\r
                this(reg.url, reg.account, reg.password);\r
        }\r
@@ -128,10 +142,25 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
                        }\r
                });\r
 \r
+               JButton refreshRepositories = new JButton("Refresh");\r
+               refreshRepositories.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               try {\r
+                                       refreshRepositoriesTable();\r
+                               } catch (ForbiddenException x) {\r
+                                       explainForbidden(RpcRequest.LIST_REPOSITORIES);\r
+                               } catch (UnauthorizedException x) {\r
+                                       explainUnauthorized(RpcRequest.LIST_REPOSITORIES);\r
+                               } catch (Throwable t) {\r
+                                       showException(t);\r
+                               }\r
+                       }\r
+               });\r
+\r
                createRepository = new JButton("Create");\r
                createRepository.addActionListener(new ActionListener() {\r
                        public void actionPerformed(ActionEvent e) {\r
-                               System.out.println("TODO Create Repository");\r
+                               createRepository();\r
                        }\r
                });\r
 \r
@@ -139,9 +168,7 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
                editRepository.setEnabled(false);\r
                editRepository.addActionListener(new ActionListener() {\r
                        public void actionPerformed(ActionEvent e) {\r
-                               for (RepositoryModel model : getSelectedRepositories()) {\r
-                                       System.out.println("TODO Edit " + model);\r
-                               }\r
+                               editRepository(getSelectedRepositories().get(0));\r
                        }\r
                });\r
 \r
@@ -149,9 +176,7 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
                delRepository.setEnabled(false);\r
                delRepository.addActionListener(new ActionListener() {\r
                        public void actionPerformed(ActionEvent e) {\r
-                               for (RepositoryModel model : getSelectedRepositories()) {\r
-                                       System.out.println("TODO Delete " + model);\r
-                               }\r
+                               deleteRepositories(getSelectedRepositories());\r
                        }\r
                });\r
 \r
@@ -165,7 +190,7 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
                        }\r
                });\r
 \r
-               nameRenderer = new NameRenderer(Color.gray, new Color(0x00, 0x69, 0xD6));\r
+               nameRenderer = new NameRenderer();\r
                typeRenderer = new TypeRenderer();\r
 \r
                sizeRenderer = new DefaultTableCellRenderer();\r
@@ -246,10 +271,25 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
                repositoriesPanel.add(tablePanel, BorderLayout.CENTER);\r
                repositoriesPanel.add(repositoryControls, BorderLayout.SOUTH);\r
 \r
+               JButton refreshUsers = new JButton("Refresh");\r
+               refreshUsers.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               try {\r
+                                       refreshUsersTable();\r
+                               } catch (ForbiddenException x) {\r
+                                       explainForbidden(RpcRequest.LIST_USERS);\r
+                               } catch (UnauthorizedException x) {\r
+                                       explainUnauthorized(RpcRequest.LIST_USERS);\r
+                               } catch (Throwable t) {\r
+                                       showException(t);\r
+                               }\r
+                       }\r
+               });\r
+\r
                JButton createUser = new JButton("Create");\r
                createUser.addActionListener(new ActionListener() {\r
                        public void actionPerformed(ActionEvent e) {\r
-                               System.out.println("TODO Create User");\r
+                               createUser();\r
                        }\r
                });\r
 \r
@@ -257,9 +297,7 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
                editUser.setEnabled(false);\r
                editUser.addActionListener(new ActionListener() {\r
                        public void actionPerformed(ActionEvent e) {\r
-                               for (UserModel user : getSelectedUsers()) {\r
-                                       System.out.println("TODO Edit " + user);\r
-                               }\r
+                               editUser(getSelectedUsers().get(0));\r
                        }\r
                });\r
 \r
@@ -267,9 +305,7 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
                delUser.setEnabled(false);\r
                delUser.addActionListener(new ActionListener() {\r
                        public void actionPerformed(ActionEvent e) {\r
-                               for (UserModel user : getSelectedUsers()) {\r
-                                       System.out.println("TODO Delete " + user);\r
-                               }\r
+                               deleteUsers(getSelectedUsers());\r
                        }\r
                });\r
 \r
@@ -288,7 +324,8 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
                        }\r
                });\r
 \r
-               JPanel userControls = new JPanel();\r
+               JPanel userControls = new JPanel(new GridLayout(0, 2));\r
+               userControls.add(refreshUsers);\r
                userControls.add(createUser);\r
                userControls.add(editUser);\r
                userControls.add(delUser);\r
@@ -327,6 +364,7 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
 \r
                try {\r
                        refreshUsersTable();\r
+                       refreshSettings();\r
                        isAdmin = true;\r
                        refreshFederationPanel();\r
                } catch (ForbiddenException e) {\r
@@ -348,8 +386,10 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
        private void refreshRepositoriesTable() throws IOException {\r
                Map<String, RepositoryModel> repositories = RpcUtils\r
                                .getRepositories(url, account, password);\r
+               allRepositories = new ArrayList<RepositoryModel>(repositories.values());\r
+               Collections.sort(allRepositories);\r
                repositoriesModel.list.clear();\r
-               repositoriesModel.list.addAll(repositories.values());\r
+               repositoriesModel.list.addAll(allRepositories);\r
                repositoriesModel.fireTableDataChanged();\r
                packColumns(repositoriesTable, 2);\r
        }\r
@@ -360,8 +400,12 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
        }\r
 \r
        private void refreshUsersTable() throws IOException {\r
-               List<UserModel> users = RpcUtils.getUsers(url, account, password);\r
-               usersList.setListData(users.toArray());\r
+               allUsers = RpcUtils.getUsers(url, account, password);\r
+               usersList.setListData(allUsers.toArray());\r
+       }\r
+\r
+       private void refreshSettings() throws IOException {\r
+               settings = RpcUtils.getSettings(url, account, password);\r
        }\r
 \r
        private void refreshFederationPanel() throws IOException {\r
@@ -465,4 +509,313 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
        @Override\r
        public void closeTab(Component c) {\r
        }\r
+\r
+       /**\r
+        * Displays the create repository dialog and fires a SwingWorker to update\r
+        * the server, if appropriate.\r
+        * \r
+        */\r
+       protected void createRepository() {\r
+               EditRepositoryDialog dialog = new EditRepositoryDialog(allUsers);\r
+               dialog.setVisible(true);\r
+               final RepositoryModel newRepository = dialog.getRepository();\r
+               if (newRepository == null) {\r
+                       return;\r
+               }\r
+\r
+               final RpcRequest request = RpcRequest.CREATE_REPOSITORY;\r
+               SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {\r
+\r
+                       @Override\r
+                       protected Boolean doInBackground() throws IOException {\r
+                               return RpcUtils.createRepository(newRepository, url, account, password);\r
+                       }\r
+\r
+                       @Override\r
+                       protected void done() {\r
+                               try {\r
+                                       boolean success = get();\r
+                                       if (success) {\r
+                                               refreshRepositoriesTable();\r
+                                       } else {\r
+                                               String msg = MessageFormat.format(\r
+                                                               "Failed to execute request \"{0}\" for repository \"{1}\".",\r
+                                                               request.name(), newRepository.name);\r
+                                               JOptionPane.showMessageDialog(GitblitPanel.this, msg, "Error!",\r
+                                                               JOptionPane.ERROR_MESSAGE);\r
+                                       }\r
+                               } catch (ForbiddenException e) {\r
+                                       explainForbidden(request);\r
+                               } catch (UnauthorizedException e) {\r
+                                       explainUnauthorized(request);\r
+                               } catch (Throwable t) {\r
+                                       showException(t);\r
+                               }\r
+                       }\r
+               };\r
+               worker.execute();\r
+       }\r
+\r
+       /**\r
+        * Displays the edit repository dialog and fires a SwingWorker to update the\r
+        * server, if appropriate.\r
+        * \r
+        * @param repository\r
+        */\r
+       protected void editRepository(final RepositoryModel repository) {\r
+               EditRepositoryDialog dialog = new EditRepositoryDialog(repository, allUsers);\r
+               List<String> usernames = new ArrayList<String>();\r
+               for (UserModel user : this.allUsers) {\r
+                       usernames.add(user.username);\r
+               }\r
+               Collections.sort(usernames);\r
+               dialog.setUsers(usernames, null);\r
+               dialog.setFederationSets(settings.getStrings(Keys.federation.sets),\r
+                               repository.federationSets);\r
+               dialog.setVisible(true);\r
+               final RepositoryModel revisedRepository = dialog.getRepository();\r
+               if (revisedRepository == null) {\r
+                       return;\r
+               }\r
+\r
+               final RpcRequest request = RpcRequest.EDIT_REPOSITORY;\r
+               SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {\r
+\r
+                       @Override\r
+                       protected Boolean doInBackground() throws IOException {\r
+                               return RpcUtils.updateRepository(repository.name, revisedRepository, url, account,\r
+                                               password);\r
+                       }\r
+\r
+                       @Override\r
+                       protected void done() {\r
+                               try {\r
+                                       boolean success = get();\r
+                                       if (success) {\r
+                                               refreshRepositoriesTable();\r
+                                       } else {\r
+                                               String msg = MessageFormat.format(\r
+                                                               "Failed to execute request \"{0}\" for repository \"{1}\".",\r
+                                                               request.name(), repository.name);\r
+                                               JOptionPane.showMessageDialog(GitblitPanel.this, msg, "Error!",\r
+                                                               JOptionPane.ERROR_MESSAGE);\r
+                                       }\r
+                               } catch (ForbiddenException e) {\r
+                                       explainForbidden(request);\r
+                               } catch (UnauthorizedException e) {\r
+                                       explainUnauthorized(request);\r
+                               } catch (Throwable t) {\r
+                                       showException(t);\r
+                               }\r
+                       }\r
+               };\r
+               worker.execute();\r
+       }\r
+\r
+       protected void deleteRepositories(final List<RepositoryModel> repositories) {\r
+               if (repositories == null || repositories.size() == 0) {\r
+                       return;\r
+               }\r
+               StringBuilder message = new StringBuilder("Delete the following repositories?\n\n");\r
+               for (RepositoryModel repository : repositories) {\r
+                       message.append(repository.name).append("\n");\r
+               }\r
+               int result = JOptionPane.showConfirmDialog(GitblitPanel.this, message.toString(),\r
+                               "Delete Repositories?", JOptionPane.YES_NO_OPTION);\r
+               if (result == JOptionPane.YES_OPTION) {\r
+                       final RpcRequest request = RpcRequest.DELETE_REPOSITORY;\r
+                       SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {\r
+                               @Override\r
+                               protected Boolean doInBackground() throws Exception {\r
+                                       boolean success = true;\r
+                                       for (RepositoryModel repository : repositories) {\r
+                                               success &= RpcUtils.deleteRepository(repository, url, account, password);\r
+                                       }\r
+                                       return success;\r
+                               }\r
+\r
+                               @Override\r
+                               protected void done() {\r
+                                       try {\r
+                                               boolean success = get();\r
+                                               if (success) {\r
+                                                       refreshRepositoriesTable();\r
+                                               } else {\r
+                                                       String msg = "Failed to delete specified repositories!";\r
+                                                       JOptionPane.showMessageDialog(GitblitPanel.this, msg, "Error!",\r
+                                                                       JOptionPane.ERROR_MESSAGE);\r
+                                               }\r
+                                       } catch (ForbiddenException e) {\r
+                                               explainForbidden(request);\r
+                                       } catch (UnauthorizedException e) {\r
+                                               explainUnauthorized(request);\r
+                                       } catch (Throwable t) {\r
+                                               showException(t);\r
+                                       }\r
+                               }\r
+                       };\r
+                       worker.execute();\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Displays the create user dialog and fires a SwingWorker to update the\r
+        * server, if appropriate.\r
+        * \r
+        */\r
+       protected void createUser() {\r
+               EditUserDialog dialog = new EditUserDialog(settings);\r
+               dialog.setRepositories(allRepositories, null);\r
+               dialog.setVisible(true);\r
+               final UserModel newUser = dialog.getUser();\r
+               if (newUser == null) {\r
+                       return;\r
+               }\r
+\r
+               final RpcRequest request = RpcRequest.CREATE_USER;\r
+               SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {\r
+\r
+                       @Override\r
+                       protected Boolean doInBackground() throws IOException {\r
+                               return RpcUtils.createUser(newUser, url, account, password);\r
+                       }\r
+\r
+                       @Override\r
+                       protected void done() {\r
+                               try {\r
+                                       boolean success = get();\r
+                                       if (success) {\r
+                                               refreshUsersTable();\r
+                                       } else {\r
+                                               String msg = MessageFormat.format(\r
+                                                               "Failed to execute request \"{0}\" for user \"{1}\".",\r
+                                                               request.name(), newUser.username);\r
+                                               JOptionPane.showMessageDialog(GitblitPanel.this, msg, "Error!",\r
+                                                               JOptionPane.ERROR_MESSAGE);\r
+                                       }\r
+                               } catch (ForbiddenException e) {\r
+                                       explainForbidden(request);\r
+                               } catch (UnauthorizedException e) {\r
+                                       explainUnauthorized(request);\r
+                               } catch (Throwable t) {\r
+                                       showException(t);\r
+                               }\r
+                       }\r
+               };\r
+               worker.execute();\r
+       }\r
+\r
+       /**\r
+        * Displays the edit user dialog and fires a SwingWorker to update the\r
+        * server, if appropriate.\r
+        * \r
+        * @param user\r
+        */\r
+       protected void editUser(final UserModel user) {\r
+               EditUserDialog dialog = new EditUserDialog(user, settings);\r
+               dialog.setRepositories(allRepositories, new ArrayList<String>(user.repositories));\r
+               dialog.setVisible(true);\r
+               final UserModel revisedUser = dialog.getUser();\r
+               if (revisedUser == null) {\r
+                       return;\r
+               }\r
+\r
+               final RpcRequest request = RpcRequest.EDIT_USER;\r
+               SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {\r
+\r
+                       @Override\r
+                       protected Boolean doInBackground() throws IOException {\r
+                               return RpcUtils.updateUser(user.username, revisedUser, url, account, password);\r
+                       }\r
+\r
+                       @Override\r
+                       protected void done() {\r
+                               try {\r
+                                       boolean success = get();\r
+                                       if (success) {\r
+                                               refreshUsersTable();\r
+                                       } else {\r
+                                               String msg = MessageFormat.format(\r
+                                                               "Failed to execute request \"{0}\" for user \"{1}\".",\r
+                                                               request.name(), user.username);\r
+                                               JOptionPane.showMessageDialog(GitblitPanel.this, msg, "Error!",\r
+                                                               JOptionPane.ERROR_MESSAGE);\r
+                                       }\r
+                               } catch (ForbiddenException e) {\r
+                                       explainForbidden(request);\r
+                               } catch (UnauthorizedException e) {\r
+                                       explainUnauthorized(request);\r
+                               } catch (Throwable t) {\r
+                                       showException(t);\r
+                               }\r
+                       }\r
+               };\r
+               worker.execute();\r
+       }\r
+\r
+       protected void deleteUsers(final List<UserModel> users) {\r
+               if (users == null || users.size() == 0) {\r
+                       return;\r
+               }\r
+               StringBuilder message = new StringBuilder("Delete the following users?\n\n");\r
+               for (UserModel user : users) {\r
+                       message.append(user.username).append("\n");\r
+               }\r
+               int result = JOptionPane.showConfirmDialog(GitblitPanel.this, message.toString(),\r
+                               "Delete Users?", JOptionPane.YES_NO_OPTION);\r
+               if (result == JOptionPane.YES_OPTION) {\r
+                       final RpcRequest request = RpcRequest.DELETE_USER;\r
+                       SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {\r
+                               @Override\r
+                               protected Boolean doInBackground() throws Exception {\r
+                                       boolean success = true;\r
+                                       for (UserModel user : users) {\r
+                                               success &= RpcUtils.deleteUser(user, url, account, password);\r
+                                       }\r
+                                       return success;\r
+                               }\r
+\r
+                               @Override\r
+                               protected void done() {\r
+                                       try {\r
+                                               boolean success = get();\r
+                                               if (success) {\r
+                                                       refreshUsersTable();\r
+                                               } else {\r
+                                                       String msg = "Failed to delete specified users!";\r
+                                                       JOptionPane.showMessageDialog(GitblitPanel.this, msg, "Error!",\r
+                                                                       JOptionPane.ERROR_MESSAGE);\r
+                                               }\r
+                                       } catch (ForbiddenException e) {\r
+                                               explainForbidden(request);\r
+                                       } catch (UnauthorizedException e) {\r
+                                               explainUnauthorized(request);\r
+                                       } catch (Throwable t) {\r
+                                               showException(t);\r
+                                       }\r
+                               }\r
+                       };\r
+                       worker.execute();\r
+               }\r
+       }\r
+\r
+       private void explainForbidden(RpcRequest request) {\r
+               String msg = MessageFormat.format(\r
+                               "The request \"{0}\" has been forbidden by the Gitblit server @ {1}.",\r
+                               request.name(), url);\r
+               JOptionPane.showMessageDialog(GitblitPanel.this, msg, "Forbidden",\r
+                               JOptionPane.ERROR_MESSAGE);\r
+       }\r
+\r
+       private void explainUnauthorized(RpcRequest request) {\r
+               String msg = MessageFormat.format(\r
+                               "The account \"{0}\" is not authorized to execute the request \"{1}\".", account,\r
+                               request.name());\r
+               JOptionPane.showMessageDialog(GitblitPanel.this, msg, "Unauthorized",\r
+                               JOptionPane.ERROR_MESSAGE);\r
+       }\r
+\r
+       private void showException(Throwable t) {\r
+               // TODO show the unexpected exception\r
+       }\r
 }\r
diff --git a/src/com/gitblit/client/JPalette.java b/src/com/gitblit/client/JPalette.java
new file mode 100644 (file)
index 0000000..19456e1
--- /dev/null
@@ -0,0 +1,177 @@
+/*\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.Dimension;\r
+import java.awt.GridBagLayout;\r
+import java.awt.GridLayout;\r
+import java.awt.event.ActionEvent;\r
+import java.awt.event.ActionListener;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import javax.swing.JButton;\r
+import javax.swing.JLabel;\r
+import javax.swing.JPanel;\r
+import javax.swing.JScrollPane;\r
+import javax.swing.JTable;\r
+import javax.swing.table.AbstractTableModel;\r
+\r
+public class JPalette<T> extends JPanel {\r
+\r
+       private static final long serialVersionUID = 1L;\r
+       private PaletteModel<T> availableModel;\r
+       private PaletteModel<T> selectedModel;\r
+\r
+       public JPalette() {\r
+               super(new BorderLayout(5, 5));\r
+\r
+               availableModel = new PaletteModel<T>();\r
+               selectedModel = new PaletteModel<T>();\r
+\r
+               final JTable available = new JTable(availableModel);\r
+               final JTable selected = new JTable(selectedModel);\r
+\r
+               JButton add = new JButton("->");\r
+               add.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent event) {\r
+                               List<T> move = new ArrayList<T>();\r
+                               if (available.getSelectedRowCount() <= 0) {\r
+                                       return;\r
+                               }\r
+                               for (int row : available.getSelectedRows()) {\r
+                                       int modelIndex = available.convertRowIndexToModel(row);\r
+                                       T item = (T) availableModel.list.get(modelIndex);\r
+                                       move.add(item);\r
+                               }\r
+                               availableModel.list.removeAll(move);\r
+                               selectedModel.list.addAll(move);\r
+                               availableModel.fireTableDataChanged();\r
+                               selectedModel.fireTableDataChanged();\r
+                       }\r
+               });\r
+               JButton subtract = new JButton("<-");\r
+               subtract.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent event) {\r
+                               List<T> move = new ArrayList<T>();\r
+                               if (selected.getSelectedRowCount() <= 0) {\r
+                                       return;\r
+                               }\r
+                               for (int row : selected.getSelectedRows()) {\r
+                                       int modelIndex = selected.convertRowIndexToModel(row);\r
+                                       T item = (T) selectedModel.list.get(modelIndex);\r
+                                       move.add(item);\r
+                               }\r
+                               selectedModel.list.removeAll(move);\r
+                               availableModel.list.addAll(move);\r
+\r
+                               selectedModel.fireTableDataChanged();\r
+                               availableModel.fireTableDataChanged();\r
+                       }\r
+               });\r
+\r
+               JPanel controls = new JPanel(new GridLayout(0, 1, 0, 5));\r
+               controls.add(add);\r
+               controls.add(subtract);\r
+\r
+               JPanel center = new JPanel(new GridBagLayout());\r
+               center.add(controls);\r
+\r
+               add(newListPanel("Available", available), BorderLayout.WEST);\r
+               add(center, BorderLayout.CENTER);\r
+               add(newListPanel("Selected", selected), BorderLayout.EAST);\r
+       }\r
+\r
+       private JPanel newListPanel(String label, JTable table) {\r
+               NameRenderer nameRenderer = new NameRenderer();\r
+               table.setCellSelectionEnabled(false);\r
+               table.setRowSelectionAllowed(true);\r
+               table.setRowHeight(nameRenderer.getFont().getSize() + 8);\r
+               table.getTableHeader().setReorderingAllowed(false);\r
+               table.setGridColor(new Color(0xd9d9d9));\r
+               table.setBackground(Color.white);\r
+               table.getColumn(table.getColumnName(0)).setCellRenderer(nameRenderer);\r
+\r
+               JScrollPane jsp = new JScrollPane(table);\r
+               jsp.setPreferredSize(new Dimension(225, 175));\r
+               JPanel panel = new JPanel(new BorderLayout());\r
+               panel.add(new JLabel(label), BorderLayout.NORTH);\r
+               panel.add(jsp, BorderLayout.CENTER);\r
+               return panel;\r
+       }\r
+\r
+       public void setObjects(List<T> all, List<T> selected) {\r
+               List<T> available = new ArrayList<T>(all);\r
+               if (selected != null) {\r
+                       available.removeAll(selected);\r
+               }\r
+               availableModel.list.clear();\r
+               availableModel.list.addAll(available);\r
+               availableModel.fireTableDataChanged();\r
+\r
+               if (selected != null) {\r
+                       selectedModel.list.clear();\r
+                       selectedModel.list.addAll(selected);\r
+                       selectedModel.fireTableDataChanged();\r
+               }\r
+       }\r
+\r
+       public List<T> getSelections() {\r
+               return new ArrayList<T>(selectedModel.list);\r
+       }\r
+\r
+       public class PaletteModel<K> extends AbstractTableModel {\r
+\r
+               private static final long serialVersionUID = 1L;\r
+\r
+               List<K> list;\r
+\r
+               public PaletteModel() {\r
+                       this(new ArrayList<K>());\r
+               }\r
+\r
+               public PaletteModel(List<K> list) {\r
+                       this.list = new ArrayList<K>(list);\r
+               }\r
+\r
+               @Override\r
+               public int getRowCount() {\r
+                       return list.size();\r
+               }\r
+\r
+               @Override\r
+               public int getColumnCount() {\r
+                       return 1;\r
+               }\r
+\r
+               @Override\r
+               public String getColumnName(int column) {\r
+                       return "Name";\r
+               }\r
+\r
+               public Class<?> getColumnClass(int columnIndex) {\r
+                       return String.class;\r
+               }\r
+\r
+               @Override\r
+               public Object getValueAt(int rowIndex, int columnIndex) {\r
+                       K o = list.get(rowIndex);\r
+                       return o.toString();\r
+               }\r
+       }\r
+}\r
index 41393fb583c475efec08a08fd602bdd88e16dae8..5b1a17364cd7c4efbfdc66728570f3558b82d6dc 100644 (file)
@@ -34,6 +34,10 @@ public class NameRenderer extends DefaultTableCellRenderer {
 \r
        final String groupSpan;\r
 \r
+       public NameRenderer() {\r
+               this(Color.gray, new Color(0x00, 0x69, 0xD6));\r
+       }\r
+\r
        public NameRenderer(Color group, Color repo) {\r
                groupSpan = "<span style='color:" + getHexColor(group) + "'>";\r
                setForeground(repo);\r
index 3834c8edf079a1789b1c088bfa2d3804626e3fe4..fee799015b463d05d9855e5939708f7ba2f4c405 100644 (file)
@@ -157,6 +157,25 @@ public class JsonUtils {
                }\r
                return gson().fromJson(json, type);\r
        }\r
+       \r
+       /**\r
+        * Reads a gson object from the specified url.\r
+        * \r
+        * @param url\r
+        * @param clazz\r
+        * @param username\r
+        * @param password\r
+        * @return the deserialized object\r
+        * @throws {@link IOException}\r
+        */\r
+       public static <X> X retrieveJson(String url, Class<X> clazz, String username, char[] password)\r
+                       throws IOException {\r
+               String json = retrieveJsonString(url, username, password);\r
+               if (StringUtils.isEmpty(json)) {\r
+                       return null;\r
+               }\r
+               return gson().fromJson(json, clazz);\r
+       }\r
 \r
        /**\r
         * Retrieves a JSON message.\r
index 715ecb57c7104fed7bcb75820cdd1b6d513f2695..eb28c0f943532e8928b2a93d2d94b77e713a0788 100644 (file)
@@ -21,9 +21,11 @@ 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
@@ -294,7 +296,7 @@ public class RpcUtils {
                List<FederationModel> list = new ArrayList<FederationModel>(registrations);\r
                return list;\r
        }\r
-       \r
+\r
        /**\r
         * Retrieves the list of federation proposals.\r
         * \r
@@ -304,15 +306,15 @@ public class RpcUtils {
         * @return a collection of FederationProposal objects\r
         * @throws IOException\r
         */\r
-       public static List<FederationProposal> getFederationProposals(String serverUrl,\r
-                       String account, char[] password) throws IOException {\r
+       public static List<FederationProposal> getFederationProposals(String serverUrl, String account,\r
+                       char[] password) throws IOException {\r
                String url = asLink(serverUrl, RpcRequest.LIST_FEDERATION_PROPOSALS);\r
                Collection<FederationProposal> proposals = JsonUtils.retrieveJson(url, PROPOSALS_TYPE,\r
                                account, password);\r
                List<FederationProposal> list = new ArrayList<FederationProposal>(proposals);\r
                return list;\r
        }\r
-       \r
+\r
        /**\r
         * Retrieves the list of federation repository sets.\r
         * \r
@@ -322,15 +324,31 @@ public class RpcUtils {
         * @return a collection of FederationSet objects\r
         * @throws IOException\r
         */\r
-       public static List<FederationSet> getFederationSets(String serverUrl,\r
-                       String account, char[] password) throws IOException {\r
+       public static List<FederationSet> getFederationSets(String serverUrl, String account,\r
+                       char[] password) throws IOException {\r
                String url = asLink(serverUrl, RpcRequest.LIST_FEDERATION_SETS);\r
-               Collection<FederationSet> sets = JsonUtils.retrieveJson(url, SETS_TYPE,\r
-                               account, password);\r
+               Collection<FederationSet> sets = JsonUtils.retrieveJson(url, SETS_TYPE, account, password);\r
                List<FederationSet> list = new ArrayList<FederationSet>(sets);\r
                return list;\r
        }\r
 \r
+       /**\r
+        * Retrieves the settings of the Gitblit server.\r
+        * \r
+        * @param serverUrl\r
+        * @param account\r
+        * @param password\r
+        * @return an IStoredSettings object\r
+        * @throws IOException\r
+        */\r
+       public static IStoredSettings getSettings(String serverUrl, String account, char[] password)\r
+                       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
+               return settings;\r
+       }\r
+\r
        /**\r
         * Do the specified administrative action on the Gitblit server.\r
         * \r
@@ -351,4 +369,31 @@ 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 2aa5107999fa9dbeacf0fdaf21bd158e78fd93e1..30fac60022d2ec23a9e30735e46666010b6de505 100644 (file)
@@ -92,7 +92,7 @@ gb.isFrozen = is frozen
 gb.isFrozenDescription = deny push operations\r
 gb.zip = zip\r
 gb.showReadme = show readme\r
-gb.showReadmeDescription = show a \"readme\" markdown file on the summary page\r
+gb.showReadmeDescription = show a \"readme\" Markdown file on the summary page\r
 gb.nameDescription = use '/' to group repositories.  e.g. libraries/mycoollib.git\r
 gb.ownerDescription = the owner may edit repository settings\r
 gb.blob = blob\r
@@ -106,7 +106,7 @@ gb.isFederated = is federated
 gb.federateThis = federate this repository\r
 gb.federateOrigin = federate the origin\r
 gb.excludeFromFederation = exclude from federation\r
-gb.excludeFromFederationDescription = block federated Gitblit instances from pulling this object\r
+gb.excludeFromFederationDescription = block federated Gitblit instances from pulling this account\r
 gb.tokens = federation tokens\r
 gb.tokenAllDescription = all repositories, users, & settings\r
 gb.tokenUnrDescription = all repositories & users\r
index a20b918cdd6c1f1856f982dcf09d47bd4b3b4e87..450b5978a22c4fff56c533cd51feb3dfcd369e55 100644 (file)
@@ -23,6 +23,7 @@ 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
@@ -203,4 +204,9 @@ public class RpcTests extends TestCase {
                List<FederationSet> sets = RpcUtils.getFederationSets(url, account, password.toCharArray());\r
                assertTrue("No federation sets were retrieved!", sets.size() > 0);\r
        }\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
+       }\r
 }\r