blob: def2f5b56ca20c59eeedc74c078523c7236b6cb0 [file] [log] [blame]
// 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_ENABLED;
import static com.googlesource.gerrit.plugins.xdocs.XDocGlobalConfig.KEY_EXT;
import static com.googlesource.gerrit.plugins.xdocs.XDocGlobalConfig.KEY_FORMATTER;
import static com.googlesource.gerrit.plugins.xdocs.XDocGlobalConfig.KEY_MIME_TYPE;
import static com.googlesource.gerrit.plugins.xdocs.XDocGlobalConfig.KEY_PREFIX;
import static com.googlesource.gerrit.plugins.xdocs.XDocGlobalConfig.KEY_PRIO;
import static com.googlesource.gerrit.plugins.xdocs.XDocGlobalConfig.SECTION_FORMATTER;
import com.google.gerrit.common.data.PatchScript.FileMode;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.change.FileContentUtil;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.mime.FileTypeRegistry;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.googlesource.gerrit.plugins.xdocs.ConfigSection;
import com.googlesource.gerrit.plugins.xdocs.XDocGlobalConfig;
import eu.medsea.mimeutil.MimeType;
import java.util.Map.Entry;
import org.apache.commons.io.FilenameUtils;
import org.eclipse.jgit.lib.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class Formatters {
private static final Logger log = LoggerFactory.getLogger(Formatters.class);
public static final String RAW_FORMATTER = "RAW";
private final String pluginName;
private final PluginConfigFactory pluginCfgFactory;
private final FileTypeRegistry fileTypeRegistry;
private final DynamicMap<Formatter> formatters;
private final ProjectCache projectCache;
@Inject
Formatters(
@PluginName String pluginName,
PluginConfigFactory pluginCfgFactory,
FileTypeRegistry fileTypeRegistry,
DynamicMap<Formatter> formatters,
ProjectCache projectCache) {
this.pluginName = pluginName;
this.pluginCfgFactory = pluginCfgFactory;
this.fileTypeRegistry = fileTypeRegistry;
this.formatters = formatters;
this.projectCache = projectCache;
}
public FormatterProvider get(String projectName, String fileName) {
ProjectState project = projectCache.get(new Project.NameKey(projectName));
if (project == null) {
return null;
}
return get(project, fileName);
}
public FormatterProvider get(ProjectState project, String fileName) {
XDocGlobalConfig globalCfg =
new XDocGlobalConfig(pluginCfgFactory.getGlobalPluginConfig(pluginName));
MimeType mimeType = fileTypeRegistry.getMimeType(fileName, (byte[]) null);
mimeType =
new MimeType(
FileContentUtil.resolveContentType(
project, fileName, FileMode.FILE, mimeType.toString()));
String extension = FilenameUtils.getExtension(fileName);
FormatterProvider formatter = null;
int formatterPrio = 0;
for (String pluginName : formatters.plugins()) {
for (Entry<String, Provider<Formatter>> e : formatters.byPlugin(pluginName).entrySet()) {
if (!globalCfg.getFormatterConfig(e.getKey()).getBoolean(KEY_ENABLED, true)) {
continue;
}
ConfigSection formatterCfg = getFormatterConfig(e.getKey(), project);
String[] prefixes = formatterCfg.getStringList(KEY_PREFIX);
if (prefixes.length > 0) {
boolean match = false;
for (String prefix : prefixes) {
if (fileName.startsWith(prefix)) {
match = true;
break;
}
}
if (!match) {
continue;
}
}
for (String mt : formatterCfg.getStringList(KEY_MIME_TYPE)) {
MimeType configuredMimeType = new MimeType(mt);
if (mimeType.equals(configuredMimeType)
|| ("*".equals(configuredMimeType.getSubType())
&& mimeType.getMediaType().equals(configuredMimeType.getMediaType()))) {
int prio = formatterCfg.getInt(KEY_PRIO, 0);
if (formatter == null || prio > formatterPrio) {
formatter = new FormatterProvider(e.getKey(), e.getValue());
formatterPrio = prio;
}
}
}
for (String ext : formatterCfg.getStringList(KEY_EXT)) {
if (extension.equals(ext) || "*".equals(ext)) {
int prio = formatterCfg.getInt(KEY_PRIO, 0);
if (formatter == null || prio > formatterPrio) {
formatter = new FormatterProvider(e.getKey(), e.getValue());
formatterPrio = prio;
}
}
}
}
}
return formatter;
}
public ConfigSection getFormatterConfig(String formatterName, String projectName) {
ProjectState project = projectCache.get(new Project.NameKey(projectName));
if (project == null) {
return null;
}
return getFormatterConfig(formatterName, project);
}
public ConfigSection getFormatterConfig(String formatterName, ProjectState project) {
for (ProjectState p : project.tree()) {
Config cfg = pluginCfgFactory.getProjectPluginConfig(p, pluginName);
if (cfg.getSubsections(SECTION_FORMATTER).contains(formatterName)) {
return new XDocGlobalConfig(cfg).getFormatterConfig(formatterName);
}
}
return new XDocGlobalConfig(pluginCfgFactory.getGlobalPluginConfig(pluginName))
.getFormatterConfig(formatterName);
}
public FormatterProvider getByName(String formatterName) {
if (formatterName.equals(RAW_FORMATTER)) {
return resolveRawFormatter();
}
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 FormatterProvider getRawFormatter() {
return getByName(RAW_FORMATTER);
}
private FormatterProvider resolveRawFormatter() {
XDocGlobalConfig globalCfg =
new XDocGlobalConfig(pluginCfgFactory.getGlobalPluginConfig(pluginName));
String formatterName =
globalCfg
.getFormatterConfig(RAW_FORMATTER)
.getString(KEY_FORMATTER, PlainTextFormatter.NAME);
if (formatterName.equals(RAW_FORMATTER)) {
log.warn(
String.format(
"%s plugin: Invalid '%s' formatter configuration, '%s' formatter cannot be set to '%s', using '%s' formatter",
pluginName, RAW_FORMATTER, RAW_FORMATTER, formatterName, PlainTextFormatter.NAME));
formatterName = PlainTextFormatter.NAME;
}
FormatterProvider formatter = getByName(formatterName);
if (formatter == null) {
log.warn(
String.format(
"%s plugin: Invalid '%s' formatter configuration, formatter '%s' not found, using '%s' formatter",
pluginName, RAW_FORMATTER, formatterName, PlainTextFormatter.NAME));
formatter = getByName(PlainTextFormatter.NAME);
}
return new FormatterProvider(RAW_FORMATTER, formatter.formatter);
}
public static class FormatterProvider {
private final String name;
private final Provider<? extends Formatter> formatter;
FormatterProvider(String name, Provider<? extends Formatter> formatter) {
this.name = name;
this.formatter = formatter;
}
public Formatter get() {
return formatter.get();
}
public String getName() {
return name;
}
}
}