Convert build to buck

Build a plugin jar linked that depends on this plugin being
cloned/linked into the Gerrit tree so it has access to Gerrit's buck
defs.

Build an output jar including resources in /+static. The
Gerrit-HttpStaticPrefix has to match the actual location in the jar of
the resources. Unlike the Gitiles dev server, which actually maps
/+static to an arbitrary resource path, we need to copy these to the
root of the jar.

Encoded URIs would also be passed through untouched to Gitiles,
which would cause errors finding repositories or performing diffs.
By decoding the URI in a filter and HttpRequestWrapper, we can
instead provide the decoded URI to Gitiles.

Change-Id: I9974756cb6fdcf6efdf2effd62016431ea2d49c1
diff --git a/BUCK b/BUCK
new file mode 100644
index 0000000..41dc7a7
--- /dev/null
+++ b/BUCK
@@ -0,0 +1,89 @@
+include_defs('//lib/maven.defs')
+
+genrule(
+  name = 'gitiles',
+  cmd = ' && '.join([
+    'cp $(location :gitiles_base) $OUT',
+    'unzip -qd $TMP $(location :gitiles-servlet) "com/google/gitiles/static/*"',
+    'cd $TMP/com/google/gitiles',
+    'mv static +static',
+    'zip -Drq $OUT -g . -i "+static/*"',
+  ]),
+  out = 'gitiles.jar',
+  deps = [
+    ':gitiles-servlet',
+    ':gitiles_base',
+  ],
+)
+
+gerrit_plugin(
+  name = 'gitiles_base',
+  srcs = glob(['src/main/java/**/*.java']),
+  deps = [
+    ':gitiles-servlet',
+
+    # Deps only needed by Gitiles.
+    ':guice-multibindings',
+    ':soy',
+    ':commons-lang3',
+  ],
+  # Deps shared with Gerrit but not in the plugin API.
+  compile_deps = [
+    '//lib/jgit:jgit-servlet',
+  ],
+  resources = glob(['src/main/resources/**/*']),
+  manifest_entries = [
+    'Gerrit-PluginName: gitiles',
+    'Gerrit-Module: com.googlesource.gerrit.plugins.gitiles.Module',
+    'Gerrit-HttpModule: com.googlesource.gerrit.plugins.gitiles.HttpModule',
+    'Gerrit-InitStep: com.googlesource.gerrit.plugins.gitiles.InitGitiles',
+
+    # Gitiles uses /repo to access a repo, so the default plugin layout would
+    # disallow repos named "static" or "Documentation". Paths starting with +
+    # are reserved by Gitiles and can't match repos.
+    'Gerrit-HttpStaticPrefix: +static',
+    'Gerrit-HttpDocumentationPrefix: +Documentation',
+  ],
+  visibility = [],
+)
+
+maven_jar(
+  name = 'gitiles-servlet',
+  id = 'com.google.gitiles:gitiles-servlet:0.1-2',
+  sha1 = '31c84c6fdcde30174c70e4f1f5a5a8d71c57a19e',
+  license = 'Apache2.0',
+  repository = GERRIT,
+  visibility = [],
+)
+
+maven_jar(
+  name = 'commons-lang3',
+  id = 'org.apache.commons:commons-lang3:3.1',
+  sha1 = '905075e6c80f206bbe6cf1e809d2caa69f420c76',
+  license = 'Apache2.0',
+  visibility = [],
+)
+
+maven_jar(
+  name = 'soy',
+  id = 'com.google.template:soy:2012-12-21',
+  sha1 = 'cc28da103845a0f08cfd3fa5abdd45899b0adae1',
+  license = 'Apache2.0',
+  visibility = [],
+)
+
+maven_jar(
+  name = 'guice-multibindings',
+  id = 'com.google.inject.extensions:guice-multibindings:4.0-beta',
+  sha1 = '558a3dcfd203db33a5a96a70a18076c866723ee4',
+  license = 'Apache2.0',
+  exclude_java_sources = True,
+  exclude = [
+    'META-INF/DEPENDENCIES',
+    'META-INF/LICENSE',
+    'META-INF/NOTICE',
+    'META-INF/maven/com.google.guava/guava/pom.properties',
+    'META-INF/maven/com.google.guava/guava/pom.xml',
+  ],
+  visibility = [],
+)
diff --git a/pom.xml b/pom.xml
deleted file mode 100644
index dd31e43..0000000
--- a/pom.xml
+++ /dev/null
@@ -1,172 +0,0 @@
-<!--
-Copyright (C) 2013 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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-
-  <groupId>com.googlesource.gerrit.plugins.gitiles</groupId>
-  <artifactId>gitiles</artifactId>
-  <packaging>jar</packaging>
-  <version>1.0-SNAPSHOT</version>
-  <name>gitiles</name>
-
-  <properties>
-    <Gerrit-ApiType>plugin</Gerrit-ApiType>
-    <Gerrit-ApiVersion>2.10-SNAPSHOT</Gerrit-ApiVersion>
-
-    <gitilesVersion>0.1-2</gitilesVersion>
-  </properties>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-jar-plugin</artifactId>
-        <version>2.4</version>
-        <configuration>
-          <archive>
-            <manifestEntries>
-            </manifestEntries>
-          </archive>
-        </configuration>
-      </plugin>
-
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-compiler-plugin</artifactId>
-        <version>2.3.2</version>
-        <configuration>
-          <source>1.6</source>
-          <target>1.6</target>
-          <encoding>UTF-8</encoding>
-        </configuration>
-      </plugin>
-
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-shade-plugin</artifactId>
-        <version>1.6</version>
-        <configuration>
-          <promoteTransitiveDependencies>true</promoteTransitiveDependencies>
-          <artifactSet>
-            <excludes>
-              <!-- Common Gitiles/Gerrit/Soy transitive dependencies. -->
-              <exclude>aopalliance:aopalliance</exclude>
-              <exclude>args4j:args4j</exclude>
-              <exclude>com.google.code.findbugs:jsr305</exclude>
-              <exclude>com.google.code.gson:gson</exclude>
-              <exclude>com.google.guava:guava</exclude>
-              <exclude>com.google.inject.extensions:guice-assistedinject</exclude>
-              <exclude>com.google.inject:guice</exclude>
-              <exclude>com.google.inject:guice-multibindings:3.0</exclude>
-              <exclude>com.googlecode.javaewah</exclude>
-              <exclude>com.jcraft:jsch</exclude>
-              <exclude>javax.inject:javax.inject</exclude>
-              <exclude>org.eclipse.jgit:org.eclipse.jgit.http.server</exclude>
-              <exclude>org.eclipse.jgit:org.eclipse.jgit</exclude>
-              <exclude>org.slf4j:slf4j-api</exclude>
-            </excludes>
-          </artifactSet>
-          <transformers>
-            <transformer
-              implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
-              <manifestEntries>
-                <Gerrit-Module>com.googlesource.gerrit.plugins.gitiles.Module</Gerrit-Module>
-                <Gerrit-HttpModule>com.googlesource.gerrit.plugins.gitiles.HttpModule</Gerrit-HttpModule>
-                <Gerrit-InitStep>com.googlesource.gerrit.plugins.gitiles.InitGitiles</Gerrit-InitStep>
-
-                <!-- Gitiles uses /repo to access a repo, so the default plugin layout would
-                     disallow repos named "static" or "Documentation". Paths starting with + are
-                     reserved by Gitiles and can't match repos. -->
-                <Gerrit-HttpStaticPrefix>+static</Gerrit-HttpStaticPrefix>>
-                <Gerrit-HttpDocumentationPrefix>+Documentation</Gerrit-HttpDocumentationPrefix>>
-
-                <Implementation-Vendor>Gerrit Code Review</Implementation-Vendor>
-                <Implementation-URL>http://code.google.com/p/gerrit/</Implementation-URL>
-                <Implementation-Title>${Gerrit-ApiType} ${project.artifactId}</Implementation-Title>
-                <Implementation-Version>${project.version}</Implementation-Version>
-                <Gerrit-ApiType>${Gerrit-ApiType}</Gerrit-ApiType>
-                <Gerrit-ApiVersion>${Gerrit-ApiVersion}</Gerrit-ApiVersion>
-              </manifestEntries>
-            </transformer>
-          </transformers>
-          <filters>
-            <filter>
-              <artifact>*:*</artifact>
-              <excludes>
-                <exclude>META-INF/*.SF</exclude>
-                <exclude>META-INF/*.DSA</exclude>
-                <exclude>META-INF/*.RSA</exclude>
-              </excludes>
-            </filter>
-          </filters>
-          <relocations>
-            <relocation>
-              <pattern>com.google.gitiles.static</pattern>
-              <shadedPattern>+static</shadedPattern>
-            </relocation>
-          </relocations>
-
-        </configuration>
-        <executions>
-          <execution>
-            <phase>package</phase>
-            <goals>
-              <goal>shade</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
-
-  <dependencies>
-    <dependency>
-      <groupId>com.google.gerrit</groupId>
-      <artifactId>gerrit-${Gerrit-ApiType}-api</artifactId>
-      <version>${Gerrit-ApiVersion}</version>
-      <scope>provided</scope>
-    </dependency>
-
-    <dependency>
-      <groupId>com.google.gitiles</groupId>
-      <artifactId>gitiles-servlet</artifactId>
-      <version>${gitilesVersion}</version>
-      <scope>compile</scope>
-    </dependency>
-
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>4.11</version>
-      <scope>test</scope>
-    </dependency>
-
-    <dependency>
-      <groupId>com.google.inject.extensions</groupId>
-      <artifactId>guice-multibindings</artifactId>
-      <version>4.0-beta</version>
-    </dependency>
-  </dependencies>
-
-  <repositories>
-    <repository>
-      <id>gerrit-api-repository</id>
-      <url>https://gerrit-api.commondatastorage.googleapis.com/snapshot/</url>
-    </repository>
-  </repositories>
-</project>
diff --git a/src/main/java/com/googlesource/gerrit/plugins/gitiles/HttpModule.java b/src/main/java/com/googlesource/gerrit/plugins/gitiles/HttpModule.java
index a5d7023..9913999 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/gitiles/HttpModule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/gitiles/HttpModule.java
@@ -34,16 +34,56 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
 
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
 import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
 
 class HttpModule extends ServletModule {
+  protected Filter createPathFilter() {
+    return new Filter() {
+      @Override
+      public void doFilter(ServletRequest request, ServletResponse response,
+          FilterChain chain) throws IOException, ServletException {
+        HttpServletRequestWrapper wrappedRequest =
+            new HttpServletRequestWrapper((HttpServletRequest) request) {
+              @Override
+              public String getRequestURI() {
+                try {
+                  // Note: URLDecoder.decode() will decode "+" to a space.
+                  // This doesn't work, so use URI.getPath() instead.
+                  URI uri = new URI(super.getRequestURI());
+                  return uri.getPath();
+                } catch (URISyntaxException e) {
+                  return super.getRequestURI();
+                }
+              }
+            };
+        chain.doFilter(wrappedRequest, response);
+      }
+
+      @Override
+      public void destroy() {}
+
+      @Override
+      public void init(FilterConfig config) throws ServletException {}
+    };
+  }
+
   private static final Logger log = LoggerFactory
       .getLogger(ServletModule.class);
 
   @Override
   protected void configureServlets() {
+    // Filter all paths so we can decode escaped entities in the URI
+    filter("/*").through(createPathFilter());
     // Let /+static, /+Documentation, etc. fall through to default servlet, but
     // handle everything else.
     serveRegex("^(/)$", "^(/[^+].*)").with(GitilesServlet.class);