Use sensible defaults in the dev server
When no config file is present, default to exporting all git
repositories under the current directory and making templates
reloadable. Move some of the default dev-specific behavior out of
GitilesFilter and into DevServer, including removing the
gitiles.reloadTemplates config option entirely.
Change-Id: Ibf62d49ed2a77ff232d5477b326c3f03e98895fb
diff --git a/gitiles-dev/src/main/java/com/google/gitiles/dev/DevServer.java b/gitiles-dev/src/main/java/com/google/gitiles/dev/DevServer.java
index 7ce5a83..8502aac 100644
--- a/gitiles-dev/src/main/java/com/google/gitiles/dev/DevServer.java
+++ b/gitiles-dev/src/main/java/com/google/gitiles/dev/DevServer.java
@@ -14,7 +14,12 @@
package com.google.gitiles.dev;
+import static com.google.gitiles.GitilesServlet.STATIC_PREFIX;
+
+import com.google.common.base.Objects;
+import com.google.gitiles.DebugRenderer;
import com.google.gitiles.GitilesServlet;
+import com.google.gitiles.PathServlet;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
@@ -28,23 +33,119 @@
import org.eclipse.jetty.util.resource.FileResource;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ThreadPool;
+import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.util.FS;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
-import java.net.MalformedURLException;
+import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
-import java.net.URL;
+import java.net.UnknownHostException;
class DevServer {
+ private static final Logger log = LoggerFactory.getLogger(PathServlet.class);
+
+ private static Config defaultConfig() throws UnknownHostException {
+ Config cfg = new Config();
+ String cwd = System.getProperty("user.dir");
+ cfg.setString("gitiles", null, "basePath", cwd);
+ cfg.setBoolean("gitiles", null, "exportAll", true);
+ cfg.setString("gitiles", null, "baseGitUrl", "file://" + cwd + "/");
+ String networkHostName = InetAddress.getLocalHost().getCanonicalHostName();
+ cfg.setString("gitiles", null, "siteTitle",
+ String.format("Gitiles - %s:%s", networkHostName, cwd));
+ cfg.setString("gitiles", null, "canonicalHostName", new File(cwd).getName());
+ return cfg;
+ }
+
+ private static FileNotFoundException badSourceRoot(URI u) {
+ return new FileNotFoundException("Cannot find source root from " + u);
+ }
+
+ private static FileNotFoundException badSourceRoot(URI u, Throwable cause) {
+ FileNotFoundException notFound = badSourceRoot(u);
+ notFound.initCause(cause);
+ return notFound;
+ }
+
+ private static File findSourceRoot() throws IOException {
+ URI u;
+ try {
+ u = DevServer.class.getResource(DevServer.class.getSimpleName() + ".class").toURI();
+ } catch (URISyntaxException e) {
+ u = null;
+ }
+ if (u == null) {
+ throw new FileNotFoundException("Cannot find Gitiles source directory");
+ }
+ if ("jar".equals(u.getScheme())) {
+ int jarEntry = u.getPath().indexOf("!/");
+ if (jarEntry < 0) {
+ throw badSourceRoot(u);
+ }
+ try {
+ return findSourceRoot(new URI(u.getPath().substring(0, jarEntry)));
+ } catch (URISyntaxException e) {
+ throw badSourceRoot(u, e);
+ }
+ } else {
+ return findSourceRoot(u);
+ }
+ }
+
+ private static File findSourceRoot(URI targetUri) throws IOException {
+ if (!"file".equals(targetUri.getScheme())) {
+ throw badSourceRoot(targetUri);
+ }
+ String targetPath = targetUri.getPath();
+ // targetPath is an arbitrary path under gitiles-dev/target in the standard
+ // Maven package layout.
+ int targetIndex = targetPath.lastIndexOf("gitiles-dev/target/");
+ if (targetIndex < 0) {
+ throw badSourceRoot(targetUri);
+ }
+ String path = targetPath.substring(0, targetIndex);
+ URI u;
+ try {
+ u = new URI("file", path, null).normalize();
+ } catch (URISyntaxException e) {
+ throw new IOException(e);
+ }
+ File root = new File(u);
+ if (!root.exists() || !root.isDirectory()) {
+ throw badSourceRoot(targetUri);
+ }
+ return root;
+ }
+
+ private final File sourceRoot;
+ private final Config cfg;
private final Server httpd;
- DevServer(Config cfg) throws IOException {
+ DevServer(File cfgFile) throws IOException, ConfigInvalidException {
+ sourceRoot = findSourceRoot();
+
+ Config cfg = defaultConfig();
+ if (cfgFile.exists() && cfgFile.isFile()) {
+ FileBasedConfig fcfg = new FileBasedConfig(cfg, cfgFile, FS.DETECTED);
+ fcfg.load();
+ cfg = fcfg;
+ } else {
+ // TODO(dborowitz): This is not getting outputted, we're probably missing
+ // some logging config.
+ log.info("Config file %s not found, using defaults", cfgFile.getPath());
+ }
+ this.cfg = cfg;
+
httpd = new Server();
- httpd.setConnectors(connectors(cfg));
- httpd.setThreadPool(threadPool(cfg));
+ httpd.setConnectors(connectors());
+ httpd.setThreadPool(threadPool());
httpd.setHandler(handler());
}
@@ -53,7 +154,7 @@
httpd.join();
}
- private Connector[] connectors(Config cfg) {
+ private Connector[] connectors() {
Connector c = new SelectChannelConnector();
c.setHost(null);
c.setPort(cfg.getInt("gitiles", null, "port", 8080));
@@ -61,7 +162,7 @@
return new Connector[]{c};
}
- private ThreadPool threadPool(Config cfg) {
+ private ThreadPool threadPool() {
QueuedThreadPool pool = new QueuedThreadPool();
pool.setName("HTTP");
pool.setMinThreads(2);
@@ -75,54 +176,33 @@
handlers.addHandler(staticHandler());
handlers.addHandler(appHandler());
return handlers;
-
}
private Handler appHandler() {
+ GitilesServlet servlet = new GitilesServlet(
+ cfg,
+ new DebugRenderer(
+ STATIC_PREFIX,
+ cfg.getString("gitiles", null, "customTemplates"),
+ new File(sourceRoot, "gitiles-servlet/src/main/resources/com/google/gitiles/templates")
+ .getPath(),
+ Objects.firstNonNull(cfg.getString("gitiles", null, "siteTitle"), "Gitiles")),
+ null, null, null, null);
+
ServletContextHandler handler = new ServletContextHandler();
handler.setContextPath("");
- handler.addServlet(new ServletHolder(new GitilesServlet()), "/*");
+ handler.addServlet(new ServletHolder(servlet), "/*");
return handler;
}
- private FileNotFoundException badWebRoot(URL u) {
- return new FileNotFoundException("Cannot find web root from " + u);
- }
-
- private FileNotFoundException badWebRoot(URL u, Throwable cause) {
- FileNotFoundException notFound = badWebRoot(u);
- notFound.initCause(cause);
- return notFound;
- }
-
- private Handler staticHandler(URL targetUrl) throws IOException {
- if (!"file".equals(targetUrl.getProtocol())) {
- throw badWebRoot(targetUrl);
- }
- String targetPath = targetUrl.getPath();
- // targetPath is an arbitrary path under gitiles-dev/target in the standard
- // Maven package layout.
- int targetIndex = targetPath.lastIndexOf("gitiles-dev/target/");
- if (targetIndex < 0) {
- throw badWebRoot(targetUrl);
- }
- String staticPath = targetPath.substring(0, targetIndex)
- + "./gitiles-servlet/src/main/resources/com/google/gitiles/static";
- URI staticUri;
- try {
- staticUri = new URI("file", staticPath, null).normalize();
- } catch (URISyntaxException e) {
- throw new IOException(e);
- }
- File staticRoot = new File(staticUri);
- if (!staticRoot.exists() || !staticRoot.isDirectory()) {
- throw badWebRoot(targetUrl);
- }
+ private Handler staticHandler() throws IOException {
+ File staticRoot = new File(sourceRoot,
+ "gitiles-servlet/src/main/resources/com/google/gitiles/static");
ResourceHandler rh = new ResourceHandler();
try {
- rh.setBaseResource(new FileResource(staticUri.toURL()));
+ rh.setBaseResource(new FileResource(staticRoot.toURI().toURL()));
} catch (URISyntaxException e) {
- throw badWebRoot(targetUrl, e);
+ throw new IOException(e);
}
rh.setWelcomeFiles(new String[]{});
rh.setDirectoriesListed(false);
@@ -130,24 +210,4 @@
handler.setHandler(rh);
return handler;
}
-
- private Handler staticHandler() throws IOException {
- URL u = getClass().getResource(getClass().getSimpleName() + ".class");
- if (u == null) {
- throw new FileNotFoundException("Cannot find web root");
- }
- if ("jar".equals(u.getProtocol())) {
- int jarEntry = u.getPath().indexOf("!/");
- if (jarEntry < 0) {
- throw badWebRoot(u);
- }
- try {
- return staticHandler(new URL(u.getPath().substring(0, jarEntry)));
- } catch (MalformedURLException e) {
- throw badWebRoot(u, e);
- }
- } else {
- return staticHandler(u);
- }
- }
}
diff --git a/gitiles-dev/src/main/java/com/google/gitiles/dev/Main.java b/gitiles-dev/src/main/java/com/google/gitiles/dev/Main.java
index 204a229..2522944 100644
--- a/gitiles-dev/src/main/java/com/google/gitiles/dev/Main.java
+++ b/gitiles-dev/src/main/java/com/google/gitiles/dev/Main.java
@@ -18,6 +18,6 @@
public class Main {
public static void main(String[] args) throws Exception {
- new DevServer(GitilesConfig.loadDefault()).start();
+ new DevServer(GitilesConfig.defaultFile()).start();
}
}
diff --git a/gitiles-servlet/src/main/java/com/google/gitiles/DefaultUrls.java b/gitiles-servlet/src/main/java/com/google/gitiles/DefaultUrls.java
index 6495b5d..83c5436 100644
--- a/gitiles-servlet/src/main/java/com/google/gitiles/DefaultUrls.java
+++ b/gitiles-servlet/src/main/java/com/google/gitiles/DefaultUrls.java
@@ -40,7 +40,7 @@
this.canonicalHostName = InetAddress.getLocalHost().getCanonicalHostName();
}
this.baseGitUrl = checkNotNull(baseGitUrl, "baseGitUrl");
- this.baseGerritUrl = checkNotNull(baseGerritUrl, "baseGerritUrl");
+ this.baseGerritUrl = baseGerritUrl;
}
@Override
diff --git a/gitiles-servlet/src/main/java/com/google/gitiles/GitilesConfig.java b/gitiles-servlet/src/main/java/com/google/gitiles/GitilesConfig.java
index bf87c4a..3f6c35c 100644
--- a/gitiles-servlet/src/main/java/com/google/gitiles/GitilesConfig.java
+++ b/gitiles-servlet/src/main/java/com/google/gitiles/GitilesConfig.java
@@ -29,12 +29,11 @@
private static final String PROPERTY_NAME = "com.google.gitiles.configPath";
private static final String DEFAULT_PATH = "gitiles.config";
- public static Config loadDefault() throws IOException, ConfigInvalidException {
- return loadDefault(null);
+ public static File defaultFile() {
+ return defaultFile(null);
}
- public static Config loadDefault(FilterConfig filterConfig)
- throws IOException, ConfigInvalidException {
+ public static File defaultFile(FilterConfig filterConfig) {
String configPath = null;
if (filterConfig != null) {
configPath = filterConfig.getInitParameter(FILTER_CONFIG_PARAM);
@@ -42,7 +41,16 @@
if (configPath == null) {
configPath = System.getProperty(PROPERTY_NAME, DEFAULT_PATH);
}
- FileBasedConfig config = new FileBasedConfig(new File(configPath), FS.DETECTED);
+ return new File(configPath);
+ }
+
+ public static Config loadDefault() throws IOException, ConfigInvalidException {
+ return loadDefault(null);
+ }
+
+ public static Config loadDefault(FilterConfig filterConfig)
+ throws IOException, ConfigInvalidException {
+ FileBasedConfig config = new FileBasedConfig(defaultFile(), FS.DETECTED);
config.load();
return config;
}
diff --git a/gitiles-servlet/src/main/java/com/google/gitiles/GitilesFilter.java b/gitiles-servlet/src/main/java/com/google/gitiles/GitilesFilter.java
index 99a2c4e..b926666 100644
--- a/gitiles-servlet/src/main/java/com/google/gitiles/GitilesFilter.java
+++ b/gitiles-servlet/src/main/java/com/google/gitiles/GitilesFilter.java
@@ -20,7 +20,6 @@
import static com.google.gitiles.ViewFilter.getRegexGroup;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Joiner;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.LinkedListMultimap;
@@ -154,6 +153,7 @@
private final ListMultimap<GitilesView.Type, Filter> filters = LinkedListMultimap.create();
private final Map<GitilesView.Type, HttpServlet> servlets = Maps.newHashMap();
+ private Config config;
private Renderer renderer;
private GitilesUrls urls;
private Linkifier linkifier;
@@ -166,17 +166,20 @@
}
GitilesFilter(
+ Config config,
Renderer renderer,
GitilesUrls urls,
GitilesAccess.Factory accessFactory,
final RepositoryResolver<HttpServletRequest> resolver,
VisibilityCache visibilityCache) {
- this.renderer = checkNotNull(renderer, "renderer");
- this.urls = checkNotNull(urls, "urls");
- this.accessFactory = checkNotNull(accessFactory, "accessFactory");
- this.visibilityCache = checkNotNull(visibilityCache, "visibilityCache");
- this.linkifier = new Linkifier(urls);
- this.resolver = wrapResolver(resolver);
+ this.config = checkNotNull(config, "config");
+ this.renderer = renderer;
+ this.urls = urls;
+ this.accessFactory = accessFactory;
+ this.visibilityCache = visibilityCache;
+ if (resolver != null) {
+ this.resolver = wrapResolver(resolver);
+ }
}
@Override
@@ -219,18 +222,23 @@
case REPOSITORY_INDEX:
return new RepositoryIndexServlet(renderer, accessFactory);
case REVISION:
- return new RevisionServlet(renderer, linkifier);
+ return new RevisionServlet(renderer, linkifier());
case PATH:
return new PathServlet(renderer);
case DIFF:
- return new DiffServlet(renderer, linkifier);
+ return new DiffServlet(renderer, linkifier());
case LOG:
- return new LogServlet(renderer, linkifier);
+ return new LogServlet(renderer, linkifier());
default:
throw new IllegalArgumentException("Invalid view type: " + view);
}
}
+ public synchronized void setRenderer(Renderer renderer) {
+ checkNotInitialized();
+ this.renderer = checkNotNull(renderer, "renderer");
+ }
+
synchronized void addFilter(GitilesView.Type view, Filter filter) {
checkNotInitialized();
filters.put(checkNotNull(view, "view"), checkNotNull(filter, "filter for %s", view));
@@ -259,47 +267,48 @@
};
}
+ private synchronized Linkifier linkifier() {
+ if (linkifier == null) {
+ checkState(urls != null, "GitilesUrls not yet set");
+ linkifier = new Linkifier(urls);
+ }
+ return linkifier;
+ }
+
private void setDefaultFields(FilterConfig filterConfig) throws ServletException {
if (renderer != null && urls != null && accessFactory != null && resolver != null
&& visibilityCache != null) {
return;
}
Config config;
- try {
- config = GitilesConfig.loadDefault(filterConfig);
- } catch (IOException e) {
- throw new ServletException(e);
- } catch (ConfigInvalidException e) {
- throw new ServletException(e);
+ if (this.config != null) {
+ config = this.config;
+ } else {
+ try {
+ config = GitilesConfig.loadDefault(filterConfig);
+ } catch (IOException e) {
+ throw new ServletException(e);
+ } catch (ConfigInvalidException e) {
+ throw new ServletException(e);
+ }
}
if (renderer == null) {
- String staticPrefix = filterConfig.getServletContext().getContextPath() + STATIC_PREFIX;
- String customTemplates = config.getString("gitiles", null, "customTemplates");
- String siteTitle = Objects.firstNonNull(config.getString("gitiles", null, "siteTitle"),
- "Gitiles");
- // TODO(dborowitz): Automatically set to true when run with mvn jetty:run.
- if (config.getBoolean("gitiles", null, "reloadTemplates", false)) {
- renderer = new DebugRenderer(staticPrefix, customTemplates,
- Joiner.on(File.separatorChar).join(System.getProperty("user.dir"),
- "gitiles-servlet", "src", "main", "resources",
- "com", "google", "gitiles", "templates"), siteTitle);
- } else {
- renderer = new DefaultRenderer(staticPrefix, Renderer.toFileURL(customTemplates),
- siteTitle);
- }
+ renderer = new DefaultRenderer(
+ filterConfig.getServletContext().getContextPath() + STATIC_PREFIX,
+ Renderer.toFileURL(config.getString("gitiles", null, "customTemplates")),
+ Objects.firstNonNull(config.getString("gitiles", null, "siteTitle"), "Gitiles"));
}
if (urls == null) {
try {
urls = new DefaultUrls(
config.getString("gitiles", null, "canonicalHostName"),
getBaseGitUrl(config),
- getGerritUrl(config));
+ config.getString("gitiles", null, "gerritUrl"));
} catch (UnknownHostException e) {
throw new ServletException(e);
}
}
- linkifier = new Linkifier(urls);
if (accessFactory == null || resolver == null) {
String basePath = config.getString("gitiles", null, "basePath");
if (basePath == null) {
@@ -345,12 +354,4 @@
}
return baseGitUrl;
}
-
- private static String getGerritUrl(Config config) throws ServletException {
- String gerritUrl = config.getString("gitiles", null, "gerritUrl");
- if (gerritUrl == null) {
- throw new ServletException("gitiles.gerritUrl not set");
- }
- return gerritUrl;
- }
}
diff --git a/gitiles-servlet/src/main/java/com/google/gitiles/GitilesServlet.java b/gitiles-servlet/src/main/java/com/google/gitiles/GitilesServlet.java
index c1647ba..be03293 100644
--- a/gitiles-servlet/src/main/java/com/google/gitiles/GitilesServlet.java
+++ b/gitiles-servlet/src/main/java/com/google/gitiles/GitilesServlet.java
@@ -15,10 +15,12 @@
package com.google.gitiles;
import org.eclipse.jgit.http.server.glue.MetaServlet;
+import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.transport.resolver.RepositoryResolver;
import java.util.Enumeration;
+import javax.annotation.Nullable;
import javax.servlet.Filter;
import javax.servlet.FilterConfig;
import javax.servlet.ServletConfig;
@@ -42,12 +44,14 @@
/** The prefix from which static resources are served. */
public static final String STATIC_PREFIX = "/+static/";
- public GitilesServlet(Renderer renderer,
- GitilesUrls urls,
- GitilesAccess.Factory accessFactory,
- RepositoryResolver<HttpServletRequest> resolver,
- VisibilityCache visibilityCache) {
- super(new GitilesFilter(renderer, urls, accessFactory, resolver, visibilityCache));
+ public GitilesServlet(
+ @Nullable Config config,
+ @Nullable Renderer renderer,
+ @Nullable GitilesUrls urls,
+ @Nullable GitilesAccess.Factory accessFactory,
+ @Nullable RepositoryResolver<HttpServletRequest> resolver,
+ @Nullable VisibilityCache visibilityCache) {
+ super(new GitilesFilter(config, renderer, urls, accessFactory, resolver, visibilityCache));
}
public GitilesServlet() {