Merge branch 'stable-2.12' into stable-2.13

* stable-2.12:
  Do not log exception stack trace when project not in database
  Fix JDBC connection
  Fix configuration documentation formatting
  Remove source_under_test to comply with new BUCK version

Change-Id: I4d4888aed5bb5f787c9c881c8b905b2037395512
diff --git a/BUCK b/BUCK
index b7fea48..749b4c8 100644
--- a/BUCK
+++ b/BUCK
@@ -7,11 +7,8 @@
   '//lib:gson',
   '//lib/commons:dbcp',
 ]
-TEST_DEPS = GERRIT_PLUGIN_API + [
+TEST_DEPS = GERRIT_PLUGIN_API + DEPS + GERRIT_TESTS + [
   ':events-log__plugin',
-  '//lib/easymock:easymock',
-  '//lib:gson',
-  '//lib:truth',
 ]
 
 gerrit_plugin(
@@ -30,7 +27,7 @@
 
 java_library(
   name = 'classpath',
-  deps = list(set(DEPS) | set(TEST_DEPS))
+  deps = TEST_DEPS,
 )
 
 java_test(
diff --git a/lib/BUCK b/lib/BUCK
index 190d931..06f7c02 100644
--- a/lib/BUCK
+++ b/lib/BUCK
@@ -6,37 +6,3 @@
   sha1 = 'ecb6e1f8e4b0e84c4b886c2f14a1500caf309757',
   license = 'Apache2.0',
 )
-
-maven_jar(
-  name = 'guava',
-  id = 'com.google.guava:guava:19.0-rc1',
-  sha1 = '0364538ac107b8943a1f4d68ac50f1b0421bb983',
-  license = 'Apache2.0',
-)
-
-maven_jar(
-  name = 'junit',
-  id = 'junit:junit:4.11',
-  sha1 = '4e031bb61df09069aeb2bffb4019e7a5034a4ee0',
-  license = 'DO_NOT_DISTRIBUTE',
-  exported_deps = [':hamcrest-core'],
-)
-
-maven_jar(
-  name = 'hamcrest-core',
-  id = 'org.hamcrest:hamcrest-core:1.3',
-  sha1 = '42a25dc3219429f0e5d060061f71acb49bf010a0',
-  license = 'DO_NOT_DISTRIBUTE',
-  visibility = ['//lib:junit'],
-)
-
-maven_jar(
-  name = 'truth',
-  id = 'com.google.truth:truth:0.27',
-  sha1 = 'bd17774d2dc0fffa884d42c07d2537e86c67acd6',
-  license = 'DO_NOT_DISTRIBUTE',
-  exported_deps = [
-    ':guava',
-    ':junit',
-  ],
-)
diff --git a/lib/easymock/BUCK b/lib/easymock/BUCK
deleted file mode 100644
index 11d95a4..0000000
--- a/lib/easymock/BUCK
+++ /dev/null
@@ -1,29 +0,0 @@
-include_defs('//bucklets/maven_jar.bucklet')
-
-maven_jar(
-  name = 'easymock',
-  id = 'org.easymock:easymock:3.3.1',
-  sha1 = 'a497d7f00c9af78b72b6d8f24762d9210309148a',
-  license = 'DO_NOT_DISTRIBUTE',
-  deps = [
-    ':cglib-2_2',
-    ':objenesis',
-  ],
-)
-
-maven_jar(
-  name = 'cglib-2_2',
-  id = 'cglib:cglib-nodep:2.2.2',
-  sha1 = '00d456bb230c70c0b95c76fb28e429d42f275941',
-  license = 'DO_NOT_DISTRIBUTE',
-  attach_source = False,
-)
-
-maven_jar(
-  name = 'objenesis',
-  id = 'org.objenesis:objenesis:2.1',
-  sha1 = '87c0ea803b69252868d09308b4618f766f135a96',
-  license = 'DO_NOT_DISTRIBUTE',
-  visibility = ['//lib/powermock:powermock-reflect'],
-  attach_source = False,
-)
diff --git a/lib/gerrit/BUCK b/lib/gerrit/BUCK
index 0a0b2bc..f83d917 100644
--- a/lib/gerrit/BUCK
+++ b/lib/gerrit/BUCK
@@ -1,12 +1,21 @@
 include_defs('//bucklets/maven_jar.bucklet')
 
-VER = '2.12'
+VER = '2.13'
 REPO = MAVEN_CENTRAL
 
 maven_jar(
+  name = 'acceptance-framework',
+  id = 'com.google.gerrit:gerrit-acceptance-framework:' + VER,
+  sha1 = 'a6913a61196a8fccdb45e761f43a0b7e21867c90',
+  license = 'Apache2.0',
+  attach_source = False,
+  repository = REPO,
+)
+
+maven_jar(
   name = 'plugin-api',
   id = 'com.google.gerrit:gerrit-plugin-api:' + VER,
-  sha1 = '8ce1f6e65078bbcf03a1758f96b3ebca19b7fe3c',
+  sha1 = 'e25d55b8f41627c4ae6b9d2069ec398638b219a3',
   license = 'Apache2.0',
   attach_source = False,
   repository = REPO,
diff --git a/src/main/java/com/ericsson/gerrit/plugins/eventslog/EventModule.java b/src/main/java/com/ericsson/gerrit/plugins/eventslog/EventModule.java
index 232a1fc..04b4abd 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/eventslog/EventModule.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/eventslog/EventModule.java
@@ -24,6 +24,7 @@
 
 import java.util.concurrent.ScheduledThreadPoolExecutor;
 
+/** Configures handling for an event queue while providing its pool. */
 public class EventModule extends AbstractModule {
 
   @Override
diff --git a/src/main/java/com/ericsson/gerrit/plugins/eventslog/EventPool.java b/src/main/java/com/ericsson/gerrit/plugins/eventslog/EventPool.java
index 84de1bd..25aeef4 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/eventslog/EventPool.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/eventslog/EventPool.java
@@ -20,6 +20,9 @@
 
 import java.lang.annotation.Retention;
 
+/**
+ * Annotation applied to a ScheduledThreadPoolExecutor.
+ */
 @Retention(RUNTIME)
 @BindingAnnotation
 public @interface EventPool {
diff --git a/src/main/java/com/ericsson/gerrit/plugins/eventslog/EventsLogConfig.java b/src/main/java/com/ericsson/gerrit/plugins/eventslog/EventsLogConfig.java
index c60f4cc..997f86d 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/eventslog/EventsLogConfig.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/eventslog/EventsLogConfig.java
@@ -132,6 +132,7 @@
     return maxTries;
   }
 
+  /** @return the local-store (database) driver which happens to be h2 */
   public String getLocalStoreDriver() {
     return DEFAULT_DRIVER;
   }
diff --git a/src/main/java/com/ericsson/gerrit/plugins/eventslog/EventsLogException.java b/src/main/java/com/ericsson/gerrit/plugins/eventslog/EventsLogException.java
index 8aa0a35..8b270bf 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/eventslog/EventsLogException.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/eventslog/EventsLogException.java
@@ -14,6 +14,7 @@
 
 package com.ericsson.gerrit.plugins.eventslog;
 
+/** Custom exception for events log. */
 public class EventsLogException extends Exception {
   private static final long serialVersionUID = 1L;
 
diff --git a/src/main/java/com/ericsson/gerrit/plugins/eventslog/HttpModule.java b/src/main/java/com/ericsson/gerrit/plugins/eventslog/HttpModule.java
index 32aa9ff..9bec33f 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/eventslog/HttpModule.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/eventslog/HttpModule.java
@@ -16,7 +16,7 @@
 
 import com.google.gerrit.httpd.plugins.HttpPluginModule;
 
-public class HttpModule extends HttpPluginModule {
+class HttpModule extends HttpPluginModule {
   @Override
   protected void configureServlets() {
     serve("/events/").with(EventsRestApiServlet.class);
diff --git a/src/main/java/com/ericsson/gerrit/plugins/eventslog/MalformedQueryException.java b/src/main/java/com/ericsson/gerrit/plugins/eventslog/MalformedQueryException.java
index 7b37be7..668fc29 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/eventslog/MalformedQueryException.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/eventslog/MalformedQueryException.java
@@ -14,6 +14,7 @@
 
 package com.ericsson.gerrit.plugins.eventslog;
 
+/** Custom exception for malformed queries. */
 public class MalformedQueryException extends EventsLogException {
   private static final long serialVersionUID = 1L;
   private static final String MESSAGE =
diff --git a/src/main/java/com/ericsson/gerrit/plugins/eventslog/QueryMaker.java b/src/main/java/com/ericsson/gerrit/plugins/eventslog/QueryMaker.java
index 0e0b6c7..8f1360f 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/eventslog/QueryMaker.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/eventslog/QueryMaker.java
@@ -16,6 +16,7 @@
 
 import java.util.Map;
 
+/** Helps build well-formed database query strings. */
 public interface QueryMaker {
 
   /**
diff --git a/src/main/java/com/ericsson/gerrit/plugins/eventslog/sql/SQLClient.java b/src/main/java/com/ericsson/gerrit/plugins/eventslog/sql/SQLClient.java
index 3f31a22..d4ae595 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/eventslog/sql/SQLClient.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/eventslog/sql/SQLClient.java
@@ -24,11 +24,14 @@
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.concurrent.TimeUnit.SECONDS;
 
+import com.google.common.base.Supplier;
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.ListMultimap;
 import com.google.gerrit.server.events.ProjectEvent;
 import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
 import com.google.inject.Inject;
+import com.google.gerrit.server.events.SupplierSerializer;
 
 import com.ericsson.gerrit.plugins.eventslog.EventsLogException;
 import com.ericsson.gerrit.plugins.eventslog.MalformedQueryException;
@@ -47,6 +50,7 @@
 
 class SQLClient {
   private static final Logger log = LoggerFactory.getLogger(SQLClient.class);
+  private final Gson gson;
   private BasicDataSource ds;
 
   @Inject
@@ -55,6 +59,8 @@
     ds.setDriverClassName(storeDriver);
     ds.setUrl(storeUrl);
     ds.setConnectionProperties(urlOptions);
+    gson = new GsonBuilder()
+        .registerTypeAdapter(Supplier.class, new SupplierSerializer()).create();
   }
 
   /**
@@ -145,8 +151,7 @@
   void storeEvent(ProjectEvent event) throws SQLException {
     storeEvent(event.getProjectNameKey().get(),
         new Timestamp(SECONDS.toMillis(event.eventCreatedOn)),
-        new Gson().toJson(event));
-
+        gson.toJson(event));
   }
 
   /**
diff --git a/src/main/java/com/ericsson/gerrit/plugins/eventslog/sql/SQLQueryMaker.java b/src/main/java/com/ericsson/gerrit/plugins/eventslog/sql/SQLQueryMaker.java
index 621d545..aadf455 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/eventslog/sql/SQLQueryMaker.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/eventslog/sql/SQLQueryMaker.java
@@ -76,15 +76,14 @@
 
   private Date[] parseDates(String dateOne, String dateTwo)
       throws MalformedQueryException, ParseException {
-    Calendar cal = Calendar.getInstance();
-    if (dateOne == null & dateTwo == null) {
+    if (dateOne == null && dateTwo == null) {
       throw new MalformedQueryException();
     }
+    Calendar cal = Calendar.getInstance();
+    Date dOne = dateOne == null ? cal.getTime() : parseDate(dateOne);
+    Date dTwo = dateTwo == null ? cal.getTime() : parseDate(dateTwo);
     Date[] dates = new Date[TWO];
-    Date dOne =
-        dateOne == null && dateTwo != null ? cal.getTime() : parseDate(dateOne);
-    Date dTwo =
-        dateTwo == null && dateOne != null ? cal.getTime() : parseDate(dateTwo);
+
     dates[0] = dOne.compareTo(dTwo) < 0 ? dOne : dTwo;
     dates[1] = dOne.compareTo(dTwo) < 0 ? dTwo : dOne;
     return dates;
diff --git a/src/main/java/com/ericsson/gerrit/plugins/eventslog/sql/SQLStore.java b/src/main/java/com/ericsson/gerrit/plugins/eventslog/sql/SQLStore.java
index 5f24627..9be05fd 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/eventslog/sql/SQLStore.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/eventslog/sql/SQLStore.java
@@ -114,21 +114,21 @@
       throw new ServiceUnavailableException();
     }
     List<SQLEntry> entries = new ArrayList<>();
-    Project.NameKey project = null;
+
     for (Entry<String, Collection<SQLEntry>> entry
         : eventsDb.getEvents(query).asMap().entrySet()) {
+      String projectName = entry.getKey();
       try {
-        project = new Project.NameKey(entry.getKey());
-        if (projectControlFactory.controlFor(project,
+        if (projectControlFactory.controlFor(new Project.NameKey(projectName),
             userProvider.get()).isVisible()) {
           entries.addAll(entry.getValue());
         }
       } catch (NoSuchProjectException e) {
-        log.warn("Database contains a non-existing project, " + project.get()
+        log.warn("Database contains a non-existing project, " + projectName
             + ", removing project from database");
-        eventsDb.removeProjectEvents(project.get());
+        eventsDb.removeProjectEvents(projectName);
       } catch (IOException e) {
-        log.warn("Cannot get project visibility info for " + project.get()
+        log.warn("Cannot get project visibility info for " + projectName
             + " from cache", e);
       }
     }
@@ -167,21 +167,25 @@
         if (e.getCause() instanceof ConnectException
             || e.getMessage().contains("terminating connection")) {
           done = false;
-          retryIfAllowed(failedConnections);
+          try {
+            retryIfAllowed(failedConnections);
+          } catch (InterruptedException e1) {
+            log.warn("Cannot store ChangeEvent for: " + projectName.get()
+                + ": Interrupted");
+            Thread.currentThread().interrupt();
+            return;
+          }
           failedConnections++;
         }
       }
     }
   }
 
-  private void retryIfAllowed(int failedConnections) {
+  private void retryIfAllowed(int failedConnections)
+      throws InterruptedException {
     if (failedConnections < maxTries - 1) {
       log.info("Retrying store event");
-      try {
-        Thread.sleep(waitTime);
-      } catch (InterruptedException e1) {
-        return;
-      }
+      Thread.sleep(waitTime);
     } else {
       log.error("Failed to store event " + maxTries + " times");
       setOnline(false);
diff --git a/src/test/java/com/ericsson/gerrit/plugins/eventslog/EventsLogIT.java b/src/test/java/com/ericsson/gerrit/plugins/eventslog/EventsLogIT.java
new file mode 100644
index 0000000..9bb2834
--- /dev/null
+++ b/src/test/java/com/ericsson/gerrit/plugins/eventslog/EventsLogIT.java
@@ -0,0 +1,49 @@
+// Copyright (C) 2015 Ericsson
+//
+// 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.ericsson.gerrit.plugins.eventslog;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.gerrit.acceptance.PluginDaemonTest;
+
+import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.junit.Test;
+
+import java.io.IOException;
+
+public class EventsLogIT extends PluginDaemonTest {
+
+  @Override
+  protected void beforeTestServerStarts() throws IOException,
+      ConfigInvalidException {
+    // otherwise default ~/db not deleted after => corrupted next test/run
+    setPluginConfigString("storeUrl", "jdbc:h2:" + testSite + "/db/");
+  }
+
+  @Test
+  public void getEventsShallBeConsistent() throws Exception {
+    String events = "/plugins/events-log/events/?t1=1970-01-01;t2=2999-01-01";
+    String change1 = "refs/changes/01/1/1";
+
+    createChange();
+    String response = adminRestSession.get(events).getEntityContent();
+    assertThat(response).contains(change1);
+
+    createChange();
+    response = adminRestSession.get(events).getEntityContent();
+    assertThat(response).contains(change1);
+    assertThat(response).contains("refs/changes/02/2/1");
+  }
+}
diff --git a/src/test/java/com/ericsson/gerrit/plugins/eventslog/sql/SQLStoreTest.java b/src/test/java/com/ericsson/gerrit/plugins/eventslog/sql/SQLStoreTest.java
index dcfec06..d67ebd2 100644
--- a/src/test/java/com/ericsson/gerrit/plugins/eventslog/sql/SQLStoreTest.java
+++ b/src/test/java/com/ericsson/gerrit/plugins/eventslog/sql/SQLStoreTest.java
@@ -19,10 +19,9 @@
 import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.expectLastCall;
 
-import com.google.gerrit.reviewdb.client.Change.Key;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.CurrentUser;
-import com.google.gerrit.server.events.ChangeEvent;
+import com.google.gerrit.server.events.ProjectEvent;
 import com.google.gerrit.server.project.NoSuchProjectException;
 import com.google.gerrit.server.project.ProjectControl;
 import com.google.gson.Gson;
@@ -450,7 +449,7 @@
     expect(cfgMock.getCopyLocal()).andReturn(true).once();
   }
 
-  public class MockEvent extends ChangeEvent {
+  public class MockEvent extends ProjectEvent {
     public String project = "mock project";
 
     MockEvent() {
@@ -466,16 +465,6 @@
     public Project.NameKey getProjectNameKey() {
       return new Project.NameKey(project);
     }
-
-    @Override
-    public Key getChangeKey() {
-      return null;
-    }
-
-    @Override
-    public String getRefName() {
-      return null;
-    }
   }
 
   class PoolMock extends ScheduledThreadPoolExecutor {