Merge branch 'stable-2.11'

* stable-2.11:
  Adapt to getPatchSetWebLink spelling correction

Change-Id: I580bc0fb84f190c01964c8db38e994a43be11ca4
diff --git a/lib/gerrit/BUCK b/lib/gerrit/BUCK
index 89c75df..ee02ebb 100644
--- a/lib/gerrit/BUCK
+++ b/lib/gerrit/BUCK
@@ -1,6 +1,6 @@
 include_defs('//bucklets/maven_jar.bucklet')
 
-VER = '2.11-SNAPSHOT'
+VER = '2.12-SNAPSHOT'
 REPO = MAVEN_LOCAL
 
 maven_jar(
diff --git a/pom.xml b/pom.xml
index b765d38..2ea24d5 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.11-SNAPSHOT</version>
+  <version>2.12-SNAPSHOT</version>
   <properties>
     <Gerrit-ApiType>plugin</Gerrit-ApiType>
     <Gerrit-ApiVersion>${project.version}</Gerrit-ApiVersion>
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 58a9017..5cb3053 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/cookbook/Greetings.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/Greetings.java
@@ -17,17 +17,12 @@
 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
-  Greetings() {
-  }
-
   @Override
   public Response<Collection<GreetInfo>> apply(RevisionResource rev) {
     Collection<GreetInfo> l = new ArrayList<>(3);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/pluginprovider/HelloSshCommand.java b/src/main/java/com/googlesource/gerrit/plugins/cookbook/pluginprovider/HelloSshCommand.java
index b1da6de..853d04d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/cookbook/pluginprovider/HelloSshCommand.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/pluginprovider/HelloSshCommand.java
@@ -14,39 +14,64 @@
 
 package com.googlesource.gerrit.plugins.cookbook.pluginprovider;
 
+import com.google.gerrit.extensions.annotations.PluginData;
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.server.config.SitePaths;
 import com.google.gerrit.sshd.CommandMetaData;
 import com.google.gerrit.sshd.SshCommand;
 import com.google.inject.Inject;
 
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
+import org.kohsuke.args4j.Argument;
 
-/**
- * SSH command defined by dynamically registered plugins.
- *
- */
-@CommandMetaData(name = "print", description = "Print content of the plugin file")
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+
+/** SSH command defined by dynamically registered plugins. */
+@CommandMetaData(name = "cat", description = "Print content of plugin file")
 public final class HelloSshCommand extends SshCommand {
   private final String pluginName;
-  private final File pluginDir;
+  private final Path pluginDir;
+  private final Path dataDir;
+
+  @Argument(usage = "files in data directory to print")
+  private List<String> files = new ArrayList<>();
 
   @Inject
-  public HelloSshCommand(@PluginName String pluginName, SitePaths sitePaths) {
+  public HelloSshCommand(@PluginName String pluginName,
+      SitePaths sitePaths,
+      @PluginData Path dataDir) {
     this.pluginName = pluginName;
-    this.pluginDir = sitePaths.plugins_dir;
+    this.pluginDir = sitePaths.plugins_dir.normalize();
+    this.dataDir = dataDir.normalize();
   }
 
   @Override
   public void run() {
-    File pluginFile = new File(pluginDir, pluginName + ".ssh");
+    Path pluginPath = pluginDir.resolve(pluginName + ".ssh");
+    printOne(pluginPath);
+    for (String name : files) {
+      Path p = dataDir.resolve(name).normalize();
+      if (!p.startsWith(dataDir)) {
+        throw new RuntimeException(p + " is outside data directory " + dataDir);
+      }
+      printOne(p);
+    }
+  }
+
+  private void printOne(Path p) {
     try {
-      Files.copy(pluginFile.toPath(), out);
+      Files.copy(p, out);
     } catch (IOException e) {
-      throw new RuntimeException("Cannot read plugin content of " + pluginFile,
-          e);
+      try (PrintWriter w = new PrintWriter(err)) {
+        w.write("Error reading contents of ");
+        w.write(p.toAbsolutePath().toString());
+        w.write(": \n");
+        e.printStackTrace(w);
+      }
     }
   }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cookbook/pluginprovider/HelloSshPluginProvider.java b/src/main/java/com/googlesource/gerrit/plugins/cookbook/pluginprovider/HelloSshPluginProvider.java
index a7d7268..8ffd8c2 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/cookbook/pluginprovider/HelloSshPluginProvider.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/cookbook/pluginprovider/HelloSshPluginProvider.java
@@ -22,19 +22,25 @@
 
 import org.eclipse.jgit.internal.storage.file.FileSnapshot;
 
-import java.io.File;
+import java.nio.file.Path;
 
 /**
- * Dynamic provider of Gerrit plugins derived by *.ssh files under $GERRIT_SITE/plugins.
- *
+ * Dynamic provider of Gerrit plugins derived by *.ssh files under
+ * $GERRIT_SITE/plugins.
+ * <p>
  * Example of how to define a dynamic Gerrit plugin provider to register
  * a new plugin based on the content of *.ssh files.
- *
+ * <p>
  * This provider allows to define a Gerrit plugin by simply dropping a .ssh file
  * (e.g. hello.ssh) under $GERRIT_SITE/plugins.
+ * <p>
  * Once the file is created a new plugin is automatically loaded with the name
- * without extension of the .ssh file (e.g. hello) and a new 'cat' SSH command is
- * automatically available from the registered plugin.
+ * without extension of the .ssh file (e.g. hello) and a new 'cat' SSH command
+ * is automatically available from the registered plugin.
+ * <p>
+ * The 'cat' command will print the contents of the .ssh file, along with the
+ * contents of any arguments, resolved against the plugin's data directory
+ * $GERRIT_SITE/data/name.
  */
 public class HelloSshPluginProvider implements ServerPluginProvider {
   private static final String SSH_EXT = ".ssh";
@@ -46,22 +52,22 @@
   }
 
   @Override
-  public boolean handles(File srcFile) {
-    return srcFile.getName().endsWith(SSH_EXT);
+  public boolean handles(Path srcPath) {
+    return srcPath.getFileName().toString().endsWith(SSH_EXT);
   }
 
   @Override
-  public String getPluginName(File srcFile) {
-    String srcFileName = srcFile.getName();
-    return srcFileName.substring(0, srcFileName.length() - SSH_EXT.length());
+  public String getPluginName(Path srcPath) {
+    String name = srcPath.getFileName().toString();
+    return name.substring(0, name.length() - SSH_EXT.length());
   }
 
   @Override
-  public ServerPlugin get(File srcFile, FileSnapshot snapshot,
+  public ServerPlugin get(Path srcPath, FileSnapshot snapshot,
       PluginDescription pluginDescriptor) throws InvalidPluginException {
-    String name = getPluginName(srcFile);
+    String name = getPluginName(srcPath);
     return new ServerPlugin(name, pluginDescriptor.canonicalUrl,
-        pluginDescriptor.user, srcFile, snapshot,
+        pluginDescriptor.user, srcPath, snapshot,
         new HelloSshPluginContentScanner(name), pluginDescriptor.dataDir,
         getClass().getClassLoader());
   }