Serve static resources for non-jar Server plugins
Abstract from the Server plugins external packaging and allows to serve static resources from any form of Server plugin that exposes a PluginContentScanner. This allows potentially other forms of plugins (e.g. Scripting, directory-based or any other) to provide their on-line documentation and serve their static resources. Change-Id: I80b8159cf87255e3132298f5863b374b5bd44a6c
This commit is contained in:
@@ -14,7 +14,11 @@
|
|||||||
|
|
||||||
package com.google.gerrit.httpd.plugins;
|
package com.google.gerrit.httpd.plugins;
|
||||||
|
|
||||||
|
import static com.google.gerrit.server.plugins.PluginEntry.ATTR_CHARACTER_ENCODING;
|
||||||
|
import static com.google.gerrit.server.plugins.PluginEntry.ATTR_CONTENT_TYPE;
|
||||||
|
|
||||||
import com.google.common.base.CharMatcher;
|
import com.google.common.base.CharMatcher;
|
||||||
|
import com.google.common.base.Optional;
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import com.google.common.cache.Cache;
|
import com.google.common.cache.Cache;
|
||||||
@@ -27,9 +31,11 @@ import com.google.gerrit.server.config.CanonicalWebUrl;
|
|||||||
import com.google.gerrit.server.config.GerritServerConfig;
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
import com.google.gerrit.server.documentation.MarkdownFormatter;
|
import com.google.gerrit.server.documentation.MarkdownFormatter;
|
||||||
import com.google.gerrit.server.plugins.Plugin;
|
import com.google.gerrit.server.plugins.Plugin;
|
||||||
|
import com.google.gerrit.server.plugins.Plugin.ApiType;
|
||||||
|
import com.google.gerrit.server.plugins.PluginContentScanner;
|
||||||
|
import com.google.gerrit.server.plugins.PluginEntry;
|
||||||
import com.google.gerrit.server.plugins.PluginsCollection;
|
import com.google.gerrit.server.plugins.PluginsCollection;
|
||||||
import com.google.gerrit.server.plugins.ReloadPluginListener;
|
import com.google.gerrit.server.plugins.ReloadPluginListener;
|
||||||
import com.google.gerrit.server.plugins.ServerPlugin;
|
|
||||||
import com.google.gerrit.server.plugins.StartPluginListener;
|
import com.google.gerrit.server.plugins.StartPluginListener;
|
||||||
import com.google.gerrit.server.ssh.SshInfo;
|
import com.google.gerrit.server.ssh.SshInfo;
|
||||||
import com.google.gwtexpui.server.CacheHeaders;
|
import com.google.gwtexpui.server.CacheHeaders;
|
||||||
@@ -55,14 +61,11 @@ import java.io.OutputStream;
|
|||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.jar.Attributes;
|
import java.util.jar.Attributes;
|
||||||
import java.util.jar.JarEntry;
|
|
||||||
import java.util.jar.JarFile;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@@ -83,13 +86,6 @@ class HttpPluginServlet extends HttpServlet
|
|||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
private static final Logger log
|
private static final Logger log
|
||||||
= LoggerFactory.getLogger(HttpPluginServlet.class);
|
= LoggerFactory.getLogger(HttpPluginServlet.class);
|
||||||
private static final Comparator<JarEntry> JAR_ENTRY_COMPARATOR_BY_NAME =
|
|
||||||
new Comparator<JarEntry>() {
|
|
||||||
@Override
|
|
||||||
public int compare(JarEntry a, JarEntry b) {
|
|
||||||
return a.getName().compareTo(b.getName());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final MimeUtilFileTypeRegistry mimeUtil;
|
private final MimeUtilFileTypeRegistry mimeUtil;
|
||||||
private final Provider<String> webUrl;
|
private final Provider<String> webUrl;
|
||||||
@@ -276,17 +272,17 @@ class HttpPluginServlet extends HttpServlet
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (file.startsWith(holder.staticPrefix)) {
|
if (file.startsWith(holder.staticPrefix)) {
|
||||||
JarFile jar = jarFileOf(holder.plugin);
|
if (holder.plugin.getApiType() == ApiType.JS) {
|
||||||
if (jar != null) {
|
sendJsPlugin(holder.plugin, key, req, res);
|
||||||
JarEntry entry = jar.getJarEntry(file);
|
} else {
|
||||||
if (exists(entry)) {
|
PluginContentScanner scanner = holder.plugin.getContentScanner();
|
||||||
sendResource(jar, entry, key, res);
|
Optional<PluginEntry> entry = scanner.getEntry(file);
|
||||||
|
if (entry.isPresent()) {
|
||||||
|
sendResource(scanner, entry.get(), key, res);
|
||||||
} else {
|
} else {
|
||||||
resourceCache.put(key, Resource.NOT_FOUND);
|
resourceCache.put(key, Resource.NOT_FOUND);
|
||||||
Resource.NOT_FOUND.send(req, res);
|
Resource.NOT_FOUND.send(req, res);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
sendJsPlugin(holder.plugin, key, req, res);
|
|
||||||
}
|
}
|
||||||
} else if (file.equals(
|
} else if (file.equals(
|
||||||
holder.docPrefix.substring(0, holder.docPrefix.length() - 1))) {
|
holder.docPrefix.substring(0, holder.docPrefix.length() - 1))) {
|
||||||
@@ -294,19 +290,19 @@ class HttpPluginServlet extends HttpServlet
|
|||||||
} else if (file.startsWith(holder.docPrefix) && file.endsWith("/")) {
|
} else if (file.startsWith(holder.docPrefix) && file.endsWith("/")) {
|
||||||
res.sendRedirect(uri + "index.html");
|
res.sendRedirect(uri + "index.html");
|
||||||
} else if (file.startsWith(holder.docPrefix)) {
|
} else if (file.startsWith(holder.docPrefix)) {
|
||||||
JarFile jar = jarFileOf(holder.plugin);
|
PluginContentScanner scanner = holder.plugin.getContentScanner();
|
||||||
JarEntry entry = jar.getJarEntry(file);
|
Optional<PluginEntry> entry = scanner.getEntry(file);
|
||||||
if (!exists(entry)) {
|
if (!entry.isPresent()) {
|
||||||
entry = findSource(jar, file);
|
entry = findSource(scanner, file);
|
||||||
}
|
}
|
||||||
if (!exists(entry) && file.endsWith("/index.html")) {
|
if (!entry.isPresent() && file.endsWith("/index.html")) {
|
||||||
String pfx = file.substring(0, file.length() - "index.html".length());
|
String pfx = file.substring(0, file.length() - "index.html".length());
|
||||||
sendAutoIndex(jar, pfx, holder.plugin.getName(), key, res,
|
sendAutoIndex(scanner, pfx, holder.plugin.getName(), key, res,
|
||||||
holder.plugin.getSrcFile().lastModified());
|
holder.plugin.getSrcFile().lastModified());
|
||||||
} else if (exists(entry) && entry.getName().endsWith(".md")) {
|
} else if (entry.isPresent() && entry.get().getName().endsWith(".md")) {
|
||||||
sendMarkdownAsHtml(jar, entry, holder.plugin.getName(), key, res);
|
sendMarkdownAsHtml(scanner, entry.get(), holder.plugin.getName(), key, res);
|
||||||
} else if (exists(entry)) {
|
} else if (entry.isPresent()) {
|
||||||
sendResource(jar, entry, key, res);
|
sendResource(scanner, entry.get(), key, res);
|
||||||
} else {
|
} else {
|
||||||
resourceCache.put(key, Resource.NOT_FOUND);
|
resourceCache.put(key, Resource.NOT_FOUND);
|
||||||
Resource.NOT_FOUND.send(req, res);
|
Resource.NOT_FOUND.send(req, res);
|
||||||
@@ -317,18 +313,18 @@ class HttpPluginServlet extends HttpServlet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void appendEntriesSection(JarFile jar, List<JarEntry> entries,
|
private void appendEntriesSection(PluginContentScanner scanner, List<PluginEntry> entries,
|
||||||
String sectionTitle, StringBuilder md, String prefix,
|
String sectionTitle, StringBuilder md, String prefix,
|
||||||
int nameOffset) throws IOException {
|
int nameOffset) throws IOException {
|
||||||
if (!entries.isEmpty()) {
|
if (!entries.isEmpty()) {
|
||||||
md.append("## ").append(sectionTitle).append(" ##\n");
|
md.append("## ").append(sectionTitle).append(" ##\n");
|
||||||
for(JarEntry entry : entries) {
|
for(PluginEntry entry : entries) {
|
||||||
String rsrc = entry.getName().substring(prefix.length());
|
String rsrc = entry.getName().substring(prefix.length());
|
||||||
String entryTitle;
|
String entryTitle;
|
||||||
if (rsrc.endsWith(".html")) {
|
if (rsrc.endsWith(".html")) {
|
||||||
entryTitle = rsrc.substring(nameOffset, rsrc.length() - 5).replace('-', ' ');
|
entryTitle = rsrc.substring(nameOffset, rsrc.length() - 5).replace('-', ' ');
|
||||||
} else if (rsrc.endsWith(".md")) {
|
} else if (rsrc.endsWith(".md")) {
|
||||||
entryTitle = extractTitleFromMarkdown(jar, entry);
|
entryTitle = extractTitleFromMarkdown(scanner, entry);
|
||||||
if (Strings.isNullOrEmpty(entryTitle)) {
|
if (Strings.isNullOrEmpty(entryTitle)) {
|
||||||
entryTitle = rsrc.substring(nameOffset, rsrc.length() - 3).replace('-', ' ');
|
entryTitle = rsrc.substring(nameOffset, rsrc.length() - 3).replace('-', ' ');
|
||||||
}
|
}
|
||||||
@@ -342,24 +338,25 @@ class HttpPluginServlet extends HttpServlet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendAutoIndex(JarFile jar,
|
private void sendAutoIndex(PluginContentScanner scanner,
|
||||||
String prefix, String pluginName,
|
String prefix, String pluginName,
|
||||||
ResourceKey cacheKey, HttpServletResponse res, long lastModifiedTime)
|
ResourceKey cacheKey, HttpServletResponse res,long lastModifiedTime)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
List<JarEntry> cmds = Lists.newArrayList();
|
List<PluginEntry> cmds = Lists.newArrayList();
|
||||||
List<JarEntry> servlets = Lists.newArrayList();
|
List<PluginEntry> servlets = Lists.newArrayList();
|
||||||
List<JarEntry> restApis = Lists.newArrayList();
|
List<PluginEntry> restApis = Lists.newArrayList();
|
||||||
List<JarEntry> docs = Lists.newArrayList();
|
List<PluginEntry> docs = Lists.newArrayList();
|
||||||
JarEntry about = null;
|
PluginEntry about = null;
|
||||||
Enumeration<JarEntry> entries = jar.entries();
|
Enumeration<PluginEntry> entries = scanner.entries();
|
||||||
while (entries.hasMoreElements()) {
|
while (entries.hasMoreElements()) {
|
||||||
JarEntry entry = entries.nextElement();
|
PluginEntry entry = entries.nextElement();
|
||||||
String name = entry.getName();
|
String name = entry.getName();
|
||||||
long size = entry.getSize();
|
Optional<Long> size = entry.getSize();
|
||||||
if (name.startsWith(prefix)
|
if (name.startsWith(prefix)
|
||||||
&& (name.endsWith(".md")
|
&& (name.endsWith(".md")
|
||||||
|| name.endsWith(".html"))
|
|| name.endsWith(".html"))
|
||||||
&& 0 < size && size <= SMALL_RESOURCE) {
|
&& size.isPresent()
|
||||||
|
&& 0 < size.get() && size.get() <= SMALL_RESOURCE) {
|
||||||
name = name.substring(prefix.length());
|
name = name.substring(prefix.length());
|
||||||
if (name.startsWith("cmd-")) {
|
if (name.startsWith("cmd-")) {
|
||||||
cmds.add(entry);
|
cmds.add(entry);
|
||||||
@@ -377,16 +374,16 @@ class HttpPluginServlet extends HttpServlet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Collections.sort(cmds, JAR_ENTRY_COMPARATOR_BY_NAME);
|
Collections.sort(cmds, PluginEntry.COMPARATOR_BY_NAME);
|
||||||
Collections.sort(docs, JAR_ENTRY_COMPARATOR_BY_NAME);
|
Collections.sort(docs, PluginEntry.COMPARATOR_BY_NAME);
|
||||||
|
|
||||||
StringBuilder md = new StringBuilder();
|
StringBuilder md = new StringBuilder();
|
||||||
md.append(String.format("# Plugin %s #\n", pluginName));
|
md.append(String.format("# Plugin %s #\n", pluginName));
|
||||||
md.append("\n");
|
md.append("\n");
|
||||||
appendPluginInfoTable(md, jar.getManifest().getMainAttributes());
|
appendPluginInfoTable(md, scanner.getManifest().getMainAttributes());
|
||||||
|
|
||||||
if (about != null) {
|
if (about != null) {
|
||||||
InputStreamReader isr = new InputStreamReader(jar.getInputStream(about));
|
InputStreamReader isr = new InputStreamReader(scanner.getInputStream(about));
|
||||||
BufferedReader reader = new BufferedReader(isr);
|
BufferedReader reader = new BufferedReader(isr);
|
||||||
StringBuilder aboutContent = new StringBuilder();
|
StringBuilder aboutContent = new StringBuilder();
|
||||||
String line;
|
String line;
|
||||||
@@ -407,10 +404,10 @@ class HttpPluginServlet extends HttpServlet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
appendEntriesSection(jar, docs, "Documentation", md, prefix, 0);
|
appendEntriesSection(scanner, docs, "Documentation", md, prefix, 0);
|
||||||
appendEntriesSection(jar, servlets, "Servlets", md, prefix, "servlet-".length());
|
appendEntriesSection(scanner, servlets, "Servlets", md, prefix, "servlet-".length());
|
||||||
appendEntriesSection(jar, restApis, "REST APIs", md, prefix, "rest-api-".length());
|
appendEntriesSection(scanner, restApis, "REST APIs", md, prefix, "rest-api-".length());
|
||||||
appendEntriesSection(jar, cmds, "Commands", md, prefix, "cmd-".length());
|
appendEntriesSection(scanner, cmds, "Commands", md, prefix, "cmd-".length());
|
||||||
|
|
||||||
sendMarkdownAsHtml(md.toString(), pluginName, cacheKey, res, lastModifiedTime);
|
sendMarkdownAsHtml(md.toString(), pluginName, cacheKey, res, lastModifiedTime);
|
||||||
}
|
}
|
||||||
@@ -494,41 +491,38 @@ class HttpPluginServlet extends HttpServlet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String extractTitleFromMarkdown(JarFile jar, JarEntry entry)
|
private static String extractTitleFromMarkdown(PluginContentScanner scanner, PluginEntry entry)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
String charEnc = null;
|
String charEnc = null;
|
||||||
Attributes atts = entry.getAttributes();
|
Map<Object, String> atts = entry.getAttrs();
|
||||||
if (atts != null) {
|
if (atts != null) {
|
||||||
charEnc = Strings.emptyToNull(atts.getValue("Character-Encoding"));
|
charEnc = Strings.emptyToNull(atts.get(ATTR_CHARACTER_ENCODING));
|
||||||
}
|
}
|
||||||
if (charEnc == null) {
|
if (charEnc == null) {
|
||||||
charEnc = "UTF-8";
|
charEnc = "UTF-8";
|
||||||
}
|
}
|
||||||
return new MarkdownFormatter().extractTitleFromMarkdown(
|
return new MarkdownFormatter().extractTitleFromMarkdown(
|
||||||
readWholeEntry(jar, entry),
|
readWholeEntry(scanner, entry),
|
||||||
charEnc);
|
charEnc);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JarEntry findSource(JarFile jar, String file) {
|
private static Optional<PluginEntry> findSource(
|
||||||
|
PluginContentScanner scanner, String file) throws IOException {
|
||||||
if (file.endsWith(".html")) {
|
if (file.endsWith(".html")) {
|
||||||
int d = file.lastIndexOf('.');
|
int d = file.lastIndexOf('.');
|
||||||
return jar.getJarEntry(file.substring(0, d) + ".md");
|
return scanner.getEntry(file.substring(0, d) + ".md");
|
||||||
}
|
}
|
||||||
return null;
|
return Optional.absent();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean exists(JarEntry entry) {
|
private void sendMarkdownAsHtml(PluginContentScanner scanner, PluginEntry entry,
|
||||||
return entry != null && entry.getSize() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendMarkdownAsHtml(JarFile jar, JarEntry entry,
|
|
||||||
String pluginName, ResourceKey key, HttpServletResponse res)
|
String pluginName, ResourceKey key, HttpServletResponse res)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
byte[] rawmd = readWholeEntry(jar, entry);
|
byte[] rawmd = readWholeEntry(scanner, entry);
|
||||||
String encoding = null;
|
String encoding = null;
|
||||||
Attributes atts = entry.getAttributes();
|
Map<Object, String> atts = entry.getAttrs();
|
||||||
if (atts != null) {
|
if (atts != null) {
|
||||||
encoding = Strings.emptyToNull(atts.getValue("Character-Encoding"));
|
encoding = Strings.emptyToNull(atts.get(ATTR_CHARACTER_ENCODING));
|
||||||
}
|
}
|
||||||
|
|
||||||
String txtmd = RawParseUtils.decode(
|
String txtmd = RawParseUtils.decode(
|
||||||
@@ -541,20 +535,21 @@ class HttpPluginServlet extends HttpServlet
|
|||||||
sendMarkdownAsHtml(txtmd, pluginName, key, res, time);
|
sendMarkdownAsHtml(txtmd, pluginName, key, res, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendResource(JarFile jar, JarEntry entry,
|
private void sendResource(PluginContentScanner scanner, PluginEntry entry,
|
||||||
ResourceKey key, HttpServletResponse res)
|
ResourceKey key, HttpServletResponse res)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
byte[] data = null;
|
byte[] data = null;
|
||||||
if (entry.getSize() <= SMALL_RESOURCE) {
|
Optional<Long> size = entry.getSize();
|
||||||
data = readWholeEntry(jar, entry);
|
if (size.isPresent() && size.get() <= SMALL_RESOURCE) {
|
||||||
|
data = readWholeEntry(scanner, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
String contentType = null;
|
String contentType = null;
|
||||||
String charEnc = null;
|
String charEnc = null;
|
||||||
Attributes atts = entry.getAttributes();
|
Map<Object, String> atts = entry.getAttrs();
|
||||||
if (atts != null) {
|
if (atts != null) {
|
||||||
contentType = Strings.emptyToNull(atts.getValue("Content-Type"));
|
contentType = Strings.emptyToNull(atts.get(ATTR_CONTENT_TYPE));
|
||||||
charEnc = Strings.emptyToNull(atts.getValue("Character-Encoding"));
|
charEnc = Strings.emptyToNull(atts.get(ATTR_CHARACTER_ENCODING));
|
||||||
}
|
}
|
||||||
if (contentType == null) {
|
if (contentType == null) {
|
||||||
contentType = mimeUtil.getMimeType(entry.getName(), data).toString();
|
contentType = mimeUtil.getMimeType(entry.getName(), data).toString();
|
||||||
@@ -568,7 +563,9 @@ class HttpPluginServlet extends HttpServlet
|
|||||||
if (0 < time) {
|
if (0 < time) {
|
||||||
res.setDateHeader("Last-Modified", time);
|
res.setDateHeader("Last-Modified", time);
|
||||||
}
|
}
|
||||||
res.setHeader("Content-Length", Long.toString(entry.getSize()));
|
if (size.isPresent()) {
|
||||||
|
res.setHeader("Content-Length", size.get().toString());
|
||||||
|
}
|
||||||
res.setContentType(contentType);
|
res.setContentType(contentType);
|
||||||
if (charEnc != null) {
|
if (charEnc != null) {
|
||||||
res.setCharacterEncoding(charEnc);
|
res.setCharacterEncoding(charEnc);
|
||||||
@@ -580,7 +577,7 @@ class HttpPluginServlet extends HttpServlet
|
|||||||
.setLastModified(time));
|
.setLastModified(time));
|
||||||
res.getOutputStream().write(data);
|
res.getOutputStream().write(data);
|
||||||
} else {
|
} else {
|
||||||
writeToResponse(res, jar.getInputStream(entry));
|
writeToResponse(res, scanner.getInputStream(entry));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -620,10 +617,10 @@ class HttpPluginServlet extends HttpServlet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] readWholeEntry(JarFile jar, JarEntry entry)
|
private static byte[] readWholeEntry(PluginContentScanner scanner, PluginEntry entry)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
byte[] data = new byte[(int) entry.getSize()];
|
byte[] data = new byte[entry.getSize().get().intValue()];
|
||||||
InputStream in = jar.getInputStream(entry);
|
InputStream in = scanner.getInputStream(entry);
|
||||||
try {
|
try {
|
||||||
IO.readFully(in, data, 0, data.length);
|
IO.readFully(in, data, 0, data.length);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -632,14 +629,6 @@ class HttpPluginServlet extends HttpServlet
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JarFile jarFileOf(Plugin plugin) {
|
|
||||||
if(plugin instanceof ServerPlugin) {
|
|
||||||
return ((ServerPlugin) plugin).getJarFile();
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class PluginHolder {
|
private static class PluginHolder {
|
||||||
final Plugin plugin;
|
final Plugin plugin;
|
||||||
final GuiceFilter filter;
|
final GuiceFilter filter;
|
||||||
@@ -656,13 +645,14 @@ class HttpPluginServlet extends HttpServlet
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static String getPrefix(Plugin plugin, String attr, String def) {
|
private static String getPrefix(Plugin plugin, String attr, String def) {
|
||||||
JarFile jarFile = jarFileOf(plugin);
|
File srcFile = plugin.getSrcFile();
|
||||||
if (jarFile == null) {
|
PluginContentScanner scanner = plugin.getContentScanner();
|
||||||
|
if (srcFile == null || scanner == PluginContentScanner.EMPTY) {
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
String prefix = jarFile.getManifest().getMainAttributes()
|
String prefix =
|
||||||
.getValue(attr);
|
scanner.getManifest().getMainAttributes().getValue(attr);
|
||||||
if (prefix != null) {
|
if (prefix != null) {
|
||||||
return CharMatcher.is('/').trimFrom(prefix) + "/";
|
return CharMatcher.is('/').trimFrom(prefix) + "/";
|
||||||
} else {
|
} else {
|
||||||
|
@@ -299,7 +299,7 @@ public class JarScanner implements PluginContentScanner {
|
|||||||
|
|
||||||
private PluginEntry resourceOf(JarEntry jarEntry) throws IOException {
|
private PluginEntry resourceOf(JarEntry jarEntry) throws IOException {
|
||||||
return new PluginEntry(jarEntry.getName(), jarEntry.getTime(),
|
return new PluginEntry(jarEntry.getName(), jarEntry.getTime(),
|
||||||
jarEntry.getSize(), attributesOf(jarEntry));
|
Optional.of(jarEntry.getSize()), attributesOf(jarEntry));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<Object, String> attributesOf(JarEntry jarEntry)
|
private Map<Object, String> attributesOf(JarEntry jarEntry)
|
||||||
|
@@ -13,7 +13,10 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
package com.google.gerrit.server.plugins;
|
package com.google.gerrit.server.plugins;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -26,15 +29,23 @@ import java.util.Map;
|
|||||||
public class PluginEntry {
|
public class PluginEntry {
|
||||||
public static final String ATTR_CHARACTER_ENCODING = "Character-Encoding";
|
public static final String ATTR_CHARACTER_ENCODING = "Character-Encoding";
|
||||||
public static final String ATTR_CONTENT_TYPE = "Content-Type";
|
public static final String ATTR_CONTENT_TYPE = "Content-Type";
|
||||||
|
public static final Comparator<PluginEntry> COMPARATOR_BY_NAME =
|
||||||
|
new Comparator<PluginEntry>() {
|
||||||
|
@Override
|
||||||
|
public int compare(PluginEntry a, PluginEntry b) {
|
||||||
|
return a.getName().compareTo(b.getName());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private static final Map<Object,String> EMPTY_ATTRS = Collections.emptyMap();
|
private static final Map<Object, String> EMPTY_ATTRS = Collections.emptyMap();
|
||||||
|
private static final Optional<Long> NO_SIZE = Optional.absent();
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final long time;
|
private final long time;
|
||||||
private final long size;
|
private final Optional<Long> size;
|
||||||
private final Map<Object, String> attrs;
|
private final Map<Object, String> attrs;
|
||||||
|
|
||||||
public PluginEntry(String name, long time, long size,
|
public PluginEntry(String name, long time, Optional<Long> size,
|
||||||
Map<Object, String> attrs) {
|
Map<Object, String> attrs) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.time = time;
|
this.time = time;
|
||||||
@@ -42,10 +53,14 @@ public class PluginEntry {
|
|||||||
this.attrs = attrs;
|
this.attrs = attrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PluginEntry(String name, long time, long size) {
|
public PluginEntry(String name, long time, Optional<Long> size) {
|
||||||
this(name, time, size, EMPTY_ATTRS);
|
this(name, time, size, EMPTY_ATTRS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PluginEntry(String name, long time) {
|
||||||
|
this(name, time, NO_SIZE, EMPTY_ATTRS);
|
||||||
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
@@ -54,11 +69,11 @@ public class PluginEntry {
|
|||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getSize() {
|
public Optional<Long> getSize() {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<Object, String> getAttrs() {
|
public Map<Object, String> getAttrs() {
|
||||||
return attrs;
|
return attrs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user