Merge "Fix spacing in header of XDocScreen"
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocLoader.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocLoader.java
index cf0971c..502c1a6 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocLoader.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocLoader.java
@@ -33,8 +33,11 @@
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
 
+import com.googlesource.gerrit.plugins.xdocs.formatter.Formatter;
 import com.googlesource.gerrit.plugins.xdocs.formatter.Formatters;
 import com.googlesource.gerrit.plugins.xdocs.formatter.Formatters.FormatterProvider;
+import com.googlesource.gerrit.plugins.xdocs.formatter.StreamFormatter;
+import com.googlesource.gerrit.plugins.xdocs.formatter.StringFormatter;
 
 import org.eclipse.jgit.api.Git;
 import org.eclipse.jgit.api.errors.GitAPIException;
@@ -48,14 +51,19 @@
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.eclipse.jgit.treewalk.TreeWalk;
 import org.eclipse.jgit.treewalk.filter.PathFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
+import java.io.InputStream;
 import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 @Singleton
 public class XDocLoader extends CacheLoader<String, Resource> {
+  private static final Logger log = LoggerFactory.getLogger(XDocLoader.class);
+
   private static final String DEFAULT_HOST = "review.example.com";
 
   private final GitRepositoryManager repoManager;
@@ -107,21 +115,33 @@
           }
           ObjectId objectId = tw.getObjectId(0);
           ObjectLoader loader = repo.open(objectId);
-          byte[] bytes = loader.getBytes(Integer.MAX_VALUE);
-          boolean isBinary = RawText.isBinary(bytes);
-          if (formatter.getName().equals(Formatters.RAW_FORMATTER) && isBinary) {
-            return Resources.METHOD_NOT_ALLOWED;
-          }
           ObjectReader reader = repo.newObjectReader();
+          String abbrRevId = reader.abbreviate(revId).name();
           try {
-            String abbrRevId = reader.abbreviate(revId).name();
-            String raw = new String(bytes, UTF_8);
-            if (!isBinary) {
-              raw = replaceMacros(repo, key.getProject(), revId, abbrRevId, raw);
-            }
-            String html =
-                formatter.get().format(key.getProject().get(),
+            String html;
+            Formatter f = formatter.get();
+            if (f instanceof StringFormatter) {
+              byte[] bytes = loader.getBytes(Integer.MAX_VALUE);
+              boolean isBinary = RawText.isBinary(bytes);
+              if (formatter.getName().equals(Formatters.RAW_FORMATTER) && isBinary) {
+                return Resources.METHOD_NOT_ALLOWED;
+              }
+              String raw = new String(bytes, UTF_8);
+              if (!isBinary) {
+                raw = replaceMacros(repo, key.getProject(), revId, abbrRevId, raw);
+              }
+              html = ((StringFormatter) f).format(key.getProject().get(),
+                  abbrRevId, formatterCfg, raw);
+            } else if (f instanceof StreamFormatter) {
+              try (InputStream raw = loader.openStream()) {
+                html = ((StreamFormatter) f).format(key.getProject().get(),
                     abbrRevId, formatterCfg, raw);
+              }
+            } else {
+              log.error(String.format("Unsupported formatter: %s", formatter.getName()));
+              return Resource.NOT_FOUND;
+            }
+
             return getAsHtmlResource(html, commit.getCommitTime());
           } finally {
             reader.release();
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/AsciidoctorFormatter.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/AsciidoctorFormatter.java
index fe57a90..200ac03 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/AsciidoctorFormatter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/AsciidoctorFormatter.java
@@ -49,7 +49,7 @@
 import java.util.Properties;
 
 @Singleton
-public class AsciidoctorFormatter implements Formatter {
+public class AsciidoctorFormatter implements StringFormatter {
   public static final String NAME = "ASCIIDOCTOR";
 
   private static final String BACKEND = "html5";
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/Formatter.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/Formatter.java
index c975147..d7c6549 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/Formatter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/Formatter.java
@@ -16,25 +16,6 @@
 
 import com.google.gerrit.extensions.annotations.ExtensionPoint;
 
-import com.googlesource.gerrit.plugins.xdocs.ConfigSection;
-
-import java.io.IOException;
-
 @ExtensionPoint
 public interface Formatter {
-
-  /**
-   * Formats the given raw text as html.
-   *
-   * @param projectName the name of the project that contains the file to be
-   *        formatted
-   * @param revision the abbreviated revision from which the file is loaded
-   * @param cfg the global configuration for this formatter
-   * @param raw the raw text
-   * @return the given text formatted as html
-   * @throws IOException thrown if the formatting fails
-   */
-  public String format(String projectName, String revision, ConfigSection cfg,
-      String raw)
-      throws IOException;
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/Formatters.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/Formatters.java
index 4e3c359..95e412e 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/Formatters.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/Formatters.java
@@ -201,10 +201,9 @@
 
   public static class FormatterProvider {
     private final String name;
-    private final Provider<Formatter> formatter;
+    private final Provider<? extends Formatter> formatter;
 
-    FormatterProvider(String name,
-        Provider<Formatter> formatter) {
+    FormatterProvider(String name, Provider<? extends Formatter> formatter) {
       this.name = name;
       this.formatter = formatter;
     }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/MarkdownFormatter.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/MarkdownFormatter.java
index f4aa3a8..d4150ea 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/MarkdownFormatter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/MarkdownFormatter.java
@@ -25,7 +25,7 @@
 
 import java.io.IOException;
 
-public class MarkdownFormatter implements Formatter {
+public class MarkdownFormatter implements StringFormatter {
   public final static String NAME = "MARKDOWN";
 
   private final FormatterUtil util;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/PlainTextFormatter.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/PlainTextFormatter.java
index 0c79bd5..6e36bba 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/PlainTextFormatter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/PlainTextFormatter.java
@@ -18,7 +18,7 @@
 
 import com.googlesource.gerrit.plugins.xdocs.ConfigSection;
 
-public class PlainTextFormatter implements Formatter {
+public class PlainTextFormatter implements StringFormatter {
   public final static String NAME = "PLAIN_TEXT";
 
   @Override
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/StreamFormatter.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/StreamFormatter.java
new file mode 100644
index 0000000..c435b23
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/StreamFormatter.java
@@ -0,0 +1,36 @@
+// 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.xdocs.formatter;
+
+import com.googlesource.gerrit.plugins.xdocs.ConfigSection;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public interface StreamFormatter extends Formatter {
+  /**
+   * Formats the given raw text as html.
+   *
+   * @param projectName the name of the project that contains the file to be
+   *        formatted
+   * @param revision the abbreviated revision from which the file is loaded
+   * @param cfg the global configuration for this formatter
+   * @param raw the raw stream
+   * @return the content from the given stream formatted as html
+   * @throws IOException thrown if the formatting fails
+   */
+  public String format(String projectName, String revision, ConfigSection cfg,
+      InputStream raw) throws IOException;
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/StringFormatter.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/StringFormatter.java
new file mode 100644
index 0000000..952794c
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/StringFormatter.java
@@ -0,0 +1,36 @@
+// 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.xdocs.formatter;
+
+import com.googlesource.gerrit.plugins.xdocs.ConfigSection;
+
+import java.io.IOException;
+
+public interface StringFormatter extends Formatter {
+
+  /**
+   * Formats the given raw text as html.
+   *
+   * @param projectName the name of the project that contains the file to be
+   *        formatted
+   * @param revision the abbreviated revision from which the file is loaded
+   * @param cfg the global configuration for this formatter
+   * @param raw the raw text
+   * @return the given text formatted as html
+   * @throws IOException thrown if the formatting fails
+   */
+  public String format(String projectName, String revision, ConfigSection cfg,
+      String raw) throws IOException;
+}