Merge branch 'stable-2.10' into stable-2.11

* stable-2.10:
  Maven: use same version number for plugin version and API version
  Maven: Add missing junit dependency
  Consume API version 2.10
  Consume API version 2.9

Conflicts:
	lib/gerrit/BUCK
	pom.xml

Change-Id: If133617f4e8a46821790d0e6ce3d2c576979654e
diff --git a/BUCK b/BUCK
index 066e743..b28f661 100644
--- a/BUCK
+++ b/BUCK
@@ -17,6 +17,15 @@
   ]
 )
 
+java_test(
+  name = 'cookbook_tests',
+  srcs = glob(['src/test/java/**/*.java']),
+  deps = [
+    ':cookbook-plugin__plugin',
+    '//lib:junit',
+  ],
+)
+
 # TODO(davido): is this needed?
 # requires for bucklets/tools/eclipse/project.py to work
 # not sure, if this does something useful in standalone context
diff --git a/lib/gerrit/BUCK b/lib/gerrit/BUCK
index 80c9229..89c75df 100644
--- a/lib/gerrit/BUCK
+++ b/lib/gerrit/BUCK
@@ -1,7 +1,7 @@
 include_defs('//bucklets/maven_jar.bucklet')
 
-VER = '2.10'
-REPO = MAVEN_CENTRAL
+VER = '2.11-SNAPSHOT'
+REPO = MAVEN_LOCAL
 
 maven_jar(
   name = 'plugin-api',
diff --git a/lib/gwt/BUCK b/lib/gwt/BUCK
index e07bf39..394ed92 100644
--- a/lib/gwt/BUCK
+++ b/lib/gwt/BUCK
@@ -1,11 +1,11 @@
 include_defs('//bucklets/maven_jar.bucklet')
 
-VER = '2.6.1'
+VER = '2.7.0'
 
 maven_jar(
   name = 'user',
   id = 'com.google.gwt:gwt-user:' + VER,
-  sha1 = 'c078b1b8cc0281214b0eb458d2c283d039374fad',
+  sha1 = 'bdc7af42581745d3d79c2efe0b514f432b998a5b',
   license = 'Apache2.0',
   attach_source = False,
   deps = [
@@ -17,7 +17,7 @@
 maven_jar(
   name = 'dev',
   id = 'com.google.gwt:gwt-dev:' + VER,
-  sha1 = 'db237e4be0aa1fe43425d2c51ab5485dba211ddd',
+  sha1 = 'c2c3dd5baf648a0bb199047a818be5e560f48982',
   license = 'Apache2.0',
   attach_source = False,
   exclude = ['org/eclipse/jetty/*'],
diff --git a/lib/ow2/BUCK b/lib/ow2/BUCK
new file mode 100644
index 0000000..db6c76c
--- /dev/null
+++ b/lib/ow2/BUCK
@@ -0,0 +1,32 @@
+include_defs('//bucklets/maven_jar.bucklet')
+
+VERSION = '5.0.3'
+
+maven_jar(
+  name = 'ow2-asm',
+  id = 'org.ow2.asm:asm:' + VERSION,
+  sha1 = 'dcc2193db20e19e1feca8b1240dbbc4e190824fa',
+  license = 'ow2',
+)
+
+maven_jar(
+  name = 'ow2-asm-analysis',
+  id = 'org.ow2.asm:asm-analysis:' + VERSION,
+  sha1 = 'c7126aded0e8e13fed5f913559a0dd7b770a10f3',
+  license = 'ow2',
+)
+
+maven_jar(
+  name = 'ow2-asm-tree',
+  id = 'org.ow2.asm:asm-tree:' + VERSION,
+  sha1 = '287749b48ba7162fb67c93a026d690b29f410bed',
+  license = 'ow2',
+)
+
+maven_jar(
+  name = 'ow2-asm-util',
+  id = 'org.ow2.asm:asm-util:' + VERSION,
+  sha1 = '1512e5571325854b05fb1efce1db75fcced54389',
+  license = 'ow2',
+)
+
diff --git a/pom.xml b/pom.xml
index d30c292..b765d38 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,7 +22,7 @@
   <groupId>com.googlesource.gerrit.plugins</groupId>
   <artifactId>cookbook-plugin</artifactId>
   <packaging>jar</packaging>
-  <version>2.10</version>
+  <version>2.11-SNAPSHOT</version>
   <properties>
     <Gerrit-ApiType>plugin</Gerrit-ApiType>
     <Gerrit-ApiVersion>${project.version}</Gerrit-ApiVersion>
@@ -69,7 +69,7 @@
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>gwt-maven-plugin</artifactId>
-        <version>2.6.1</version>
+        <version>2.7.0</version>
         <configuration>
           <module>com.googlesource.gerrit.plugins.cookbook.HelloForm</module>
           <disableClassMetadata>true</disableClassMetadata>
@@ -99,11 +99,12 @@
       <groupId>com.google.gerrit</groupId>
       <artifactId>gerrit-plugin-gwtui</artifactId>
       <version>${Gerrit-ApiVersion}</version>
+      <scope>provided</scope>
     </dependency>
     <dependency>
       <groupId>com.google.gwt</groupId>
       <artifactId>gwt-user</artifactId>
-      <version>2.6.1</version>
+      <version>2.7.0</version>
       <scope>provided</scope>
     </dependency>
     <dependency>
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/Greetings.java b/src/main/java/com/googlesource/gerrit/plugins/cookbook/Greetings.java
index 6e02c05..58a9017 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/cookbook/Greetings.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/Greetings.java
@@ -14,14 +14,14 @@
 
 package com.googlesource.gerrit.plugins.cookbook;
 
-import java.util.ArrayList;
-import java.util.Collection;
-
 import com.google.gerrit.extensions.restapi.Response;
 import com.google.gerrit.extensions.restapi.RestReadView;
 import com.google.gerrit.server.change.RevisionResource;
 import com.google.inject.Inject;
 
+import java.util.ArrayList;
+import java.util.Collection;
+
 class Greetings implements RestReadView<RevisionResource> {
 
   @Inject
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/HashtagValidator.java b/src/main/java/com/googlesource/gerrit/plugins/cookbook/HashtagValidator.java
new file mode 100644
index 0000000..52f8680
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/HashtagValidator.java
@@ -0,0 +1,42 @@
+// Copyright (C) 2014 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.googlesource.gerrit.plugins.cookbook;
+
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.server.validators.HashtagValidationListener;
+import com.google.gerrit.server.validators.ValidationException;
+
+import java.util.Set;
+
+public class HashtagValidator implements HashtagValidationListener {
+
+  @Override
+  public void validateHashtags(Change change, Set<String> toAdd, Set<String> toRemove)
+      throws ValidationException {
+    if (change.getProject().get().equals("plugins/cookbook")) {
+      if (toAdd.size() > 0) {
+        for (String hashtag : toAdd) {
+          if (!hashtag.startsWith("cookbook-")) {
+            throw new ValidationException("Invalid cookbook hashtag: " + hashtag);
+          }
+        }
+      }
+
+      if (toRemove.size() > 0) {
+        throw new ValidationException("Cannot remove cookbook hashtags");
+      }
+    }
+  }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/HelloForm.gwt.xml b/src/main/java/com/googlesource/gerrit/plugins/cookbook/HelloForm.gwt.xml
index 6616bca..954f97b 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/cookbook/HelloForm.gwt.xml
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/HelloForm.gwt.xml
@@ -18,6 +18,7 @@
   <!-- Inherit the core Web Toolkit stuff.                        -->
   <inherits name="com.google.gwt.user.User"/>
   <!-- Other module inherits                                      -->
+  <inherits name="com.google.gerrit.GerritGwtUICommon"/>
   <inherits name="com.google.gerrit.Plugin"/>
   <inherits name="com.google.gwt.http.HTTP"/>
   <inherits name="com.google.gwt.json.JSON"/>
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/HelloProjectAction.java b/src/main/java/com/googlesource/gerrit/plugins/cookbook/HelloProjectAction.java
index e977113..8057bb7 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/cookbook/HelloProjectAction.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/HelloProjectAction.java
@@ -14,7 +14,7 @@
 
 package com.googlesource.gerrit.plugins.cookbook;
 
-import com.google.common.base.Objects;
+import com.google.common.base.MoreObjects;
 import com.google.common.base.Strings;
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.extensions.webui.UiAction;
@@ -47,7 +47,7 @@
     return String.format("%s %s from project %s!",
         greeting,
         Strings.isNullOrEmpty(input.message)
-            ? Objects.firstNonNull(user.get().getUserName(), "world")
+            ? MoreObjects.firstNonNull(user.get().getUserName(), "world")
             : input.message,
         rsrc.getName());
   }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/HelloRevisionAction.java b/src/main/java/com/googlesource/gerrit/plugins/cookbook/HelloRevisionAction.java
index 21182ed..0cfbc10 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/cookbook/HelloRevisionAction.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/HelloRevisionAction.java
@@ -14,7 +14,7 @@
 
 package com.googlesource.gerrit.plugins.cookbook;
 
-import com.google.common.base.Objects;
+import com.google.common.base.MoreObjects;
 import com.google.common.base.Strings;
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.extensions.webui.UiAction;
@@ -47,7 +47,7 @@
     return String.format("%s %s from change %s, patch set %d!",
         greeting,
         Strings.isNullOrEmpty(input.message)
-            ? Objects.firstNonNull(user.get().getUserName(), "world")
+            ? MoreObjects.firstNonNull(user.get().getUserName(), "world")
             : input.message,
         rev.getChange().getId().toString(),
         rev.getPatchSet().getPatchSetId());
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/HelloTopMenu.java b/src/main/java/com/googlesource/gerrit/plugins/cookbook/HelloTopMenu.java
index 4d98601..96e22d8 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/cookbook/HelloTopMenu.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/HelloTopMenu.java
@@ -14,13 +14,13 @@
 
 package com.googlesource.gerrit.plugins.cookbook;
 
-import java.util.List;
-
 import com.google.common.collect.Lists;
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.webui.TopMenu;
 import com.google.inject.Inject;
 
+import java.util.List;
+
 public class HelloTopMenu implements TopMenu {
   private final List<MenuEntry> menuEntries;
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/HelloWeblink.java b/src/main/java/com/googlesource/gerrit/plugins/cookbook/HelloWeblink.java
index 3a27191..0137ffa 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/cookbook/HelloWeblink.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/HelloWeblink.java
@@ -14,28 +14,42 @@
 
 package com.googlesource.gerrit.plugins.cookbook;
 
+import com.google.gerrit.extensions.common.WebLinkInfo;
+import com.google.gerrit.extensions.webui.BranchWebLink;
 import com.google.gerrit.extensions.webui.PatchSetWebLink;
 import com.google.gerrit.extensions.webui.ProjectWebLink;
 
-public class HelloWeblink implements PatchSetWebLink, ProjectWebLink {
+public class HelloWeblink implements PatchSetWebLink, ProjectWebLink, BranchWebLink {
   private String name = "HelloLink";
   private String placeHolderUrlProject =
       "http://my.hellolink.com/project=%s";
+  private String placeHolderUrlProjectBranch =
+      "http://my.hellolink.com/project=%s-branch=%s";
   private String placeHolderUrlProjectCommit =
       placeHolderUrlProject + "/commit=%s";
+  private String myImageUrl = "http://placehold.it/16x16.gif";
 
   @Override
-  public String getLinkName() {
-    return name ;
+  public WebLinkInfo getBranchWebLink(String projectName, String branchName) {
+    return new WebLinkInfo(name,
+        myImageUrl,
+        String.format(placeHolderUrlProjectBranch, projectName, branchName),
+        Target.BLANK);
   }
 
   @Override
-  public String getPatchSetUrl(String project, String commit) {
-    return String.format(placeHolderUrlProjectCommit, project, commit);
+  public WebLinkInfo getProjectWeblink(String projectName) {
+    return new WebLinkInfo(name,
+        myImageUrl,
+        String.format(placeHolderUrlProject, projectName),
+        Target.BLANK);
   }
 
   @Override
-  public String getProjectUrl(String project) {
-    return String.format(placeHolderUrlProject, project);
+  public WebLinkInfo getPathSetWebLink(String projectName, String commit) {
+    return new WebLinkInfo(name,
+        myImageUrl,
+        String.format(placeHolderUrlProjectCommit, projectName, commit),
+        Target.BLANK);
   }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/HelloWorldServlet.java b/src/main/java/com/googlesource/gerrit/plugins/cookbook/HelloWorldServlet.java
index 9bb80a3..d2c3935 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/cookbook/HelloWorldServlet.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/HelloWorldServlet.java
@@ -14,14 +14,6 @@
 
 package com.googlesource.gerrit.plugins.cookbook;
 
-import java.io.IOException;
-import java.io.Writer;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
 import com.google.gerrit.extensions.annotations.PluginCanonicalWebUrl;
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.inject.Inject;
@@ -30,6 +22,14 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.IOException;
+import java.io.Writer;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
 @Singleton
 class HelloWorldServlet extends HttpServlet {
   private static final long serialVersionUID = 1L;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/MergeUserValidator.java b/src/main/java/com/googlesource/gerrit/plugins/cookbook/MergeUserValidator.java
new file mode 100644
index 0000000..2e35854
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/MergeUserValidator.java
@@ -0,0 +1,78 @@
+// Copyright (C) 2014 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.googlesource.gerrit.plugins.cookbook;
+
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.server.ApprovalsUtil;
+import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.git.CodeReviewCommit;
+import com.google.gerrit.server.git.CommitMergeStatus;
+import com.google.gerrit.server.git.validators.MergeValidationException;
+import com.google.gerrit.server.git.validators.MergeValidationListener;
+import com.google.gerrit.server.project.ProjectState;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+
+import org.eclipse.jgit.lib.Repository;
+
+// Because we have a dedicated Module, we need to bind to the set
+// there, however, if you are using this as a base for your own
+// plugin, you can simply comment out the 'Listen' annotation and
+// it will work as expected.
+//@Listen
+@Singleton
+public class MergeUserValidator implements MergeValidationListener {
+
+  private final IdentifiedUser.GenericFactory identifiedUserFactory;
+  private final Provider<ReviewDb> reviewDb;
+  private final ApprovalsUtil approvalsUtil;
+
+
+  // Because there is 'No user on merge thread' we need to get the
+  // identified user from IdentifiedUser.GenericFactory, this is
+  // normally not needed and you can, in many cases, just use
+  // Provider<CurrentUser>, unfortunately not this one.
+  @Inject
+  MergeUserValidator(IdentifiedUser.GenericFactory identifiedUserFactory,
+      Provider<ReviewDb> reviewDb,
+      ApprovalsUtil approvalsUtil) {
+    this.identifiedUserFactory = identifiedUserFactory;
+    this.reviewDb = reviewDb;
+    this.approvalsUtil = approvalsUtil;
+  }
+
+  /**
+   * Reject all merges if the submitter is not an administrator
+   */
+  @Override
+  public void onPreMerge(Repository repo, CodeReviewCommit commit,
+      ProjectState destProject, Branch.NameKey destBranch, PatchSet.Id patchSetId)
+      throws MergeValidationException {
+    PatchSetApproval psa =
+        approvalsUtil.getSubmitter(reviewDb.get(), commit.notes(), patchSetId);
+    if (psa == null) {
+      throw new MergeValidationException(CommitMergeStatus.NO_PATCH_SET);
+    }
+    IdentifiedUser submitter =
+        identifiedUserFactory.create(psa.getAccountId());
+    if (!submitter.getCapabilities().canAdministrateServer()) {
+      throw new MergeValidationException(CommitMergeStatus.MISSING_DEPENDENCY);
+    }
+  }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/Module.java b/src/main/java/com/googlesource/gerrit/plugins/cookbook/Module.java
index 5f88178..cf6c433 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/cookbook/Module.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/Module.java
@@ -19,16 +19,19 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.gerrit.extensions.annotations.Exports;
-import com.google.gerrit.extensions.common.InheritableBoolean;
+import com.google.gerrit.extensions.client.InheritableBoolean;
 import com.google.gerrit.extensions.events.UsageDataPublishedListener;
 import com.google.gerrit.extensions.registration.DynamicSet;
 import com.google.gerrit.extensions.restapi.RestApiModule;
+import com.google.gerrit.extensions.webui.BranchWebLink;
 import com.google.gerrit.extensions.webui.PatchSetWebLink;
 import com.google.gerrit.extensions.webui.ProjectWebLink;
 import com.google.gerrit.extensions.webui.TopMenu;
 import com.google.gerrit.server.config.ProjectConfigEntry;
+import com.google.gerrit.server.git.validators.MergeValidationListener;
 import com.google.gerrit.server.git.validators.UploadValidationListener;
 import com.google.gerrit.server.plugins.ServerPluginProvider;
+import com.google.gerrit.server.validators.HashtagValidationListener;
 import com.google.inject.AbstractModule;
 
 import com.googlesource.gerrit.plugins.cookbook.pluginprovider.HelloSshPluginProvider;
@@ -41,6 +44,7 @@
         .to(HelloTopMenu.class);
     DynamicSet.bind(binder(), PatchSetWebLink.class).to(HelloWeblink.class);
     DynamicSet.bind(binder(), ProjectWebLink.class).to(HelloWeblink.class);
+    DynamicSet.bind(binder(), BranchWebLink.class).to(HelloWeblink.class);
     DynamicSet.bind(binder(), ServerPluginProvider.class).to(
         HelloSshPluginProvider.class);
     DynamicSet.bind(binder(), UsageDataPublishedListener.class).to(UsageDataLogger.class);
@@ -55,6 +59,10 @@
     });
     DynamicSet.bind(binder(), UploadValidationListener.class)
         .to(DenyUploadExample.class);
+    DynamicSet.bind(binder(), MergeValidationListener.class)
+        .to(MergeUserValidator.class);
+    DynamicSet.bind(binder(), HashtagValidationListener.class)
+        .to(HashtagValidator.class);
     configurePluginParameters();
   }
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/IndexScreen.java b/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/IndexScreen.java
index c50dc36..0edf949 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/IndexScreen.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/client/IndexScreen.java
@@ -14,7 +14,9 @@
 
 package com.googlesource.gerrit.plugins.cookbook.client;
 
+import com.google.gerrit.client.Resources;
 import com.google.gerrit.plugin.client.screen.Screen;
+import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.Scheduler;
 import com.google.gwt.core.client.Scheduler.ScheduledCommand;
 import com.google.gwt.event.dom.client.ClickEvent;
@@ -24,6 +26,8 @@
 import com.google.gwt.user.client.Event;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.HorizontalPanel;
+import com.google.gwt.user.client.ui.Image;
 import com.google.gwt.user.client.ui.Label;
 import com.google.gwt.user.client.ui.Panel;
 import com.google.gwt.user.client.ui.TextArea;
@@ -41,12 +45,19 @@
 
   private TextBox usernameTxt;
   private TextArea greetingTxt;
+  private Resources RESOURCES = GWT.create(Resources.class);
 
   IndexScreen() {
     setStyleName("cookbook-panel");
 
+    Panel labelImagePanel = new HorizontalPanel();
     Panel usernamePanel = new VerticalPanel();
-    usernamePanel.add(new Label("Username:"));
+    Image img = new Image(RESOURCES.info());
+    img.setTitle("User to send greetings to");
+    labelImagePanel.add(new Label("Username"));
+    labelImagePanel.add(img);
+    labelImagePanel.add(new Label(":"));
+    usernamePanel.add(labelImagePanel);
     usernameTxt = new TextBox() {
       @Override
       public void onBrowserEvent(Event event) {
diff --git a/src/main/resources/Documentation/cmd-admin.md b/src/main/resources/Documentation/cmd-admin.md
index 312bd2b..edc054b 100644
--- a/src/main/resources/Documentation/cmd-admin.md
+++ b/src/main/resources/Documentation/cmd-admin.md
@@ -1,13 +1,13 @@
-cookbook-plugin admin
+@PLUGIN@ admin
 =====================
 
 NAME
 ----
-cookbook-plugin admin - Administrate the cookbook plugin
+@PLUGIN@ admin - Administrate the cookbook plugin
 
 SYNOPSIS
 --------
->     ssh -p <port> <host> cookbook-plugin admin
+>     ssh -p <port> <host> @PLUGIN@ admin
 
 DESCRIPTION
 -----------
@@ -28,7 +28,7 @@
 
 Have the server say hello to the administrator.
 
->     $ ssh -p 29418 review.example.com cookbook-plugin admin
+>     $ ssh -p 29418 review.example.com @PLUGIN@ admin
 
 SEE ALSO
 --------
diff --git a/src/main/resources/Documentation/cmd-print.md b/src/main/resources/Documentation/cmd-print.md
index 717b564..d471ec0 100644
--- a/src/main/resources/Documentation/cmd-print.md
+++ b/src/main/resources/Documentation/cmd-print.md
@@ -1,13 +1,13 @@
-cookbook-plugin print
+@PLUGIN@ print
 =====================
 
 NAME
 ----
-cookbook-plugin print - Print our "Hello world" message
+@PLUGIN@ print - Print our "Hello world" message
 
 SYNOPSIS
 --------
->     ssh -p <port> <host> cookbook-plugin print
+>     ssh -p <port> <host> @PLUGIN@ print
 >      [--french]
 >      [name]
 
@@ -42,15 +42,15 @@
 
 Have the server say hi to the world.
 
->     $ ssh -p 29418 review.example.com cookbook-plugin print
+>     $ ssh -p 29418 review.example.com @PLUGIN@ print
 
 Have the server say hi to the world in French.
 
->     $ ssh -p 29418 review.example.com cookbook-plugin print --french
+>     $ ssh -p 29418 review.example.com @PLUGIN@ print --french
 
 Have the server say hi to you in French.
 
->     $ ssh -p 29418 review.example.com cookbook-plugin print --french \'Revi Ewer\'
+>     $ ssh -p 29418 review.example.com @PLUGIN@ print --french \'Revi Ewer\'
 
 SEE ALSO
 --------
diff --git a/src/main/resources/Documentation/rest-api-hello-project.md b/src/main/resources/Documentation/rest-api-hello-project.md
index 4e51809..e1fb49d 100644
--- a/src/main/resources/Documentation/rest-api-hello-project.md
+++ b/src/main/resources/Documentation/rest-api-hello-project.md
@@ -1,4 +1,4 @@
-cookbook-plugin hello-project
+@PLUGIN@ hello-project
 =============================
 
 NAME
diff --git a/src/main/resources/Documentation/rest-api-hello-revision.md b/src/main/resources/Documentation/rest-api-hello-revision.md
index 403bb57..a3d7ec1 100644
--- a/src/main/resources/Documentation/rest-api-hello-revision.md
+++ b/src/main/resources/Documentation/rest-api-hello-revision.md
@@ -1,4 +1,4 @@
-cookbook-plugin hello-revision
+@PLUGIN@ hello-revision
 ==============================
 
 NAME
diff --git a/src/main/resources/Documentation/servlet-hello.md b/src/main/resources/Documentation/servlet-hello.md
index e4902bf..d2be599 100644
--- a/src/main/resources/Documentation/servlet-hello.md
+++ b/src/main/resources/Documentation/servlet-hello.md
@@ -1,4 +1,4 @@
-cookbook-plugin hello
+@PLUGIN@ hello
 =====================
 
 NAME
@@ -7,7 +7,7 @@
 
 SYNOPSIS
 --------
->     http://<host>:<port>/cookbook-plugin/say-hello/
+>     http://<host>:<port>/plugins/@PLUGIN@/say-hello/
 
 DESCRIPTION
 -----------
diff --git a/src/main/resources/static/hello-change.js b/src/main/resources/static/hello-change.js
index 4c668fd..ad339f3 100644
--- a/src/main/resources/static/hello-change.js
+++ b/src/main/resources/static/hello-change.js
@@ -18,16 +18,21 @@
           + c.id
           + ", revision: " + r.name);
     }
-    function onSubmitChange(c, r) {
-      return confirm("Really submit change:\n"
-          + c.id + "\n"
-          + "revision: " + r.name
-          + "?");
+    function onSubmitSomeoneElsesChange(c, r) {
+        var u = self.getCurrentUser();
+        if (u._account_id != c.owner._account_id) {
+          return confirm("Really submit change:\n"
+              + c.id + "\n"
+              + "revision: " + r.name + "\n"
+              + "from: " + c.owner.name
+              + "?");
+        }
+        return true;
     }
     function onHistory(t) {
       console.log("History: " + t);
     }
     Gerrit.on('showchange', onShowChange);
-    Gerrit.on('submitchange', onSubmitChange);
+    Gerrit.on('submitchange', onSubmitSomeoneElsesChange);
     Gerrit.on('history', onHistory);
   });
diff --git a/src/test/java/com/googlesource/gerrit/plugins/cookbook/CookbookTest.java b/src/test/java/com/googlesource/gerrit/plugins/cookbook/CookbookTest.java
new file mode 100644
index 0000000..d6376ae
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/cookbook/CookbookTest.java
@@ -0,0 +1,28 @@
+// Copyright (C) 2014 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.googlesource.gerrit.plugins.cookbook;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class CookbookTest {
+  @Test
+  public void cookbookTest() {
+    // Dummy test, only used to make sure the cookbook plugin gets compiled
+    // when running `buck test`, thus highlighting any compilation errors.
+    assertTrue(true);
+  }
+}