Merge "Non-argument constructor for JSON doesn't need to be public"
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/auth/userpass/LoginResult.java b/gerrit-common/src/main/java/com/google/gerrit/common/auth/userpass/LoginResult.java
index dcabf81..4a9ab66 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/auth/userpass/LoginResult.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/auth/userpass/LoginResult.java
@@ -14,7 +14,40 @@
 
 package com.google.gerrit.common.auth.userpass;
 
+import com.google.gerrit.reviewdb.AuthType;
+
 public class LoginResult {
   public boolean success;
   public boolean isNew;
+
+  protected AuthType authType;
+  protected Error error;
+
+  protected LoginResult() {
+  }
+
+  public LoginResult(final AuthType authType) {
+    this.authType = authType;
+  }
+
+  public AuthType getAuthType() {
+    return authType;
+  }
+
+  public void setError(final Error error) {
+    this.error = error;
+    success = error == null;
+  }
+
+  public Error getError() {
+    return error;
+  }
+
+  public static enum Error {
+    /** Username or password are invalid */
+    INVALID_LOGIN,
+
+    /** The authentication server is unavailable or the query to it timed out */
+    AUTHENTICATION_UNAVAILABLE
+  }
 }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/userpass/UserPassMessages.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/userpass/UserPassMessages.java
index ebb15d3..2991dc9 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/userpass/UserPassMessages.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/userpass/UserPassMessages.java
@@ -14,8 +14,10 @@
 
 package com.google.gerrit.client.auth.userpass;
 
+import com.google.gerrit.reviewdb.AuthType;
 import com.google.gwt.i18n.client.Messages;
 
 public interface UserPassMessages extends Messages {
   String signInAt(String hostname);
+  String authenticationUnavailable(AuthType authType);
 }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/userpass/UserPassMessages.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/userpass/UserPassMessages.properties
index ce40ff8..b1eab35 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/userpass/UserPassMessages.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/userpass/UserPassMessages.properties
@@ -1 +1,2 @@
 signInAt = Sign In to Gerrit Code Review at {0}
+authenticationUnavailable = {0} authentication unavailable
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/userpass/UserPassSignInDialog.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/userpass/UserPassSignInDialog.java
index 09d41e5..3463640 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/userpass/UserPassSignInDialog.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/userpass/UserPassSignInDialog.java
@@ -209,7 +209,16 @@
           }
           Location.replace(Location.getPath() + "login" + to);
         } else {
-          showError(Util.C.invalidLogin());
+          final String message;
+          switch (result.getError()) {
+            case AUTHENTICATION_UNAVAILABLE:
+              message = Util.M.authenticationUnavailable(result.getAuthType());
+              break;
+            case INVALID_LOGIN:
+            default:
+              message = Util.C.invalidLogin();
+          }
+          showError(message);
           enable(true);
           password.selectAll();
           Scheduler.get().scheduleDeferred(new ScheduledCommand() {
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/ldap/UserPassAuthServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/ldap/UserPassAuthServiceImpl.java
index e4577c1..a77dfc9 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/ldap/UserPassAuthServiceImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/ldap/UserPassAuthServiceImpl.java
@@ -17,11 +17,14 @@
 import com.google.gerrit.common.auth.userpass.LoginResult;
 import com.google.gerrit.common.auth.userpass.UserPassAuthService;
 import com.google.gerrit.httpd.WebSession;
+import com.google.gerrit.reviewdb.AuthType;
 import com.google.gerrit.server.account.AccountException;
 import com.google.gerrit.server.account.AccountManager;
 import com.google.gerrit.server.account.AccountUserNameException;
 import com.google.gerrit.server.account.AuthRequest;
 import com.google.gerrit.server.account.AuthResult;
+import com.google.gerrit.server.auth.AuthenticationUnavailableException;
+import com.google.gerrit.server.config.AuthConfig;
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
@@ -29,21 +32,23 @@
 class UserPassAuthServiceImpl implements UserPassAuthService {
   private final Provider<WebSession> webSession;
   private final AccountManager accountManager;
+  private final AuthType authType;
 
   @Inject
   UserPassAuthServiceImpl(final Provider<WebSession> webSession,
-      final AccountManager accountManager) {
+      final AccountManager accountManager, final AuthConfig authConfig) {
     this.webSession = webSession;
     this.accountManager = accountManager;
+    this.authType = authConfig.getAuthType();
   }
 
   @Override
   public void authenticate(String username, final String password,
       final AsyncCallback<LoginResult> callback) {
-    LoginResult result = new LoginResult();
+    LoginResult result = new LoginResult(authType);
     if (username == null || "".equals(username.trim()) //
         || password == null || "".equals(password)) {
-      result.success = false;
+      result.setError(LoginResult.Error.INVALID_LOGIN);
       callback.onSuccess(result);
       return;
     }
@@ -62,8 +67,12 @@
       // error screen with error message should be shown to the user
       callback.onFailure(e);
       return;
+    } catch (AuthenticationUnavailableException e) {
+      result.setError(LoginResult.Error.AUTHENTICATION_UNAVAILABLE);
+      callback.onSuccess(result);
+      return;
     } catch (AccountException e) {
-      result.success = false;
+      result.setError(LoginResult.Error.INVALID_LOGIN);
       callback.onSuccess(result);
       return;
     }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/auth/AuthenticationUnavailableException.java b/gerrit-server/src/main/java/com/google/gerrit/server/auth/AuthenticationUnavailableException.java
new file mode 100644
index 0000000..b0b6142
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/auth/AuthenticationUnavailableException.java
@@ -0,0 +1,26 @@
+// Copyright (C) 2011 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.auth;
+
+import com.google.gerrit.server.account.AccountException;
+
+/** A query to the authentication server failed */
+public class AuthenticationUnavailableException extends AccountException {
+  private static final long serialVersionUID = 1L;
+
+  public AuthenticationUnavailableException(final String message, final Throwable why) {
+    super(message, why);
+  }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/LdapRealm.java b/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/LdapRealm.java
index 72d7cb0..ac2bf01 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/LdapRealm.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/LdapRealm.java
@@ -27,6 +27,7 @@
 import com.google.gerrit.server.account.AuthRequest;
 import com.google.gerrit.server.account.EmailExpander;
 import com.google.gerrit.server.account.Realm;
+import com.google.gerrit.server.auth.AuthenticationUnavailableException;
 import com.google.gerrit.server.auth.ldap.Helper.LdapSchema;
 import com.google.gerrit.server.cache.Cache;
 import com.google.gerrit.server.cache.EntryCreator;
@@ -238,7 +239,7 @@
       }
     } catch (NamingException e) {
       log.error("Cannot query LDAP to autenticate user", e);
-      throw new AccountException("Cannot query LDAP for account", e);
+      throw new AuthenticationUnavailableException("Cannot query LDAP for account", e);
     }
   }