Make it configurable which mime types should be handled as project doc At the moment it is hard-coded that "*.md" files are handled as Markdown project documentation. Instead one can now define in the global plugin configuration which mime types should be handled by the Markdown formatter: [formatter "MARKDOWN"] mimeType = text/x-markdown A mapping from file extensions to mime types already exists and doesn't need to be reimplemented, instead just rely on the mime type. Multiple mime types may be specified for a formatter. A formatter for which no mime type is specified is disabled. An init step creates the basic plugin configuration so that the default mime type for a formatter is automatically set. At the moment there is only a single formatter, the formatter for Markdown, but follow-up changes will add formatters for other syntaxes, such as Asciidoc. Change-Id: I0f89463f89baaac962876a166e72ff8e26865280 Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
diff --git a/BUCK b/BUCK index 7a43f6f..339a27c 100644 --- a/BUCK +++ b/BUCK
@@ -10,6 +10,7 @@ 'Gerrit-ApiVersion: 2.11-SNAPSHOT', 'Gerrit-HttpModule: com.googlesource.gerrit.plugins.xdocs.HttpModule', 'Gerrit-Module: com.googlesource.gerrit.plugins.xdocs.Module', + 'Gerrit-InitStep: com.googlesource.gerrit.plugins.xdocs.XDocInit', ], )
diff --git a/pom.xml b/pom.xml index 9d7d24c..6776eb4 100644 --- a/pom.xml +++ b/pom.xml
@@ -41,6 +41,7 @@ <Gerrit-PluginName>xdocs</Gerrit-PluginName> <Gerrit-HttpModule>com.googlesource.gerrit.plugins.xdocs.HttpModule</Gerrit-HttpModule> <Gerrit-Module>com.googlesource.gerrit.plugins.xdocs.Module</Gerrit-Module> + <Gerrit-InitStep>com.googlesource.gerrit.plugins.xdocs.XDocInit</Gerrit-InitStep> <Implementation-Vendor>Gerrit Code Review</Implementation-Vendor> <Implementation-URL>http://code.google.com/p/gerrit/</Implementation-URL>
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 32fb4e0..cd5d676 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocFileWebLink.java +++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocFileWebLink.java
@@ -18,6 +18,8 @@ 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; @@ -31,8 +33,11 @@ GitRepositoryManager repoManager, @Named(XDocLoader.Module.X_DOC_RESOURCES) LoadingCache<String, Resource> cache, XDocProjectConfig.Factory cfgFactory, - ProjectCache projectCache) { - super(pluginName, repoManager, cache, cfgFactory, projectCache); + ProjectCache projectCache, + FileTypeRegistry fileTypeRegistry, + PluginConfigFactory pluginCfgFactory) { + super(pluginName, repoManager, cache, cfgFactory, projectCache, + fileTypeRegistry, pluginCfgFactory); } @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 df6ff5a..062a683 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocGlobalConfig.java +++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocGlobalConfig.java
@@ -14,11 +14,17 @@ package com.googlesource.gerrit.plugins.xdocs; +import eu.medsea.mimeutil.MimeType; + 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; @@ -34,4 +40,20 @@ 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; + } + + static void initialize(Config cfg) { + cfg.setString(SECTION_FORMATTER, Formatter.MARKDOWN.name(), KEY_MIME_TYPE, + "text/x-markdown"); + } }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocInit.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocInit.java new file mode 100644 index 0000000..25cd2a2 --- /dev/null +++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocInit.java
@@ -0,0 +1,62 @@ +// 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.gerrit.extensions.annotations.PluginName; +import com.google.gerrit.pgm.init.api.ConsoleUI; +import com.google.gerrit.pgm.init.api.InitStep; +import com.google.gerrit.server.config.SitePaths; +import com.google.inject.Inject; +import com.google.inject.Singleton; + +import org.eclipse.jgit.storage.file.FileBasedConfig; +import org.eclipse.jgit.util.FS; + +import java.io.File; + +@Singleton +public class XDocInit implements InitStep { + private final String pluginName; + private final SitePaths sitePaths; + private final ConsoleUI ui; + + @Inject + XDocInit(@PluginName String pluginName, SitePaths sitePaths, + ConsoleUI ui) { + this.pluginName = pluginName; + this.sitePaths = sitePaths; + this.ui = ui; + } + + @Override + public void run() throws Exception { + File pluginConfig = new File(sitePaths.etc_dir, pluginName + ".config"); + if (!pluginConfig.exists()) { + ui.message("\n"); + ui.header("%s plugin", pluginName); + + FileBasedConfig cfg = new FileBasedConfig(pluginConfig, FS.DETECTED); + XDocGlobalConfig.initialize(cfg); + cfg.save(); + + ui.message("Initialized %s plugin: %s", pluginName, + pluginConfig.getAbsolutePath()); + } + } + + @Override + public void postRun() throws Exception { + } +}
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 ab56e70..c01cd8b 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocServlet.java +++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocServlet.java
@@ -22,6 +22,7 @@ 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; @@ -30,6 +31,7 @@ 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; @@ -43,6 +45,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 org.eclipse.jgit.errors.RepositoryNotFoundException; @@ -58,6 +62,7 @@ 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; @@ -78,6 +83,8 @@ private final LoadingCache<String, Resource> docCache; private final FileTypeRegistry fileTypeRegistry; private final XDocProjectConfig.Factory cfgFactory; + private final String pluginName; + private final PluginConfigFactory pluginCfgFactory; @Inject XDocServlet( @@ -88,7 +95,9 @@ GitRepositoryManager repoManager, @Named(XDocLoader.Module.X_DOC_RESOURCES) LoadingCache<String, Resource> cache, FileTypeRegistry fileTypeRegistry, - XDocProjectConfig.Factory cfgFactory) { + XDocProjectConfig.Factory cfgFactory, + @PluginName String pluginName, + PluginConfigFactory pluginCfgFactory) { this.db = db; this.projectControlFactory = projectControlFactory; this.projectCache = projectCache; @@ -97,6 +106,8 @@ this.docCache = cache; this.fileTypeRegistry = fileTypeRegistry; this.cfgFactory = cfgFactory; + this.pluginName = pluginName; + this.pluginCfgFactory = pluginCfgFactory; } @Override @@ -119,8 +130,11 @@ res.sendRedirect(getRedirectUrl(req, key, cfg)); return; } + XDocGlobalConfig pluginCfg = + new XDocGlobalConfig(pluginCfgFactory.getGlobalPluginConfig(pluginName)); MimeType mimeType = fileTypeRegistry.getMimeType(key.file, null); - if (!key.file.endsWith(".md") + Map<MimeType, Formatter> mimeTypes = pluginCfg.getMimeTypes(); + if (!mimeTypes.keySet().contains(mimeType) && !("image".equals(mimeType.getMediaType()) && fileTypeRegistry.isSafeInline(mimeType))) { Resource.NOT_FOUND.send(req, res); @@ -177,7 +191,7 @@ } Resource rsc; - if (key.file.endsWith(".md")) { + if (mimeTypes.get(mimeType) != null) { rsc = docCache.getUnchecked( (new XDocResourceKey(key.project, key.file, revId)).asString()); } else if ("image".equals(mimeType.getMediaType())) {
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 1838b0f..e347516 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocWebLink.java +++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocWebLink.java
@@ -21,6 +21,8 @@ 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; @@ -28,6 +30,8 @@ import com.google.inject.Singleton; import com.google.inject.name.Named; +import eu.medsea.mimeutil.MimeType; + import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Repository; @@ -46,6 +50,8 @@ private final LoadingCache<String, Resource> docCache; private final XDocProjectConfig.Factory cfgFactory; private final ProjectCache projectCache; + private final FileTypeRegistry fileTypeRegistry; + private final PluginConfigFactory pluginCfgFactory; @Inject XDocWebLink( @@ -53,12 +59,16 @@ GitRepositoryManager repoManager, @Named(XDocLoader.Module.X_DOC_RESOURCES) LoadingCache<String, Resource> cache, XDocProjectConfig.Factory cfgFactory, - ProjectCache projectCache) { + ProjectCache projectCache, + FileTypeRegistry fileTypeRegistry, + PluginConfigFactory pluginCfgFactory) { this.pluginName = pluginName; this.repoManager = repoManager; this.docCache = cache; this.cfgFactory = cfgFactory; this.projectCache = projectCache; + this.fileTypeRegistry = fileTypeRegistry; + this.pluginCfgFactory = pluginCfgFactory; } @Override @@ -84,7 +94,10 @@ public String getPatchUrl(String projectName, String revision, String fileName) { - if (!fileName.endsWith(".md")) { + XDocGlobalConfig pluginCfg = + new XDocGlobalConfig(pluginCfgFactory.getGlobalPluginConfig(pluginName)); + MimeType mimeType = fileTypeRegistry.getMimeType(fileName, null); + if (!pluginCfg.getMimeTypes().keySet().contains(mimeType)) { return null; }
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md index 7b71bf4..3ec161f 100644 --- a/src/main/resources/Documentation/config.md +++ b/src/main/resources/Documentation/config.md
@@ -30,11 +30,20 @@ The global configuration of the @PLUGIN@ plugin is done in the `$site_path/etc/@PLUGIN@.config` file. +The plugin contains an init step that creates the initial plugin +configuration. + ``` [formatter "MARKDOWN"] - allowHtml = false + mimeType = text/x-markdown ``` +<a id="formatterMimeType"> +formatter.<formatter>.mimeType +: The mime type of files that you be rendered by this formatter. + + Multiple mime types may be specified for a formatter. + <a id="formatterAllowHtml"> formatter.<formatter>.allowHtml : Whether inline HTML blocks and inline HTML tags are allowed for