changeset 1775:040e20c32a64

Add a quick setup option to provide a fast-track path through setup GUI Reviewed-by: jerboaa, aazores Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2015-September/015765.html PR2581
author Anirudhan Mukundan <amukunda@redhat.com>
date Fri, 04 Sep 2015 14:57:14 -0400
parents 95855156af9e
children 36c9ffed683c
files setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/CredentialPanel.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/DisplayCredentialPanel.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/InputCredentialPanel.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/MongoUserSetupView.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/SetupCommand.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/SetupCompleteView.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/SetupView.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/SetupWindow.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/StartView.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/UserPropertiesView.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/model/CredentialGenerator.java setup/command/src/main/java/com/redhat/thermostat/setup/command/locale/LocaleResources.java setup/command/src/main/resources/com/redhat/thermostat/setup/locale/strings.properties setup/command/src/test/java/com/redhat/thermostat/setup/command/internal/model/CredentialGeneratorTest.java
diffstat 14 files changed, 866 insertions(+), 237 deletions(-) [+]
line wrap: on
line diff
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/CredentialPanel.java	Fri Sep 04 13:06:49 2015 -0400
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/CredentialPanel.java	Fri Sep 04 14:57:14 2015 -0400
@@ -38,63 +38,43 @@
 
 import com.redhat.thermostat.client.swing.components.FontAwesomeIcon;
 import com.redhat.thermostat.client.swing.components.Icon;
-import com.redhat.thermostat.setup.command.internal.model.UserCredsValidator;
 import com.redhat.thermostat.setup.command.locale.LocaleResources;
 import com.redhat.thermostat.shared.locale.Translate;
 
 import javax.swing.BorderFactory;
-import javax.swing.JButton;
-import javax.swing.JCheckBox;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
 import javax.swing.JPasswordField;
 import javax.swing.JTextField;
-import javax.swing.SwingConstants;
 import javax.swing.SwingUtilities;
 import javax.swing.ToolTipManager;
 import javax.swing.border.Border;
-import java.awt.BorderLayout;
-import java.awt.Color;
 import java.awt.Component;
 import java.awt.Container;
 import java.awt.Dimension;
 import java.awt.Graphics;
 import java.awt.Insets;
 import java.awt.Rectangle;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 import java.awt.event.MouseEvent;
-import java.util.Arrays;
 
-public class CredentialPanel extends JPanel {
-
+public abstract class CredentialPanel extends JPanel {
+    
     private String titleText;
     private String helpMessage;
-    private String defaultUsername;
-    private char[] defaultPassword;
-
-    private JPanel messagePanel;
-    private JLabel usernameText;
-    private JLabel passwordText1;
-    private JLabel passwordText2;
-    private JLabel errorMessage;
-    private JTextField username;
-    private JPasswordField password1;
-    private JPasswordField password2;
-    private JCheckBox showPasswordCheckbox;
-    private JButton useDefaultsBtn;
     private ComponentTitledBorder titledBorder;
     private JLabel title;
 
-    private static final UserCredsValidator validator = new UserCredsValidator();
     private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
     private static final Icon infoIcon = new FontAwesomeIcon('\uf05a', 15);
 
-    public CredentialPanel(String titleText, String helpMessage, String defaultUsername, char[] defaultPassword) {
+    protected JLabel usernameText;
+    protected JLabel passwordText;
+    protected JTextField username;
+    protected JPasswordField password;
+
+    public CredentialPanel(String titleText, String helpMessage) {
         this.titleText = titleText;
         this.helpMessage = helpMessage;
-        this.defaultUsername = defaultUsername;
-        this.defaultPassword = defaultPassword;
 
         //enable tooltips
         ToolTipManager.sharedInstance().registerComponent(this);
@@ -104,37 +84,10 @@
     }
 
     private void initComponents() {
-        showPasswordCheckbox = new JCheckBox(translator.localize(LocaleResources.SHOW_PASSWORDS).getContents());
-        showPasswordCheckbox.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent actionEvent) {
-                togglePasswords(showPasswordCheckbox.isSelected());
-            }
-        });
-        showPasswordCheckbox.setSelected(false);
-
-        useDefaultsBtn = new JButton(translator.localize(LocaleResources.USE_DEFAULTS).getContents());
-        useDefaultsBtn.setPreferredSize(new Dimension(140, 30));
-        useDefaultsBtn.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent actionEvent) {
-                username.setText(defaultUsername);
-                password1.setText(String.valueOf(defaultPassword));
-                password2.setText(String.valueOf(defaultPassword));
-                removeErrorMessage();
-            }
-        });
-
-        usernameText = new JLabel();
-        usernameText.setText(translator.localize(LocaleResources.USERNAME).getContents());
-        passwordText1 = new JLabel();
-        passwordText1.setText(translator.localize(LocaleResources.PASSWORD).getContents());
-        passwordText2 = new JLabel();
-        passwordText2.setText(translator.localize(LocaleResources.VERIFY_PASSWORD).getContents());
-
+        usernameText = new JLabel(translator.localize(LocaleResources.USERNAME).getContents());
+        passwordText = new JLabel(translator.localize(LocaleResources.PASSWORD).getContents());
         username = new JTextField();
-        password1 = new JPasswordField();
-        password2 = new JPasswordField();
+        password = new JPasswordField();
 
         title = new JLabel(titleText, infoIcon, JLabel.CENTER);
         title.setHorizontalTextPosition(JLabel.LEFT);
@@ -143,63 +96,6 @@
 
         titledBorder = new ComponentTitledBorder(title, BorderFactory.createEtchedBorder());
         setBorder(titledBorder);
-
-        errorMessage = new JLabel();
-        errorMessage.setForeground(Color.RED);
-        errorMessage.setHorizontalAlignment(SwingConstants.CENTER);
-
-        messagePanel = new JPanel(new BorderLayout());
-        messagePanel.add(errorMessage, BorderLayout.CENTER);
-
-        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
-        this.setLayout(layout);
-        layout.setHorizontalGroup(
-            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                .addGroup(layout.createSequentialGroup()
-                    .addContainerGap()
-                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                        .addGroup(layout.createSequentialGroup()
-                            .addGap(25, 25, 25)
-                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                                .addComponent(passwordText1)
-                                .addComponent(usernameText)
-                                .addComponent(passwordText2))
-                            .addGap(65, 65, 65)
-                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                                .addGroup(layout.createSequentialGroup()
-                                    .addComponent(showPasswordCheckbox)
-                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 6, Short.MAX_VALUE)
-                                    .addComponent(useDefaultsBtn))
-                                .addComponent(password2, javax.swing.GroupLayout.Alignment.TRAILING)
-                                .addComponent(password1)
-                                .addComponent(username))))
-                    .addContainerGap())
-                .addComponent(messagePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-        );
-        layout.setVerticalGroup(
-            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                .addGroup(layout.createSequentialGroup()
-                    .addContainerGap()
-                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
-                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
-                        .addComponent(usernameText)
-                        .addComponent(username, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
-                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
-                        .addComponent(passwordText1)
-                        .addComponent(password1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
-                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
-                        .addComponent(passwordText2)
-                        .addComponent(password2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
-                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
-                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
-                        .addComponent(showPasswordCheckbox)
-                        .addComponent(useDefaultsBtn))
-                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                    .addComponent(messagePanel, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
-                    .addGap(0, 0, 0))
-        );
     }
 
     public JTextField getUsernameField() {
@@ -210,77 +106,12 @@
         return username.getText();
     }
 
-    public JTextField getPasswordField1() {
-        return password1;
-    }
-
-    public JTextField getPasswordField2() {
-        return password2;
+    public JTextField getPasswordField() {
+        return password;
     }
 
     public char[] getPassword() {
-        return password1.getPassword();
-    }
-
-    private void togglePasswords(boolean isVisible) {
-        if (isVisible) {
-            password1.setEchoChar((char) 0);
-            password2.setEchoChar((char) 0);
-        } else {
-            password1.setEchoChar('*');
-            password2.setEchoChar('*');
-        }
-    }
-
-    public void removeErrorMessage() {
-        errorMessage.setText(null);
-        this.revalidate();
-        this.repaint();
-    }
-
-    public void showPasswordMismatch() {
-        errorMessage.setText(translator.localize(LocaleResources.PASSWORD_MISMATCH).getContents());
-        this.revalidate();
-        this.repaint();
-    }
-
-    public void showDetailsMissing() {
-        errorMessage.setText(translator.localize(LocaleResources.DETAILS_MISSING).getContents());
-        this.revalidate();
-        this.repaint();
-    }
-
-    public boolean isInputValid() {
-        //ensure credentials are not empty
-        try {
-            validator.validateUsername(username.getText());
-            validator.validatePassword(password1.getPassword());
-            validator.validatePassword(password2.getPassword());
-        } catch (IllegalArgumentException e) {
-            showDetailsMissing();
-            return false;
-        }
-
-        //ensure passwords match
-        if (!Arrays.equals(password1.getPassword(), password2.getPassword())) {
-            showPasswordMismatch();
-            return false;
-        }
-
-        removeErrorMessage();
-        return true;
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        usernameText.setEnabled(enabled);
-        passwordText1.setEnabled(enabled);
-        passwordText2.setEnabled(enabled);
-        username.setEnabled(enabled);
-        password1.setEnabled(enabled);
-        password2.setEnabled(enabled);
-        showPasswordCheckbox.setEnabled(enabled);
-        useDefaultsBtn.setEnabled(enabled);
+        return password.getPassword();
     }
 
     @Override
@@ -294,9 +125,8 @@
 
     public class ComponentTitledBorder implements Border {
         private static final int OFFSET = 5;
-        public final Component comp;
+        private final Component comp;
         private Rectangle rect;
-
         private Border border;
 
         public ComponentTitledBorder(Component comp, Border border) {
@@ -328,6 +158,5 @@
         public Rectangle getTitleRect() {
             return rect;
         }
-
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/DisplayCredentialPanel.java	Fri Sep 04 14:57:14 2015 -0400
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2012-2015 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.setup.command.internal;
+
+public class DisplayCredentialPanel extends CredentialPanel {
+
+    public DisplayCredentialPanel(String titleText, String helpMessage) {
+        super(titleText, helpMessage);
+        initComponents();
+    }
+
+    private void initComponents() {
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                .addGroup(layout.createSequentialGroup()
+                    .addGap(33, 33, 33)
+                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                        .addComponent(passwordText)
+                        .addComponent(usernameText))
+                    .addGap(108, 108, 108)
+                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                        .addComponent(password, javax.swing.GroupLayout.DEFAULT_SIZE, 277, Short.MAX_VALUE)
+                        .addComponent(username))
+                    .addContainerGap())
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                .addGroup(layout.createSequentialGroup()
+                    .addContainerGap()
+                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                        .addComponent(usernameText)
+                        .addComponent(username, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                        .addComponent(passwordText)
+                        .addComponent(password, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                    .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+        );
+
+        username.setEditable(false);
+        password.setEditable(false);
+        password.setEchoChar((char) 0);
+    }
+
+    public void setDisplayCredentials(String username, char[] password) {
+        this.username.setText(username);
+        this.password.setText(String.valueOf(password));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/InputCredentialPanel.java	Fri Sep 04 14:57:14 2015 -0400
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2012-2015 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.setup.command.internal;
+
+import com.redhat.thermostat.setup.command.internal.model.CredentialGenerator;
+import com.redhat.thermostat.setup.command.internal.model.UserCredsValidator;
+import com.redhat.thermostat.setup.command.locale.LocaleResources;
+import com.redhat.thermostat.shared.locale.Translate;
+
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JPasswordField;
+import javax.swing.JTextField;
+import javax.swing.SwingConstants;
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Arrays;
+
+public class InputCredentialPanel extends CredentialPanel {
+
+    private JLabel passwordConfirmText;
+    private JPasswordField passwordConfirm;
+    private JPanel messagePanel;
+    private JLabel errorMessage;
+    private JCheckBox showPasswordCheckbox;
+    private JButton useDefaultsBtn;
+    private CredentialGenerator credentialGenerator;
+
+    private static final UserCredsValidator validator = new UserCredsValidator();
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    public InputCredentialPanel(String titleText, String helpMessage, String defaultUsernamePrefix) {
+        super(titleText, helpMessage);
+
+        credentialGenerator = new CredentialGenerator(defaultUsernamePrefix);
+
+        initComponents();
+    }
+
+    private void initComponents() {
+        showPasswordCheckbox = new JCheckBox(translator.localize(LocaleResources.SHOW_PASSWORDS).getContents());
+        showPasswordCheckbox.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent actionEvent) {
+                showPassword(showPasswordCheckbox.isSelected());
+            }
+        });
+        showPasswordCheckbox.setSelected(false);
+
+        useDefaultsBtn = new JButton(translator.localize(LocaleResources.USE_DEFAULTS).getContents());
+        useDefaultsBtn.setPreferredSize(new Dimension(140, 30));
+        useDefaultsBtn.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent actionEvent) {
+                String defaultUsername = credentialGenerator.generateRandomUsername();
+                char[] defaultPassword = credentialGenerator.generateRandomPassword();
+
+                username.setText(defaultUsername);
+                password.setText(String.valueOf(defaultPassword));
+                passwordConfirm.setText(String.valueOf(defaultPassword));
+                removeErrorMessage();
+            }
+        });
+
+        passwordConfirmText = new JLabel(translator.localize(LocaleResources.VERIFY_PASSWORD).getContents());
+        passwordConfirm = new JPasswordField();
+
+        errorMessage = new JLabel();
+        errorMessage.setForeground(Color.RED);
+        errorMessage.setHorizontalAlignment(SwingConstants.CENTER);
+
+        messagePanel = new JPanel(new BorderLayout());
+        messagePanel.add(errorMessage, BorderLayout.CENTER);
+
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                .addGroup(layout.createSequentialGroup()
+                    .addContainerGap()
+                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                        .addGroup(layout.createSequentialGroup()
+                            .addGap(25, 25, 25)
+                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                                .addComponent(passwordText)
+                                .addComponent(usernameText)
+                                .addComponent(passwordConfirmText))
+                            .addGap(65, 65, 65)
+                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                                .addGroup(layout.createSequentialGroup()
+                                    .addComponent(showPasswordCheckbox)
+                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 6, Short.MAX_VALUE)
+                                    .addComponent(useDefaultsBtn))
+                                .addComponent(passwordConfirm, javax.swing.GroupLayout.Alignment.TRAILING)
+                                .addComponent(password)
+                                .addComponent(username))))
+                    .addContainerGap())
+                .addComponent(messagePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                .addGroup(layout.createSequentialGroup()
+                    .addContainerGap()
+                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                        .addComponent(usernameText)
+                        .addComponent(username, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                        .addComponent(passwordText)
+                        .addComponent(password, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                        .addComponent(passwordConfirmText)
+                        .addComponent(passwordConfirm, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                        .addComponent(showPasswordCheckbox)
+                        .addComponent(useDefaultsBtn))
+                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                    .addComponent(messagePanel, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addGap(0, 0, 0))
+        );
+    }
+
+    public JTextField getUsernameField() {
+        return username;
+    }
+
+    public String getUsername() {
+        return username.getText();
+    }
+
+    public JTextField getPasswordField() {
+        return password;
+    }
+
+    public JTextField getPasswordConfirmField() {
+        return passwordConfirm;
+    }
+
+    public char[] getPassword() {
+        return password.getPassword();
+    }
+
+    private void showPassword(boolean isVisible) {
+        if (isVisible) {
+            password.setEchoChar((char) 0);
+            passwordConfirm.setEchoChar((char) 0);
+        } else {
+            password.setEchoChar('*');
+            passwordConfirm.setEchoChar('*');
+        }
+    }
+
+    public void removeErrorMessage() {
+        errorMessage.setText(null);
+        this.revalidate();
+        this.repaint();
+    }
+
+    public void showPasswordMismatch() {
+        errorMessage.setText(translator.localize(LocaleResources.PASSWORD_MISMATCH).getContents());
+        this.revalidate();
+        this.repaint();
+    }
+
+    public void showDetailsMissing() {
+        errorMessage.setText(translator.localize(LocaleResources.DETAILS_MISSING).getContents());
+        this.revalidate();
+        this.repaint();
+    }
+
+    public boolean isInputValid() {
+        //ensure credentials are not empty
+        try {
+            validator.validateUsername(username.getText());
+            validator.validatePassword(password.getPassword());
+            validator.validatePassword(passwordConfirm.getPassword());
+        } catch (IllegalArgumentException e) {
+            showDetailsMissing();
+            return false;
+        }
+
+        //ensure passwords match
+        if (!Arrays.equals(password.getPassword(), passwordConfirm.getPassword())) {
+            showPasswordMismatch();
+            return false;
+        }
+
+        removeErrorMessage();
+        return true;
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        usernameText.setEnabled(enabled);
+        passwordText.setEnabled(enabled);
+        passwordConfirmText.setEnabled(enabled);
+        username.setEnabled(enabled);
+        password.setEnabled(enabled);
+        passwordConfirm.setEnabled(enabled);
+        showPasswordCheckbox.setEnabled(enabled);
+        useDefaultsBtn.setEnabled(enabled);
+    }
+}
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/MongoUserSetupView.java	Fri Sep 04 13:06:49 2015 -0400
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/MongoUserSetupView.java	Fri Sep 04 14:57:14 2015 -0400
@@ -62,12 +62,10 @@
 
     private JPanel toolbar;
     private JPanel midPanel;
-    private CredentialPanel credentialPanel;
+    private InputCredentialPanel credentialPanel;
 
     private static final String THERMOSTAT_LOGO = "thermostat.png";
     private static final String PROGRESS = "Step 2 of 3";
-    private static final String DEFAULT_STORAGE_USER = "mongodevuser";
-    private static final char[] DEFAULT_STORAGE_PASSWORD = new char[] {'m', 'o', 'n', 'g', 'o', 'd', 'e', 'v', 'p', 'a', 's', 's', 'w', 'o', 'r', 'd'};
     private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
 
     public MongoUserSetupView(LayoutManager layout) {
@@ -81,17 +79,21 @@
     }
 
     @Override
-    public void setTitleAndProgress(JLabel title, JLabel progress) {
+    public void setTitle(JLabel title) {
         title.setText(translator.localize(LocaleResources.MONGO_SETUP_TITLE).getContents());
+    }
+
+    @Override
+    public void setProgress(JLabel progress) {
         progress.setText(PROGRESS);
     }
 
     private void createMidPanel() {
-        credentialPanel = new CredentialPanel(
+        credentialPanel = new InputCredentialPanel(
             translator.localize(LocaleResources.MONGO_CRED_TITLE).getContents(),
             translator.localize(LocaleResources.STORAGE_HELP_INFO).getContents(),
-            DEFAULT_STORAGE_USER,
-            DEFAULT_STORAGE_PASSWORD);
+            translator.localize(LocaleResources.MONGO_USER_PREFIX).getContents());
+
         DocumentListener inputValidator = new DocumentListener() {
             @Override
             public void insertUpdate(DocumentEvent documentEvent) {
@@ -109,8 +111,8 @@
             }
         };
         credentialPanel.getUsernameField().getDocument().addDocumentListener(inputValidator);
-        credentialPanel.getPasswordField1().getDocument().addDocumentListener(inputValidator);
-        credentialPanel.getPasswordField2().getDocument().addDocumentListener(inputValidator);
+        credentialPanel.getPasswordField().getDocument().addDocumentListener(inputValidator);
+        credentialPanel.getPasswordConfirmField().getDocument().addDocumentListener(inputValidator);
 
         midPanel = new JPanel();
         midPanel.setLayout(new BoxLayout(midPanel, BoxLayout.PAGE_AXIS));
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/SetupCommand.java	Fri Sep 04 13:06:49 2015 -0400
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/SetupCommand.java	Fri Sep 04 14:57:14 2015 -0400
@@ -55,7 +55,6 @@
 import com.redhat.thermostat.common.utils.LoggingUtils;
 import com.redhat.thermostat.internal.utils.laf.ThemeManager;
 import com.redhat.thermostat.launcher.Launcher;
-import com.redhat.thermostat.setup.command.internal.SetupWindow;
 import com.redhat.thermostat.setup.command.internal.cli.CLISetup;
 import com.redhat.thermostat.setup.command.internal.model.ThermostatSetup;
 import com.redhat.thermostat.setup.command.locale.LocaleResources;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/SetupCompleteView.java	Fri Sep 04 14:57:14 2015 -0400
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2012-2015 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.setup.command.internal;
+
+import com.redhat.thermostat.setup.command.locale.LocaleResources;
+import com.redhat.thermostat.shared.locale.Translate;
+
+import javax.swing.BorderFactory;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.LayoutManager;
+import java.net.URL;
+
+public class SetupCompleteView extends JPanel implements SetupView {
+
+    private JButton finishBtn;
+    private JPanel toolbar;
+    private JPanel midPanel;
+    private DisplayCredentialPanel clientInfoPanel;
+    private DisplayCredentialPanel agentInfoPanel;
+    private static final String THERMOSTAT_LOGO = "thermostat.png";
+    private static final String PROGRESS = "Step 2 of 2";
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    public SetupCompleteView(LayoutManager layout) {
+        super(layout);
+
+        createMidPanel();
+        createToolbarPanel();
+    }
+
+    public void setClientCredentials(String clientUsername, char[] clientPassword) {
+        clientInfoPanel.setDisplayCredentials(clientUsername, clientPassword);
+    }
+
+    public void setAgentCredentials(String agentUsername, char[] agentPassword) {
+        agentInfoPanel.setDisplayCredentials(agentUsername, agentPassword);
+    }
+
+    @Override
+    public void setTitle(JLabel title) {
+        title.setText(translator.localize(LocaleResources.SETUP_COMPLETE_TITLE).getContents());
+    }
+
+    @Override
+    public void setProgress(JLabel progress) {
+        progress.setText(PROGRESS);
+    }
+
+    public void createMidPanel() {
+        clientInfoPanel = new DisplayCredentialPanel(
+            translator.localize(LocaleResources.CLIENT_CRED_TITLE).getContents(),
+            translator.localize(LocaleResources.CLIENT_HELP_INFO).getContents());
+
+        agentInfoPanel = new DisplayCredentialPanel(
+            translator.localize(LocaleResources.AGENT_CRED_TITLE).getContents(),
+            translator.localize(LocaleResources.AGENT_HELP_INFO).getContents());
+
+        midPanel = new JPanel();
+        midPanel.setLayout(new BoxLayout(midPanel, BoxLayout.PAGE_AXIS));
+        midPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+        midPanel.add(Box.createRigidArea(new Dimension(0, 20)));
+        midPanel.add(clientInfoPanel);
+        midPanel.add(Box.createRigidArea(new Dimension(0, 20)));
+        midPanel.add(agentInfoPanel);
+
+        this.add(midPanel, BorderLayout.CENTER);
+    }
+
+    private void createToolbarPanel() {
+        URL logoURL = SetupCompleteView.class.getClassLoader().getResource(THERMOSTAT_LOGO);
+        JLabel thermostatLogo = new JLabel(new ImageIcon(logoURL));
+
+        finishBtn = new JButton(translator.localize(LocaleResources.FINISH).getContents());
+        finishBtn.setPreferredSize(new Dimension(70, 30));
+
+        toolbar = new JPanel();
+        toolbar.setLayout(new BoxLayout(toolbar, BoxLayout.LINE_AXIS));
+        toolbar.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
+        toolbar.add(thermostatLogo);
+        toolbar.add(Box.createHorizontalGlue());
+        toolbar.add(finishBtn);
+
+        this.add(toolbar, BorderLayout.SOUTH);
+    }
+
+    @Override
+    public void setDefaultButton() {
+        getRootPane().setDefaultButton(finishBtn);
+    }
+
+    @Override
+    public void focusInitialComponent() {
+        finishBtn.requestFocusInWindow();
+    }
+
+    @Override
+    public Component getUiComponent() {
+        return this;
+    }
+
+    public JButton getFinishBtn() {
+        return finishBtn;
+    }
+
+}
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/SetupView.java	Fri Sep 04 13:06:49 2015 -0400
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/SetupView.java	Fri Sep 04 14:57:14 2015 -0400
@@ -43,12 +43,17 @@
 
     /**
      * Sets the title of the current view
-     * and updates the progress
      *
      * @param title
+     */
+    void setTitle(JLabel title);
+
+    /**
+     * Sets the progress of the current view
+     *
      * @param progress
      */
-    void setTitleAndProgress(JLabel title, JLabel progress);
+    void setProgress(JLabel progress);
 
     Component getUiComponent();
 
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/SetupWindow.java	Fri Sep 04 13:06:49 2015 -0400
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/SetupWindow.java	Fri Sep 04 14:57:14 2015 -0400
@@ -68,6 +68,7 @@
 
 import com.redhat.thermostat.common.cli.CommandException;
 import com.redhat.thermostat.common.utils.LoggingUtils;
+import com.redhat.thermostat.setup.command.internal.model.CredentialGenerator;
 import com.redhat.thermostat.setup.command.internal.model.ThermostatSetup;
 import com.redhat.thermostat.setup.command.locale.LocaleResources;
 import com.redhat.thermostat.shared.locale.Translate;
@@ -82,8 +83,13 @@
     private StartView startView;
     private MongoUserSetupView mongoUserSetupView;
     private UserPropertiesView userPropertiesView;
+    private SetupCompleteView setupCompleteView;
     private String storageUsername = null;
     private char[] storagePassword = null;
+    private String clientUsername = null;
+    private char[] clientPassword = null;
+    private String agentUsername = null;
+    private char[] agentPassword = null;
     private boolean showDetailedBlurb = false;
     private boolean setupCancelled = false;
     private final ThermostatSetup thermostatSetup;
@@ -92,6 +98,10 @@
     private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
     private static final Logger logger = LoggingUtils.getLogger(SetupWindow.class);
 
+    private static final int FRAME_WIDTH = 600;
+    private static final int FRAME_HEIGHT = 380;
+    private static final int FRAME_LARGE_HEIGHT = 600;
+
     public SetupWindow(ThermostatSetup thermostatSetup) {
         this.thermostatSetup = thermostatSetup;
         this.shutdown = new CountDownLatch(1);
@@ -111,10 +121,7 @@
 
         try {
             shutdown.await();
-            // Explicitly dispose the window once we're done since we might have
-            // intercepted another command and the window would otherwise
-            // stay open.
-            frame.dispose();
+
             // Determine if we've finished successfully.
             if (finishAction != null) {
                 IOException finishException = finishAction.get();
@@ -127,13 +134,35 @@
                 logger.log(Level.INFO, "Setup was cancelled.");
                 throw new CommandException(translator.localize(LocaleResources.SETUP_CANCELLED));
             }
+
+            // if quick setup option was selected display
+            // the setup complete window with user credentials
+            if (startView.isQuickSetupSelected()) {
+                SwingUtilities.invokeLater(new Runnable() {
+                    @Override
+                    public void run() {
+                        mainView.remove(startView);
+                        showView(setupCompleteView);
+                    }
+                });
+                shutdown = new CountDownLatch(1);
+                shutdown.await();
+            }
         } catch (InterruptedException | ExecutionException | InvocationTargetException e) {
             throw new CommandException(translator.localize(LocaleResources.SETUP_INTERRUPTED), e);
         } finally {
+            // Explicitly dispose the window once we're done since we might have
+            // intercepted another command and the window would otherwise
+            // stay open.
+            frame.dispose();
             cleanup();
         }
     }
 
+    public static int getFrameWidth() {
+        return FRAME_WIDTH;
+    }
+    
     private void showErrorDialog(final Exception e) throws InvocationTargetException, InterruptedException {
         doSynchronouslyOnEdt(new Runnable() {
             @Override
@@ -188,6 +217,7 @@
         startView = new StartView(new BorderLayout());
         mongoUserSetupView = new MongoUserSetupView(new BorderLayout());
         userPropertiesView = new UserPropertiesView(new BorderLayout());
+        setupCompleteView = new SetupCompleteView(new BorderLayout());
     }
 
     private void createTopPanel() {
@@ -217,8 +247,12 @@
                 startView.showMoreInfo(showDetailedBlurb);
                 setLargeFrame(showDetailedBlurb);
 
-                mainView.remove(startView);
-                showView(mongoUserSetupView);
+                if (startView.isQuickSetupSelected()) {
+                    runQuickSetup();
+                } else {
+                    mainView.remove(startView);
+                    showView(mongoUserSetupView);
+                }
             }
         });
         startView.getShowMoreInfoBtn().addActionListener(new ActionListener() {
@@ -229,6 +263,18 @@
                 setLargeFrame(showDetailedBlurb);
             }
         });
+        startView.getQuickSetupBtn().addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                startView.setProgress(progress);
+            }
+        });
+        startView.getCustomSetupBtn().addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                startView.setProgress(progress);
+            }
+        });
         mongoUserSetupView.getBackBtn().addActionListener(new ActionListener() {
             @Override
             public void actionPerformed(ActionEvent actionEvent) {
@@ -264,9 +310,19 @@
         userPropertiesView.getFinishBtn().addActionListener(new ActionListener() {
             @Override
             public void actionPerformed(ActionEvent actionEvent) {
+                agentUsername = userPropertiesView.getAgentUsername();
+                agentPassword = userPropertiesView.getAgentPassword();
+                clientUsername = userPropertiesView.getClientUsername();
+                clientPassword = userPropertiesView.getClientPassword();
                 runSetup();
             }
         });
+        setupCompleteView.getFinishBtn().addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent actionEvent) {
+                shutdown();
+            }
+        });
 
         ActionListener cancelButtonListener = new ActionListener() {
             @Override
@@ -281,9 +337,9 @@
 
     private void setLargeFrame(boolean setLarge) {
         if (setLarge) {
-            frame.setSize(600, 600);
+            frame.setSize(FRAME_WIDTH, FRAME_LARGE_HEIGHT);
         } else {
-            frame.setSize(600, 350);
+            frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
         }
     }
 
@@ -292,12 +348,13 @@
             @Override
             public IOException doInBackground() {
                 frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+                startView.disableButtons();
                 mongoUserSetupView.disableButtons();
                 userPropertiesView.disableButtons();
                 thermostatSetup.createMongodbUser(storageUsername, storagePassword);
                 try {
-                    thermostatSetup.createAgentUser(userPropertiesView.getAgentUsername(), userPropertiesView.getAgentPassword());
-                    thermostatSetup.createClientAdminUser(userPropertiesView.getClientUsername(), userPropertiesView.getClientPassword());
+                    thermostatSetup.createAgentUser(agentUsername, agentPassword);
+                    thermostatSetup.createClientAdminUser(clientUsername, clientPassword);
                     thermostatSetup.commit();
                     return null;
                 } catch (IOException e) {
@@ -308,6 +365,7 @@
 
             @Override
             public void done() {
+                startView.enableButtons();
                 mongoUserSetupView.enableButtons();
                 userPropertiesView.enableButtons();
                 frame.setCursor(Cursor.getDefaultCursor());
@@ -317,9 +375,41 @@
         finishAction.execute();
     }
 
+    private void runQuickSetup() {
+        if(thermostatSetup.isWebAppInstalled()) {
+            CredentialGenerator storage = new CredentialGenerator(translator.localize(LocaleResources.MONGO_USER_PREFIX).getContents());
+            CredentialGenerator agent = new CredentialGenerator(translator.localize(LocaleResources.AGENT_USER_PREFIX).getContents());
+            CredentialGenerator client = new CredentialGenerator(translator.localize(LocaleResources.CLIENT_USER_PREFIX).getContents());
+
+            storageUsername = storage.generateRandomUsername();
+            storagePassword = storage.generateRandomPassword();
+            agentUsername = agent.generateRandomUsername();
+            agentPassword = agent.generateRandomPassword();
+            clientUsername = client.generateRandomUsername();
+            clientPassword = client.generateRandomPassword();
+        } else {
+            CredentialGenerator user = new CredentialGenerator(translator.localize(LocaleResources.USER_PREFIX).getContents());
+
+            String username = user.generateRandomUsername();
+            char[] password = user.generateRandomPassword();
+            storageUsername = username;
+            storagePassword = password;
+            agentUsername = username;
+            agentPassword = password;
+            clientUsername = username;
+            clientPassword = password;
+        }
+
+        setupCompleteView.setClientCredentials(clientUsername, clientPassword);
+        setupCompleteView.setAgentCredentials(agentUsername, agentPassword);
+
+        runSetup();
+    }
+
     private void showView(SetupView view) {
         mainView.add(view.getUiComponent(), BorderLayout.CENTER);
-        view.setTitleAndProgress(title, progress);
+        view.setTitle(title);
+        view.setProgress(progress);
         view.setDefaultButton();
         view.focusInitialComponent();
         mainView.revalidate();
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/StartView.java	Fri Sep 04 13:06:49 2015 -0400
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/StartView.java	Fri Sep 04 14:57:14 2015 -0400
@@ -44,11 +44,13 @@
 import javax.swing.BorderFactory;
 import javax.swing.Box;
 import javax.swing.BoxLayout;
+import javax.swing.ButtonGroup;
 import javax.swing.ImageIcon;
 import javax.swing.JButton;
 import javax.swing.JEditorPane;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
+import javax.swing.JRadioButton;
 import javax.swing.JScrollPane;
 import javax.swing.event.HyperlinkEvent;
 import javax.swing.event.HyperlinkListener;
@@ -68,15 +70,19 @@
     private JButton nextBtn;
     private JButton cancelBtn;
     private JButton moreInfoBtn;
+    private JRadioButton quickSetupBtn;
+    private JRadioButton customSetupBtn;
 
     private JPanel toolbar;
     private JEditorPane thermostatBlurb;
     private JPanel midPanel;
+
     private static final String THERMOSTAT_LOGO = "thermostat.png";
     private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
     private static final String SHOW_MORE = "Show More";
     private static final String SHOW_LESS = "Show Less";
     private static final String PROGRESS = "Step 1 of 3";
+    private static final String FAST_TRACK_PROGRESS = "Step 1 of 2";
 
     public StartView(LayoutManager layout) {
         super(layout);
@@ -86,20 +92,23 @@
     }
 
     @Override
-    public void setTitleAndProgress(JLabel title, JLabel progress) {
+    public void setTitle(JLabel title) {
         title.setText(translator.localize(LocaleResources.WELCOME_SCREEN_TITLE).getContents());
-        progress.setText(PROGRESS);
+    }
+
+    @Override
+    public void setProgress(JLabel progress) {
+        if (quickSetupBtn.isSelected()) {
+            progress.setText(FAST_TRACK_PROGRESS);
+        } else {
+            progress.setText(PROGRESS);
+        }
     }
 
     private void createMidPanel() {
         thermostatBlurb = new JEditorPane();
         thermostatBlurb.setEditorKit(JEditorPane.createEditorKitForContentType("text/html"));
         thermostatBlurb.setEditable(false);
-
-        moreInfoBtn = new JButton();
-        moreInfoBtn.setAlignmentX(Component.LEFT_ALIGNMENT);
-        showMoreInfo(false);
-
         thermostatBlurb.addHyperlinkListener(new HyperlinkListener() {
             public void hyperlinkUpdate(HyperlinkEvent e) {
                 if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
@@ -117,11 +126,38 @@
         JScrollPane scrollPane = new ThermostatScrollPane(thermostatBlurb);
         scrollPane.setAlignmentX(Component.LEFT_ALIGNMENT);
 
+        moreInfoBtn = new JButton();
+        moreInfoBtn.setPreferredSize(new Dimension(150, 30));
+        moreInfoBtn.setAlignmentX(Component.LEFT_ALIGNMENT);
+        showMoreInfo(false);
+
+        //Create radio buttons.
+        int radioBtnOffset = SetupWindow.getFrameWidth() / 3;
+
+        quickSetupBtn = new JRadioButton(translator.localize(LocaleResources.QUICK_SETUP).getContents());
+        quickSetupBtn.setToolTipText(translator.localize(LocaleResources.QUICK_SETUP_INFO).getContents());
+        quickSetupBtn.setAlignmentX(Component.LEFT_ALIGNMENT);
+        quickSetupBtn.setBorder(BorderFactory.createEmptyBorder(0, radioBtnOffset, 0, 0));
+        quickSetupBtn.setSelected(true);
+
+        customSetupBtn = new JRadioButton(translator.localize(LocaleResources.CUSTOM_SETUP).getContents());
+        customSetupBtn.setToolTipText(translator.localize(LocaleResources.CUSTOM_SETUP_INFO).getContents());
+        customSetupBtn.setAlignmentX(Component.LEFT_ALIGNMENT);
+        customSetupBtn.setBorder(BorderFactory.createEmptyBorder(0, radioBtnOffset, 0, 0));
+
+        //Group the radio buttons.
+        ButtonGroup setupOptionsGroup = new ButtonGroup();
+        setupOptionsGroup.add(quickSetupBtn);
+        setupOptionsGroup.add(customSetupBtn);
+
         midPanel = new JPanel();
         midPanel.setLayout(new BoxLayout(midPanel, BoxLayout.Y_AXIS));
         midPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
         midPanel.add(scrollPane);
         midPanel.add(moreInfoBtn);
+        midPanel.add(quickSetupBtn);
+        midPanel.add(Box.createRigidArea(new Dimension(0, 5)));
+        midPanel.add(customSetupBtn);
 
         this.add(midPanel, BorderLayout.CENTER);
     }
@@ -151,7 +187,7 @@
         StringBuilder text = new StringBuilder();
 
         text.append("<html>");
-        if(setDetailed) {
+        if (setDetailed) {
             text.append(translator.localize(LocaleResources.THERMOSTAT_BLURB).getContents());
             moreInfoBtn.setText(SHOW_LESS);
         } else {
@@ -159,9 +195,9 @@
             moreInfoBtn.setText(SHOW_MORE);
         }
         text.append("<center><a href=\"\">")
-                .append(userGuideURL)
-                .append("</a></center>")
-                .append("</html>").toString();
+            .append(userGuideURL)
+            .append("</a></center>")
+            .append("</html>").toString();
 
         thermostatBlurb.setText(text.toString());
     }
@@ -193,4 +229,28 @@
         nextBtn.requestFocusInWindow();
     }
 
+    public boolean isQuickSetupSelected() {
+        return quickSetupBtn.isSelected();
+    }
+
+    public JRadioButton getCustomSetupBtn() {
+        return customSetupBtn;
+    }
+
+    public JRadioButton getQuickSetupBtn() {
+        return quickSetupBtn;
+    }
+
+    public void enableButtons() {
+        nextBtn.setEnabled(true);
+        quickSetupBtn.setEnabled(true);
+        customSetupBtn.setEnabled(true);
+    }
+
+    public void disableButtons() {
+        nextBtn.setEnabled(false);
+        quickSetupBtn.setEnabled(false);
+        customSetupBtn.setEnabled(false);
+    }
+
 }
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/UserPropertiesView.java	Fri Sep 04 13:06:49 2015 -0400
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/UserPropertiesView.java	Fri Sep 04 14:57:14 2015 -0400
@@ -61,12 +61,9 @@
     private JButton cancelBtn;
     private JPanel toolbar;
     private JPanel midPanel;
-    private CredentialPanel clientInfoPanel;
-    private CredentialPanel agentInfoPanel;
+    private InputCredentialPanel clientInfoPanel;
+    private InputCredentialPanel agentInfoPanel;
 
-    private static final String DEFAULT_CLIENT_USER = "client-tester";
-    private static final String DEFAULT_AGENT_USER = "agent-tester";
-    private static final char[] DEFAULT_USER_PASSWORD = new char[] {'t', 'e', 's', 't', 'e', 'r'};
     private static final String THERMOSTAT_LOGO = "thermostat.png";
     private static final String PROGRESS = "Step 3 of 3";
     private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
@@ -97,30 +94,32 @@
             }
         };
         clientInfoPanel.getUsernameField().getDocument().addDocumentListener(inputValidator);
-        clientInfoPanel.getPasswordField1().getDocument().addDocumentListener(inputValidator);
-        clientInfoPanel.getPasswordField2().getDocument().addDocumentListener(inputValidator);
+        clientInfoPanel.getPasswordField().getDocument().addDocumentListener(inputValidator);
+        clientInfoPanel.getPasswordConfirmField().getDocument().addDocumentListener(inputValidator);
         agentInfoPanel.getUsernameField().getDocument().addDocumentListener(inputValidator);
-        agentInfoPanel.getPasswordField1().getDocument().addDocumentListener(inputValidator);
-        agentInfoPanel.getPasswordField2().getDocument().addDocumentListener(inputValidator);
+        agentInfoPanel.getPasswordField().getDocument().addDocumentListener(inputValidator);
+        agentInfoPanel.getPasswordConfirmField().getDocument().addDocumentListener(inputValidator);
     }
 
     @Override
-    public void setTitleAndProgress(JLabel title, JLabel progress) {
+    public void setTitle(JLabel title) {
         title.setText(translator.localize(LocaleResources.USERS_SETUP_TITLE).getContents());
+    }
+
+    @Override
+    public void setProgress(JLabel progress) {
         progress.setText(PROGRESS);
     }
 
     public void createMidPanel() {
-        clientInfoPanel = new CredentialPanel(
+        clientInfoPanel = new InputCredentialPanel(
             translator.localize(LocaleResources.CLIENT_CRED_TITLE).getContents(),
             translator.localize(LocaleResources.CLIENT_HELP_INFO).getContents(),
-            DEFAULT_CLIENT_USER,
-            DEFAULT_USER_PASSWORD);
-        agentInfoPanel = new CredentialPanel(
+            translator.localize(LocaleResources.CLIENT_USER_PREFIX).getContents());
+        agentInfoPanel = new InputCredentialPanel(
             translator.localize(LocaleResources.AGENT_CRED_TITLE).getContents(),
             translator.localize(LocaleResources.AGENT_HELP_INFO).getContents(),
-            DEFAULT_AGENT_USER,
-            DEFAULT_USER_PASSWORD);
+            translator.localize(LocaleResources.AGENT_USER_PREFIX).getContents());
 
         midPanel = new JPanel();
         midPanel.setLayout(new BoxLayout(midPanel, BoxLayout.PAGE_AXIS));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/model/CredentialGenerator.java	Fri Sep 04 14:57:14 2015 -0400
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2012-2015 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.setup.command.internal.model;
+
+import java.security.SecureRandom;
+
+public class CredentialGenerator {
+    private SecureRandom random;
+    private final String usernamePrefix;
+
+    static final char[] VALID_CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".toCharArray();
+    private static final int usernameSuffixLength = 8;
+    private static final int passwordLength = 8;
+
+    public CredentialGenerator(String usernamePrefix) {
+        this.usernamePrefix = usernamePrefix;
+        random = new SecureRandom();
+    }
+
+    public String generateRandomUsername() {
+        String usernameSuffix = String.valueOf(generateRandomString(usernameSuffixLength));
+        return usernamePrefix + "-" + usernameSuffix;
+    }
+
+    public char[] generateRandomPassword() {
+        return generateRandomString(passwordLength);
+    }
+
+    private char[] generateRandomString(int length) {
+        char[] result = new char[length];
+        for (int i = 0; i < result.length; i++) {
+            int randomIndex = random.nextInt(VALID_CHARACTERS.length);
+            result[i] = VALID_CHARACTERS[randomIndex];
+        }
+        return result;
+    }
+}
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/locale/LocaleResources.java	Fri Sep 04 13:06:49 2015 -0400
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/locale/LocaleResources.java	Fri Sep 04 14:57:14 2015 -0400
@@ -45,6 +45,7 @@
     WELCOME_SCREEN_TITLE,
     MONGO_SETUP_TITLE,
     USERS_SETUP_TITLE,
+    SETUP_COMPLETE_TITLE,
     MONGO_CRED_TITLE,
     CLIENT_CRED_TITLE,
     AGENT_CRED_TITLE,
@@ -69,6 +70,14 @@
     USERNAME,
     PASSWORD,
     VERIFY_PASSWORD,
+    QUICK_SETUP,
+    CUSTOM_SETUP,
+    QUICK_SETUP_INFO,
+    CUSTOM_SETUP_INFO,
+    USER_PREFIX,
+    MONGO_USER_PREFIX,
+    CLIENT_USER_PREFIX,
+    AGENT_USER_PREFIX,
     CLI_SETUP_INTRO,
     CLI_SETUP_PROCEED_QUESTION,
     CLI_SETUP_UNKNOWN_RESPONSE,
--- a/setup/command/src/main/resources/com/redhat/thermostat/setup/locale/strings.properties	Fri Sep 04 13:06:49 2015 -0400
+++ b/setup/command/src/main/resources/com/redhat/thermostat/setup/locale/strings.properties	Fri Sep 04 14:57:14 2015 -0400
@@ -6,6 +6,8 @@
 
 USERS_SETUP_TITLE=Thermostat Users Setup
 
+SETUP_COMPLETE_TITLE=Thermostat Setup Successful
+
 MONGO_CRED_TITLE=MongoDB User
 
 CLIENT_CRED_TITLE=Client User
@@ -79,7 +81,7 @@
 
 DETAILS_MISSING=Please fill in ALL fields
 
-SHOW_PASSWORDS=Show passwords
+SHOW_PASSWORDS=Show password
 
 USE_DEFAULTS=Use Defaults
 
@@ -89,6 +91,22 @@
 
 VERIFY_PASSWORD=Verify Password:
 
+QUICK_SETUP=Quick Setup
+
+CUSTOM_SETUP=Custom Setup
+
+QUICK_SETUP_INFO=Use this option to automatically generate users.
+
+CUSTOM_SETUP_INFO=Use this option to manually set all user credentials.
+
+USER_PREFIX=user
+
+MONGO_USER_PREFIX=mongodb
+
+CLIENT_USER_PREFIX=client
+
+AGENT_USER_PREFIX=agent
+
 CLI_SETUP_INTRO=Thermostat Basics: \n\
  Thermostat is a database backed distributed monitoring \n\
  solution with support for monitoring multiple JVM instances. \n\
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/setup/command/src/test/java/com/redhat/thermostat/setup/command/internal/model/CredentialGeneratorTest.java	Fri Sep 04 14:57:14 2015 -0400
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2012-2015 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.setup.command.internal.model;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertTrue;
+
+public class CredentialGeneratorTest {
+    private CredentialGenerator credentialGenerator;
+    private static final String usernamePrefix = "prefix";
+    private static final int usernameSuffixLength = 8;
+    private static final int passwordLength = 8;
+
+    @Before
+    public void setup() {
+        credentialGenerator = new CredentialGenerator(usernamePrefix);
+    }
+
+    @Test
+    public void testRandomUsernameHasCorrectPrefix() {
+        String randomUsername = credentialGenerator.generateRandomUsername();
+        assertTrue(randomUsername.startsWith(usernamePrefix + "-"));
+    }
+
+    @Test
+    public void testRandomCredentialsHaveCorrectLength() {
+        String randomUsername = credentialGenerator.generateRandomUsername();
+        char[] randomPassword = credentialGenerator.generateRandomPassword();
+
+        assertTrue(randomUsername.length() == usernamePrefix.length() + usernameSuffixLength + 1);
+        assertTrue(randomPassword.length == passwordLength);
+    }
+
+}