Merge branch 'stable-2.6'

* stable-2.6:
  Reduce DOM nodes when updating reviewed status
  Fix PatchScreen leak when moving between files
  Use try/finally to ensure oldValue is cleared
  Remove unused HasValueChangeHandlers from PatchScriptSettingsPanel
  Make ListenableAccountDiffPreference final in PatchScriptSettingsPanel
  Remove unused setPreferences method on PatchTable
  init: Guess JDBC driver class if not configured
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchTable.java
index b2e8b01..d47e2c1 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchTable.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchTable.java
@@ -48,7 +48,9 @@
 import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 public class PatchTable extends Composite {
   public interface PatchValidator {
@@ -80,6 +82,7 @@
   private String savePointerId;
   private PatchSet.Id base;
   private List<Patch> patchList;
+  private Map<Patch.Key, Integer> patchMap;
   private ListenableAccountDiffPreference listenablePrefs;
 
   private List<ClickHandler> clickHandlers;
@@ -97,18 +100,25 @@
   }
 
   public int indexOf(Patch.Key patch) {
-    for (int i = 0; i < patchList.size(); i++) {
-      if (patchList.get(i).getKey().equals(patch)) {
-        return i;
+    Integer i = patchMap().get(patch);
+    return i != null ? i : -1;
+  }
+
+  private Map<Key, Integer> patchMap() {
+    if (patchMap == null) {
+      patchMap = new HashMap<Patch.Key, Integer>();
+      for (int i = 0; i < patchList.size(); i++) {
+        patchMap.put(patchList.get(i).getKey(), i);
       }
     }
-    return -1;
+    return patchMap;
   }
 
   public void display(PatchSet.Id base, PatchSetDetail detail) {
     this.base = base;
     this.detail = detail;
     this.patchList = detail.getPatches();
+    this.patchMap = null;
     myTable = null;
 
     final DisplayCommand cmd = new DisplayCommand(patchList, base);
@@ -293,10 +303,6 @@
     return listenablePrefs;
   }
 
-  public void setPreferences(ListenableAccountDiffPreference prefs) {
-    listenablePrefs = prefs;
-  }
-
   private class MyTable extends NavigationTable<Patch> {
     private static final int C_PATH = 2;
     private static final int C_DRAFT = 3;
@@ -330,36 +336,33 @@
     }
 
     void updateReviewedStatus(final Patch.Key patchKey, boolean reviewed) {
-      final int row = findRow(patchKey);
-      if (0 <= row) {
-        final Patch patch = getRowItem(row);
-        if (patch != null) {
-          patch.setReviewedByCurrentUser(reviewed);
-
+      int idx = patchMap().get(patchKey);
+      if (0 <= idx) {
+        Patch patch = patchList.get(idx);
+        if (patch.isReviewedByCurrentUser() != reviewed) {
+          int row = idx + 1;
           int col = C_SIDEBYSIDE + 2;
           if (patch.getPatchType() == Patch.PatchType.BINARY) {
             col = C_SIDEBYSIDE + 3;
           }
-
           if (reviewed) {
             table.setWidget(row, col, new Image(Gerrit.RESOURCES.greenCheck()));
           } else {
             table.clearCell(row, col);
           }
+          patch.setReviewedByCurrentUser(reviewed);
         }
       }
     }
 
     void notifyDraftDelta(final Patch.Key key, final int delta) {
-      final int row = findRow(key);
-      if (0 <= row) {
-        final Patch p = getRowItem(row);
-        if (p != null) {
-          p.setDraftCount(p.getDraftCount() + delta);
-          final SafeHtmlBuilder m = new SafeHtmlBuilder();
-          appendCommentCount(m, p);
-          SafeHtml.set(table, row, C_DRAFT, m);
-        }
+      int idx = patchMap().get(key);
+      if (0 <= idx) {
+        Patch p = patchList.get(idx);
+        p.setDraftCount(p.getDraftCount() + delta);
+        SafeHtmlBuilder m = new SafeHtmlBuilder();
+        appendCommentCount(m, p);
+        SafeHtml.set(table, idx + 1, C_DRAFT, m);
       }
     }
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java
index b18946b..2252483 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java
@@ -118,6 +118,7 @@
   /** The index of the file we are currently looking at among the fileList */
   private int patchIndex;
   private ListenableAccountDiffPreference prefs;
+  private HandlerRegistration prefsHandler;
 
   /** Keys that cause an action on this screen */
   private KeyCommandSet keysNavigation;
@@ -146,19 +147,12 @@
     idSideB = id.getParentKey();
     this.patchIndex = patchIndex;
 
-    prefs = fileList != null ? fileList.getPreferences() :
-                               new ListenableAccountDiffPreference();
+    prefs = fileList != null
+        ? fileList.getPreferences()
+        : new ListenableAccountDiffPreference();
     if (Gerrit.isSignedIn()) {
       prefs.reset();
     }
-    prefs.addValueChangeHandler(
-        new ValueChangeHandler<AccountDiffPreference>() {
-          @Override
-          public void onValueChange(ValueChangeEvent<AccountDiffPreference> event) {
-            update(event.getValue());
-          }
-        });
-
     reviewedPanels = new ReviewedPanels();
     settingsPanel = new PatchScriptSettingsPanel(prefs);
   }
@@ -306,6 +300,10 @@
 
   @Override
   protected void onUnload() {
+    if (prefsHandler != null) {
+      prefsHandler.removeHandler();
+      prefsHandler = null;
+    }
     if (regNavigation != null) {
       regNavigation.removeHandler();
       regNavigation = null;
@@ -500,6 +498,15 @@
   @Override
   public void onShowView() {
     super.onShowView();
+    if (prefsHandler == null) {
+      prefsHandler = prefs.addValueChangeHandler(
+          new ValueChangeHandler<AccountDiffPreference>() {
+            @Override
+            public void onValueChange(ValueChangeEvent<AccountDiffPreference> event) {
+              update(event.getValue());
+            }
+          });
+    }
     if (intralineFailure) {
       intralineFailure = false;
       new ErrorDialog(PatchUtil.C.intralineFailure()).show();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScriptSettingsPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScriptSettingsPanel.java
index a689259..8e76e47 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScriptSettingsPanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScriptSettingsPanel.java
@@ -27,10 +27,6 @@
 import com.google.gwt.event.dom.client.KeyCodes;
 import com.google.gwt.event.dom.client.KeyPressEvent;
 import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
-import com.google.gwt.event.logical.shared.ValueChangeEvent;
-import com.google.gwt.event.logical.shared.ValueChangeHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.uibinder.client.UiBinder;
 import com.google.gwt.uibinder.client.UiField;
 import com.google.gwt.uibinder.client.UiHandler;
@@ -43,14 +39,13 @@
 import com.google.gwt.user.client.ui.Widget;
 import com.google.gwtjsonrpc.common.VoidResult;
 
-public class PatchScriptSettingsPanel extends Composite implements
-    HasValueChangeHandlers<AccountDiffPreference> {
+public class PatchScriptSettingsPanel extends Composite {
   private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
 
   interface MyUiBinder extends UiBinder<Widget, PatchScriptSettingsPanel> {
   }
 
-  private ListenableAccountDiffPreference listenablePrefs;
+  private final ListenableAccountDiffPreference listenablePrefs;
   private boolean enableIntralineDifference = true;
   private boolean enableSmallFileFeatures = true;
 
@@ -139,12 +134,6 @@
     display();
   }
 
-  @Override
-  public HandlerRegistration addValueChangeHandler(
-      ValueChangeHandler<AccountDiffPreference> handler) {
-    return super.addHandler(handler, ValueChangeEvent.getType());
-  }
-
   public void setEnabled(final boolean on) {
     if (on) {
       setEnabledCounter++;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ListenableOldValue.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ListenableOldValue.java
index 5c3e127..47bca2b 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ListenableOldValue.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ListenableOldValue.java
@@ -23,8 +23,11 @@
   }
 
   public void set(final T value) {
-    oldValue = get();
-    super.set(value);
-    oldValue = null; // allow it to be gced before the next event
+    try {
+      oldValue = get();
+      super.set(value);
+    } finally {
+      oldValue = null; // allow it to be gced before the next event
+    }
   }
 }
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/JDBCInitializer.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/JDBCInitializer.java
index 94425ac1..ac3e728 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/JDBCInitializer.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/JDBCInitializer.java
@@ -16,13 +16,28 @@
 
 import static com.google.gerrit.pgm.init.InitUtil.username;
 
-class JDBCInitializer implements DatabaseConfigInitializer {
+import com.google.common.base.Strings;
 
+class JDBCInitializer implements DatabaseConfigInitializer {
   @Override
-  public void initConfig(Section databaseSection) {
-    databaseSection.string("Driver class name", "driver", null);
-    databaseSection.string("URL", "url", null);
-    databaseSection.string("Database username", "username", username());
-    databaseSection.password("username", "password");
+  public void initConfig(Section database) {
+    database.string("URL", "url", null);
+    guessDriver(database);
+    database.string("Driver class name", "driver", null);
+    database.string("Database username", "username", username());
+    database.password("username", "password");
+  }
+
+  private void guessDriver(Section database) {
+    String url = Strings.emptyToNull(database.get("url"));
+    if (url != null && Strings.isNullOrEmpty(database.get("driver"))) {
+      if (url.startsWith("jdbc:h2:")) {
+        database.set("driver", "org.h2.Driver");
+      } else if (url.startsWith("jdbc:mysql:")) {
+        database.set("driver", "com.mysql.jdbc.Driver");
+      } else if (url.startsWith("jdbc:postgresql:")) {
+        database.set("driver", "org.postgresql.Driver");
+      }
+    }
   }
 }