Add common interface for formatters Having a common interface for formatters makes it easier to add additional formatters. Now to add a new formatter one only needs to implement the Formatter interface and register the implementation in a DynamicMap. Change-Id: I4cbbf6cff89b18a277f8d828486ae9cc023c2dca Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/ConfigSection.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/ConfigSection.java new file mode 100644 index 0000000..7da04a0 --- /dev/null +++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/ConfigSection.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.xdocs; + +import com.google.common.base.MoreObjects; + +import org.eclipse.jgit.lib.Config; + +import java.util.Set; + +public class ConfigSection { + private final Config cfg; + private final String section; + private final String subsection; + + ConfigSection(Config cfg, String section) { + this(cfg, section, null); + } + + ConfigSection(Config cfg, String section, String subsection) { + this.cfg = cfg; + this.section = section; + this.subsection = subsection; + } + + public String getString(String name) { + return cfg.getString(section, subsection, name); + } + + public String getString(String name, String defaultValue) { + if (defaultValue == null) { + return cfg.getString(section, subsection, name); + } else { + return MoreObjects.firstNonNull(cfg.getString(section, subsection, name), + defaultValue); + } + } + + public String[] getStringList(String name) { + return cfg.getStringList(section, subsection, name); + } + + public int getInt(String name, int defaultValue) { + return cfg.getInt(section, subsection, name, defaultValue); + } + + public long getLong(String name, long defaultValue) { + return cfg.getLong(section, subsection, name, defaultValue); + } + + public boolean getBoolean(String name, boolean defaultValue) { + return cfg.getBoolean(section, subsection, name, defaultValue); + } + + public <T extends Enum<?>> T getEnum(String name, T defaultValue) { + return cfg.getEnum(section, subsection, name, defaultValue); + } + + public <T extends Enum<?>> T getEnum(T[] all, String name, T defaultValue) { + return cfg.getEnum(all, section, subsection, name, defaultValue); + } + + public Set<String> getNames() { + return cfg.getNames(section, subsection); + } +}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/Module.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/Module.java index c313f4d..1f3dac5 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/Module.java +++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/Module.java
@@ -15,7 +15,9 @@ package com.googlesource.gerrit.plugins.xdocs; import com.google.common.collect.Lists; +import com.google.gerrit.extensions.annotations.Exports; import com.google.gerrit.extensions.annotations.PluginName; +import com.google.gerrit.extensions.registration.DynamicMap; import com.google.gerrit.extensions.registration.DynamicSet; import com.google.gerrit.extensions.webui.BranchWebLink; import com.google.gerrit.extensions.webui.FileWebLink; @@ -25,6 +27,10 @@ import com.google.gerrit.server.config.FactoryModule; import com.google.inject.Inject; +import com.googlesource.gerrit.plugins.xdocs.formatter.Formatter; +import com.googlesource.gerrit.plugins.xdocs.formatter.MarkdownFormatter; +import com.googlesource.gerrit.plugins.xdocs.formatter.PlainTextFormatter; + import java.util.List; public class Module extends FactoryModule { @@ -40,6 +46,14 @@ install(new XDocLoader.Module()); factory(XDocProjectConfig.Factory.class); + DynamicMap.mapOf(binder(), Formatter.class); + bind(Formatter.class) + .annotatedWith(Exports.named(MarkdownFormatter.NAME)) + .to(MarkdownFormatter.class); + bind(Formatter.class) + .annotatedWith(Exports.named(PlainTextFormatter.NAME)) + .to(PlainTextFormatter.class); + DynamicSet.bind(binder(), ProjectWebLink.class) .to(XDocWebLink.class); DynamicSet.bind(binder(), BranchWebLink.class)
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocFileWebLink.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocFileWebLink.java index cd5d676..934e9b1 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocFileWebLink.java +++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocFileWebLink.java
@@ -18,13 +18,13 @@ import com.google.gerrit.extensions.annotations.PluginName; import com.google.gerrit.extensions.webui.FileWebLink; import com.google.gerrit.httpd.resources.Resource; -import com.google.gerrit.server.FileTypeRegistry; -import com.google.gerrit.server.config.PluginConfigFactory; import com.google.gerrit.server.git.GitRepositoryManager; import com.google.gerrit.server.project.ProjectCache; import com.google.inject.Inject; import com.google.inject.name.Named; +import com.googlesource.gerrit.plugins.xdocs.formatter.Formatters; + public class XDocFileWebLink extends XDocWebLink implements FileWebLink { @Inject @@ -34,10 +34,8 @@ @Named(XDocLoader.Module.X_DOC_RESOURCES) LoadingCache<String, Resource> cache, XDocProjectConfig.Factory cfgFactory, ProjectCache projectCache, - FileTypeRegistry fileTypeRegistry, - PluginConfigFactory pluginCfgFactory) { - super(pluginName, repoManager, cache, cfgFactory, projectCache, - fileTypeRegistry, pluginCfgFactory); + Formatters formatters) { + super(pluginName, repoManager, cache, cfgFactory, projectCache, formatters); } @Override
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocGlobalConfig.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocGlobalConfig.java index 6fbce26..b7fadf4 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocGlobalConfig.java +++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocGlobalConfig.java
@@ -14,48 +14,31 @@ package com.googlesource.gerrit.plugins.xdocs; -import eu.medsea.mimeutil.MimeType; +import com.googlesource.gerrit.plugins.xdocs.formatter.MarkdownFormatter; +import com.googlesource.gerrit.plugins.xdocs.formatter.PlainTextFormatter; import org.eclipse.jgit.lib.Config; -import java.util.HashMap; -import java.util.Map; - public class XDocGlobalConfig { private static final String SECTION_FORMATTER = "formatter"; - private static final String KEY_ALLOW_HTML = "allowHtml"; - private static final String KEY_MIME_TYPE = "mimeType"; - enum Formatter { - MARKDOWN, PLAIN_TEXT; - } + public static final String KEY_ALLOW_HTML = "allowHtml"; + public static final String KEY_MIME_TYPE = "mimeType"; private final Config cfg; - XDocGlobalConfig(Config cfg) { + public XDocGlobalConfig(Config cfg) { this.cfg = cfg; } - boolean isHtmlAllowed(Formatter formatter) { - return cfg.getBoolean(SECTION_FORMATTER, formatter.name(), - KEY_ALLOW_HTML, false); - } - - Map<MimeType, Formatter> getMimeTypes() { - Map<MimeType, Formatter> mimeTypes = new HashMap<>(); - for (Formatter f : Formatter.values()) { - for (String mimeType : - cfg.getStringList(SECTION_FORMATTER, f.name(), KEY_MIME_TYPE)) { - mimeTypes.put(new MimeType(mimeType), f); - } - } - return mimeTypes; + public ConfigSection getFormatterConfig(String formatterName) { + return new ConfigSection(cfg, SECTION_FORMATTER, formatterName); } static void initialize(Config cfg) { - cfg.setString(SECTION_FORMATTER, Formatter.MARKDOWN.name(), KEY_MIME_TYPE, + cfg.setString(SECTION_FORMATTER, MarkdownFormatter.NAME, KEY_MIME_TYPE, "text/x-markdown"); - cfg.setString(SECTION_FORMATTER, Formatter.PLAIN_TEXT.name(), KEY_MIME_TYPE, + cfg.setString(SECTION_FORMATTER, PlainTextFormatter.NAME, KEY_MIME_TYPE, "text/plain"); } }
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 ebfb54d..9fd8ac1 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocLoader.java +++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocLoader.java
@@ -15,7 +15,6 @@ package com.googlesource.gerrit.plugins.xdocs; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.apache.commons.lang.StringEscapeUtils.escapeHtml; import com.google.common.base.Strings; import com.google.common.cache.CacheLoader; @@ -28,13 +27,13 @@ import com.google.gerrit.server.cache.CacheModule; import com.google.gerrit.server.config.CanonicalWebUrl; import com.google.gerrit.server.config.PluginConfigFactory; -import com.google.gerrit.server.documentation.MarkdownFormatter; import com.google.gerrit.server.git.GitRepositoryManager; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; -import com.googlesource.gerrit.plugins.xdocs.XDocGlobalConfig.Formatter; +import com.googlesource.gerrit.plugins.xdocs.formatter.Formatters; +import com.googlesource.gerrit.plugins.xdocs.formatter.Formatters.FormatterProvider; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectLoader; @@ -45,7 +44,6 @@ import org.eclipse.jgit.treewalk.TreeWalk; import org.eclipse.jgit.treewalk.filter.PathFilter; -import java.io.IOException; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -58,22 +56,31 @@ private final Provider<String> webUrl; private final String pluginName; private final PluginConfigFactory cfgFactory; + private final Formatters formatters; @Inject XDocLoader(GitRepositoryManager repoManager, @CanonicalWebUrl Provider<String> webUrl, @PluginName String pluginName, - PluginConfigFactory cfgFactory) { + PluginConfigFactory cfgFactory, + Formatters formatters) { this.repoManager = repoManager; this.webUrl = webUrl; this.pluginName = pluginName; this.cfgFactory = cfgFactory; + this.formatters = formatters; } @Override public Resource load(String strKey) throws Exception { XDocResourceKey key = XDocResourceKey.fromString(strKey); - XDocGlobalConfig cfg = new XDocGlobalConfig(cfgFactory.getGlobalPluginConfig(pluginName)); + XDocGlobalConfig cfg = + new XDocGlobalConfig(cfgFactory.getGlobalPluginConfig(pluginName)); + FormatterProvider formatter = formatters.getByName(key.getFormatter()); + if (formatter == null) { + return Resource.NOT_FOUND; + } + ConfigSection formatterCfg = cfg.getFormatterConfig(formatter.getName()); Repository repo = repoManager.openRepository(key.getProject()); try { RevWalk rw = new RevWalk(repo); @@ -91,8 +98,9 @@ ObjectId objectId = tw.getObjectId(0); ObjectLoader loader = repo.open(objectId); byte[] raw = loader.getBytes(Integer.MAX_VALUE); - byte[] html = formatAsHtml(cfg, key.getFormatter(), - replaceMacros(key.getProject(), new String(raw, UTF_8))); + String html = + formatter.get().format(formatterCfg, + replaceMacros(key.getProject(), raw)); return getAsHtmlResource(html, commit.getCommitTime()); } finally { tw.release(); @@ -105,7 +113,7 @@ } } - private String replaceMacros(Project.NameKey project, String raw) { + private String replaceMacros(Project.NameKey project, byte[] raw) { Map<String, String> macros = Maps.newHashMap(); String url = webUrl.get(); @@ -117,7 +125,8 @@ macros.put("PROJECT", project.get()); macros.put("PROJECT_URL", url + "#/admin/projects/" + project.get()); - Matcher m = Pattern.compile("(\\\\)?@([A-Z_]+)@").matcher(raw); + Matcher m = Pattern.compile("(\\\\)?@([A-Z_]+)@") + .matcher(new String(raw, UTF_8)); StringBuffer sb = new StringBuffer(); while (m.find()) { String key = m.group(2); @@ -132,35 +141,8 @@ return sb.toString(); } - private byte[] formatAsHtml(XDocGlobalConfig cfg, Formatter formatter, - String raw) throws IOException { - switch (formatter) { - case MARKDOWN: - return formatMarkdownAsHtml(cfg, raw); - case PLAIN_TEXT: - return formatTxtAsHtml(raw); - default: - throw new IllegalStateException("Unsupported formatter: " - + formatter.name()); - } - } - - private byte[] formatMarkdownAsHtml(XDocGlobalConfig cfg, String md) - throws IOException { - MarkdownFormatter f = new MarkdownFormatter(); - if (!cfg.isHtmlAllowed(Formatter.MARKDOWN)) { - f.suppressHtml(); - } - return f.markdownToDocHtml(md, UTF_8.name()); - } - - private byte[] formatTxtAsHtml(String txt) { - String html = "<pre>" + escapeHtml(txt) + "</pre>"; - return html.getBytes(UTF_8); - } - - private Resource getAsHtmlResource(byte[] html, int lastModified) { - return new SmallResource(html) + private Resource getAsHtmlResource(String html, int lastModified) { + return new SmallResource(html.getBytes(UTF_8)) .setContentType("text/html") .setCharacterEncoding(UTF_8.name()) .setLastModified(lastModified);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocResourceKey.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocResourceKey.java index 09bc287..2407490 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocResourceKey.java +++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocResourceKey.java
@@ -18,17 +18,15 @@ import com.google.gerrit.extensions.restapi.IdString; import com.google.gerrit.reviewdb.client.Project; -import com.googlesource.gerrit.plugins.xdocs.XDocGlobalConfig.Formatter; - import org.eclipse.jgit.lib.ObjectId; public class XDocResourceKey { - private final Formatter formatter; + private final String formatter; private final Project.NameKey project; private final String resource; private final ObjectId revId; - XDocResourceKey(Formatter formatter, Project.NameKey project, String r, + XDocResourceKey(String formatter, Project.NameKey project, String r, ObjectId revId) { this.formatter = formatter; this.project = project; @@ -36,7 +34,7 @@ this.revId = revId; } - public Formatter getFormatter() { + public String getFormatter() { return formatter; } @@ -69,7 +67,7 @@ public String asString() { StringBuilder b = new StringBuilder(); - b.append(formatter.name()); + b.append(IdString.fromDecoded(formatter).encoded()); b.append("/"); b.append(IdString.fromDecoded(project.get()).encoded()); b.append("/"); @@ -81,12 +79,12 @@ public static XDocResourceKey fromString(String str) { String[] s = str.split("/"); - Formatter formatter = null; + String formatter = null; String project = null; String file = null; String revision = null; if (s.length > 0) { - formatter = Formatter.valueOf(s[0]); + formatter = IdString.fromUrl(s[0]).get(); } if (s.length > 1) { project = IdString.fromUrl(s[1]).get();
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocServlet.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocServlet.java index 2befa05..786a646 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocServlet.java +++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocServlet.java
@@ -22,7 +22,6 @@ import com.google.common.cache.LoadingCache; import com.google.common.hash.Hashing; import com.google.common.net.HttpHeaders; -import com.google.gerrit.extensions.annotations.PluginName; import com.google.gerrit.extensions.restapi.AuthException; import com.google.gerrit.extensions.restapi.IdString; import com.google.gerrit.extensions.restapi.ResourceNotFoundException; @@ -31,7 +30,6 @@ import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.server.FileTypeRegistry; -import com.google.gerrit.server.config.PluginConfigFactory; import com.google.gerrit.server.git.GitRepositoryManager; import com.google.gerrit.server.project.GetHead; import com.google.gerrit.server.project.NoSuchProjectException; @@ -45,7 +43,8 @@ import com.google.inject.Singleton; import com.google.inject.name.Named; -import com.googlesource.gerrit.plugins.xdocs.XDocGlobalConfig.Formatter; +import com.googlesource.gerrit.plugins.xdocs.formatter.Formatters; +import com.googlesource.gerrit.plugins.xdocs.formatter.Formatters.FormatterProvider; import eu.medsea.mimeutil.MimeType; @@ -62,7 +61,6 @@ import org.eclipse.jgit.treewalk.filter.PathFilter; import java.io.IOException; -import java.util.Map; import java.util.concurrent.TimeUnit; import javax.servlet.http.HttpServlet; @@ -83,8 +81,7 @@ private final LoadingCache<String, Resource> docCache; private final FileTypeRegistry fileTypeRegistry; private final XDocProjectConfig.Factory cfgFactory; - private final String pluginName; - private final PluginConfigFactory pluginCfgFactory; + private final Formatters formatters; @Inject XDocServlet( @@ -96,8 +93,7 @@ @Named(XDocLoader.Module.X_DOC_RESOURCES) LoadingCache<String, Resource> cache, FileTypeRegistry fileTypeRegistry, XDocProjectConfig.Factory cfgFactory, - @PluginName String pluginName, - PluginConfigFactory pluginCfgFactory) { + Formatters formatters) { this.db = db; this.projectControlFactory = projectControlFactory; this.projectCache = projectCache; @@ -106,8 +102,7 @@ this.docCache = cache; this.fileTypeRegistry = fileTypeRegistry; this.cfgFactory = cfgFactory; - this.pluginName = pluginName; - this.pluginCfgFactory = pluginCfgFactory; + this.formatters = formatters; } @Override @@ -130,11 +125,9 @@ res.sendRedirect(getRedirectUrl(req, key, cfg)); return; } - XDocGlobalConfig pluginCfg = - new XDocGlobalConfig(pluginCfgFactory.getGlobalPluginConfig(pluginName)); MimeType mimeType = fileTypeRegistry.getMimeType(key.file, null); - Map<MimeType, Formatter> mimeTypes = pluginCfg.getMimeTypes(); - if (!mimeTypes.keySet().contains(mimeType) + FormatterProvider formatter = formatters.get(key.file); + if (formatter == null && !("image".equals(mimeType.getMediaType()) && fileTypeRegistry.isSafeInline(mimeType))) { Resource.NOT_FOUND.send(req, res); @@ -191,10 +184,9 @@ } Resource rsc; - Formatter formatter = mimeTypes.get(mimeType); if (formatter != null) { rsc = docCache.getUnchecked( - (new XDocResourceKey(formatter, key.project, key.file, revId)).asString()); + (new XDocResourceKey(formatter.getName(), key.project, key.file, revId)).asString()); } else if ("image".equals(mimeType.getMediaType())) { rsc = getImageResource(repo, revId, key.file); } else {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocWebLink.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocWebLink.java index 2c25095..e0b7a60 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocWebLink.java +++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocWebLink.java
@@ -21,8 +21,6 @@ import com.google.gerrit.extensions.webui.ProjectWebLink; import com.google.gerrit.httpd.resources.Resource; import com.google.gerrit.reviewdb.client.Project; -import com.google.gerrit.server.FileTypeRegistry; -import com.google.gerrit.server.config.PluginConfigFactory; import com.google.gerrit.server.git.GitRepositoryManager; import com.google.gerrit.server.project.ProjectCache; import com.google.gerrit.server.project.ProjectState; @@ -30,9 +28,8 @@ import com.google.inject.Singleton; import com.google.inject.name.Named; -import com.googlesource.gerrit.plugins.xdocs.XDocGlobalConfig.Formatter; - -import eu.medsea.mimeutil.MimeType; +import com.googlesource.gerrit.plugins.xdocs.formatter.Formatters; +import com.googlesource.gerrit.plugins.xdocs.formatter.Formatters.FormatterProvider; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; @@ -52,8 +49,7 @@ private final LoadingCache<String, Resource> docCache; private final XDocProjectConfig.Factory cfgFactory; private final ProjectCache projectCache; - private final FileTypeRegistry fileTypeRegistry; - private final PluginConfigFactory pluginCfgFactory; + private final Formatters formatters; @Inject XDocWebLink( @@ -62,15 +58,13 @@ @Named(XDocLoader.Module.X_DOC_RESOURCES) LoadingCache<String, Resource> cache, XDocProjectConfig.Factory cfgFactory, ProjectCache projectCache, - FileTypeRegistry fileTypeRegistry, - PluginConfigFactory pluginCfgFactory) { + Formatters formatters) { this.pluginName = pluginName; this.repoManager = repoManager; this.docCache = cache; this.cfgFactory = cfgFactory; this.projectCache = projectCache; - this.fileTypeRegistry = fileTypeRegistry; - this.pluginCfgFactory = pluginCfgFactory; + this.formatters = formatters; } @Override @@ -96,10 +90,7 @@ public String getPatchUrl(String projectName, String revision, String fileName) { - XDocGlobalConfig pluginCfg = - new XDocGlobalConfig(pluginCfgFactory.getGlobalPluginConfig(pluginName)); - MimeType mimeType = fileTypeRegistry.getMimeType(fileName, null); - Formatter formatter = pluginCfg.getMimeTypes().get(mimeType); + FormatterProvider formatter = formatters.get(fileName); if (formatter == null) { return null; } @@ -113,7 +104,7 @@ return null; } Resource rsc = docCache.getUnchecked( - (new XDocResourceKey(formatter, p, fileName, revId)).asString()); + (new XDocResourceKey(formatter.getName(), p, fileName, revId)).asString()); if (rsc != Resource.NOT_FOUND) { StringBuilder url = new StringBuilder(); url.append("plugins/");
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 new file mode 100644 index 0000000..e934c0d --- /dev/null +++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/Formatter.java
@@ -0,0 +1,35 @@ +// 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.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 cfg the 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(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 new file mode 100644 index 0000000..b338027 --- /dev/null +++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/Formatters.java
@@ -0,0 +1,100 @@ +// 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 static com.googlesource.gerrit.plugins.xdocs.XDocGlobalConfig.KEY_MIME_TYPE; + +import com.google.gerrit.extensions.annotations.PluginName; +import com.google.gerrit.extensions.registration.DynamicMap; +import com.google.gerrit.server.FileTypeRegistry; +import com.google.gerrit.server.config.PluginConfigFactory; +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.Singleton; + +import com.googlesource.gerrit.plugins.xdocs.XDocGlobalConfig; + +import eu.medsea.mimeutil.MimeType; + +import java.util.Map.Entry; + +@Singleton +public class Formatters { + private final String pluginName; + private final PluginConfigFactory pluginCfgFactory; + private final FileTypeRegistry fileTypeRegistry; + private final DynamicMap<Formatter> formatters; + + @Inject + Formatters( + @PluginName String pluginName, + PluginConfigFactory pluginCfgFactory, + FileTypeRegistry fileTypeRegistry, + DynamicMap<Formatter> formatters) { + this.pluginName = pluginName; + this.pluginCfgFactory = pluginCfgFactory; + this.fileTypeRegistry = fileTypeRegistry; + this.formatters = formatters; + } + + public FormatterProvider get(String fileName) { + XDocGlobalConfig pluginCfg = + new XDocGlobalConfig(pluginCfgFactory.getGlobalPluginConfig(pluginName)); + MimeType mimeType = fileTypeRegistry.getMimeType(fileName, null); + for (String pluginName : formatters.plugins()) { + for (Entry<String, Provider<Formatter>> e : + formatters.byPlugin(pluginName).entrySet()) { + for (String configuredMimeType : + pluginCfg.getFormatterConfig(e.getKey()).getStringList(KEY_MIME_TYPE)) { + if (mimeType.equals(new MimeType(configuredMimeType))) { + return new FormatterProvider(e.getKey(), e.getValue()); + } + } + } + } + return null; + } + + public FormatterProvider getByName(String formatterName) { + for (String pluginName : formatters.plugins()) { + for (Entry<String, Provider<Formatter>> e : + formatters.byPlugin(pluginName).entrySet()) { + if (formatterName.equals(e.getKey())) { + return new FormatterProvider(formatterName, e.getValue()); + } + } + } + return null; + } + + public static class FormatterProvider { + private final String name; + private final Provider<Formatter> formatter; + + FormatterProvider(String name, + Provider<Formatter> formatter) { + this.name = name; + this.formatter = formatter; + } + + public Formatter get() { + return formatter.get(); + } + + public String getName() { + return name; + } + } +}
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 new file mode 100644 index 0000000..6a3a896 --- /dev/null +++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/MarkdownFormatter.java
@@ -0,0 +1,38 @@ +// 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 static com.googlesource.gerrit.plugins.xdocs.XDocGlobalConfig.KEY_ALLOW_HTML; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.googlesource.gerrit.plugins.xdocs.ConfigSection; + +import java.io.UnsupportedEncodingException; + +public class MarkdownFormatter implements Formatter { + public final static String NAME = "MARKDOWN"; + + @Override + public String format(ConfigSection cfg, String raw) + throws UnsupportedEncodingException { + com.google.gerrit.server.documentation.MarkdownFormatter f = + new com.google.gerrit.server.documentation.MarkdownFormatter(); + if (!cfg.getBoolean(KEY_ALLOW_HTML, false)) { + f.suppressHtml(); + } + byte[] b = f.markdownToDocHtml(raw, UTF_8.name()); + return new String(b, UTF_8); + } +}
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 new file mode 100644 index 0000000..d6ad0cd --- /dev/null +++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/PlainTextFormatter.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.xdocs.formatter; + +import static org.apache.commons.lang.StringEscapeUtils.escapeHtml; + +import com.googlesource.gerrit.plugins.xdocs.ConfigSection; + +public class PlainTextFormatter implements Formatter { + public final static String NAME = "PLAIN_TEXT"; + + @Override + public String format(ConfigSection cfg, String raw) { + return "<pre>" + escapeHtml(raw) + "</pre>"; + } +}