Include formatted HTML documentation in WAR

This way the documentation for that release is embedded within the
WAR and can be served directly from the servlet container that is
running Gerrit Code Review itself.  This should make it easier to
look up the relevant information from a running installation.

The documentation menu is only installed in the UI if the server
has the "Documentation/" subdirectory within the servlet context.
This should be true if the server was packaged with our release
script, but otherwise would be false as its not there.

Its probably more GWT-ey to use some sort of build parameter in
the module definition to enable or disable this menu creation
code at compile time, allowing GWT to strip out the resources and
JavaScript if the documentation wasn't available at build time.
But this is far too complex for our needs.  The documentation is
most likely going to be present, and its only a handful of bytes
for the strings.  Any minor savings resulting from being able to
strip this code out just isn't worth the additional code complexity.

Change-Id: Ib2be63cf99fa20ff427ab811ab25d5e9e8a6b21f
Signed-off-by: Shawn O. Pearce <sop@google.com>
diff --git a/Documentation/dev-readme.txt b/Documentation/dev-readme.txt
index 3584c12..2ae9fac 100644
--- a/Documentation/dev-readme.txt
+++ b/Documentation/dev-readme.txt
@@ -132,6 +132,14 @@
   ./tools/release.sh
 ----
 
+If AsciiDoc isn't installed or is otherwise unavailable, the WAR
+can still be built without the embedded documentation by passing
+an additional flag:
+
+----
+  ./tools/release.sh --without-documentation
+----
+
 
 Client-Server RPC
 -----------------
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/GerritConfig.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/GerritConfig.java
index 5cf2d05..5ff666d 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/GerritConfig.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/GerritConfig.java
@@ -36,6 +36,7 @@
   protected ApprovalTypes approvalTypes;
   protected Set<Account.FieldName> editableAccountFields;
   protected List<RegexFindReplace> commentLinks;
+  protected boolean documentationAvailable;
 
   public String getRegisterUrl() {
     return registerUrl;
@@ -139,4 +140,12 @@
   public void setCommentLinks(final List<RegexFindReplace> cl) {
     commentLinks = cl;
   }
+
+  public boolean isDocumentationAvailable() {
+    return documentationAvailable;
+  }
+
+  public void setDocumentationAvailable(final boolean available) {
+    documentationAvailable = available;
+  }
 }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
index d8bf4b5..a4035d5 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
@@ -418,6 +418,14 @@
       menuLeft.add(m, C.menuAdmin());
     }
 
+    if (getConfig().isDocumentationAvailable()) {
+      m = new LinkMenuBar();
+      addDocLink(m, C.menuDocumentationIndex(), "index.html");
+      addDocLink(m, C.menuDocumentationUpload(), "user-upload.html");
+      addDocLink(m, C.menuDocumentationAccess(), "access-control.html");
+      menuLeft.add(m, C.menuDocumentation());
+    }
+
     if (signedIn) {
       whoAmI();
       addLink(menuRight, C.menuSettings(), PageLinks.SETTINGS);
@@ -490,4 +498,11 @@
       final String historyToken) {
     m.addItem(new LinkMenuItem(text, historyToken));
   }
+
+  private static void addDocLink(final LinkMenuBar m, final String text,
+      final String href) {
+    final Anchor atag = anchor(text, "Documentation/" + href);
+    atag.setTarget("_blank");
+    m.add(atag);
+  }
 }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java
index b6bbbc7..b4ffe34 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java
@@ -55,6 +55,11 @@
   String menuGroups();
   String menuProjects();
 
+  String menuDocumentation();
+  String menuDocumentationIndex();
+  String menuDocumentationUpload();
+  String menuDocumentationAccess();
+
   String searchHint();
   String searchButton();
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties
index 6c26a58..7bdeac0 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties
@@ -38,6 +38,11 @@
 menuGroups = Groups
 menuProjects = Projects
 
+menuDocumentation = Documentation
+menuDocumentationIndex = Index
+menuDocumentationUpload = Uploading Changes
+menuDocumentationAccess = Access Controls
+
 searchHint = Change #, SHA-1, owner:email or reviewer:email
 searchButton = Search
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java
index a4b1a21..fff39525 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java
@@ -33,6 +33,7 @@
 
 import org.eclipse.jgit.lib.Config;
 
+import java.net.MalformedURLException;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -40,6 +41,8 @@
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
 
+import javax.servlet.ServletContext;
+
 class GerritConfigProvider implements Provider<GerritConfig> {
   private final Realm realm;
   private final Config cfg;
@@ -51,12 +54,13 @@
 
   private EmailSender emailSender;
   private final ContactStore contactStore;
+  private final ServletContext servletContext;
 
   @Inject
   GerritConfigProvider(final Realm r, @GerritServerConfig final Config gsc,
       final AuthConfig ac, final GitWebConfig gwc,
       @WildProjectName final Project.NameKey wp, final SshInfo si,
-      final ApprovalTypes at, final ContactStore cs) {
+      final ApprovalTypes at, final ContactStore cs, final ServletContext sc) {
     realm = r;
     cfg = gsc;
     authConfig = ac;
@@ -65,6 +69,7 @@
     wildProject = wp;
     approvalTypes = at;
     contactStore = cs;
+    servletContext = sc;
   }
 
   @Inject(optional = true)
@@ -72,7 +77,7 @@
     emailSender = d;
   }
 
-  private GerritConfig create() {
+  private GerritConfig create() throws MalformedURLException {
     final GerritConfig config = new GerritConfig();
     switch (authConfig.getAuthType()) {
       case LDAP:
@@ -89,6 +94,8 @@
     config.setAuthType(authConfig.getAuthType());
     config.setWildProject(wildProject);
     config.setApprovalTypes(approvalTypes);
+    config.setDocumentationAvailable(servletContext
+        .getResource("/Documentation/index.html") != null);
 
     final Set<Account.FieldName> fields = new HashSet<Account.FieldName>();
     for (final Account.FieldName n : Account.FieldName.values()) {
@@ -140,6 +147,10 @@
 
   @Override
   public GerritConfig get() {
-    return create();
+    try {
+      return create();
+    } catch (MalformedURLException e) {
+      throw new ProvisionException("Cannot create GerritConfig instance", e);
+    }
   }
 }
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebModule.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebModule.java
index cd1a516..17a7ba5 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebModule.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebModule.java
@@ -133,8 +133,8 @@
 
     bind(ContactStore.class).toProvider(ContactStoreProvider.class).in(
         SINGLETON);
-    bind(GerritConfig.class).toProvider(GerritConfigProvider.class).in(
-        SINGLETON);
+    bind(GerritConfigProvider.class);
+    bind(GerritConfig.class).toProvider(GerritConfigProvider.class);
 
     bind(AccountManager.class);
     bind(ChangeUserName.CurrentUser.class);
diff --git a/gerrit-war/pom.xml b/gerrit-war/pom.xml
index f83d0a8..d970c42 100644
--- a/gerrit-war/pom.xml
+++ b/gerrit-war/pom.xml
@@ -99,6 +99,54 @@
     </dependency>
   </dependencies>
 
+  <profiles>
+    <profile>
+      <id>include-documentation-profile</id>
+      <activation>
+        <property>
+          <name>gerrit.include-documentation</name>
+        </property>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-antrun-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>include-documentation</id>
+                <phase>process-classes</phase>
+                <configuration>
+                  <tasks>
+                    <property name="src" location="${basedir}/../Documentation" />
+                    <property name="out" location="${project.build.directory}/${project.build.finalName}" />
+                    <property name="dst" location="${out}/Documentation" />
+
+                    <exec dir="${src}" executable="make">
+                      <arg value="VERSION=${project.version}" />
+                      <arg value="clean" />
+                      <arg value="all" />
+                    </exec>
+
+                    <mkdir dir="${dst}" />
+                    <copy overwrite="true" todir="${dst}">
+                      <fileset dir="${src}">
+                        <include name="*.html" />
+                      </fileset>
+                    </copy>
+                  </tasks>
+                </configuration>
+                <goals>
+                  <goal>run</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+
   <build>
     <plugins>
       <plugin>
@@ -138,11 +186,11 @@
             <phase>process-classes</phase>
             <configuration>
               <tasks>
+                <property name="src" location="${basedir}/../Documentation" />
                 <property name="dst" location="${project.build.directory}/${project.build.finalName}" />
-                <property name="app" location="${dst}/gerrit" />
 
                 <copy tofile="${dst}/LICENSES.txt"
-                      file="${basedir}/../Documentation/licenses.txt"
+                      file="${src}/licenses.txt"
                       overwrite="true" />
               </tasks>
             </configuration>
diff --git a/tools/release.sh b/tools/release.sh
index 14d7fc8..4a872a1 100755
--- a/tools/release.sh
+++ b/tools/release.sh
@@ -1,5 +1,20 @@
 #!/bin/sh
 
+include_docs=-Dgerrit.include-documentation=1
+
+while [ $# -gt 0 ]
+do
+	case "$1" in
+	--no-documentation|--without-documentation)
+		include_docs=
+		shift
+		;;
+	*)
+		echo >&2 "usage: $0 [--without-documentation]"
+		exit 1
+	esac
+done
+
 git update-index -q --refresh
 
 if test -n "$(git diff-index --name-only HEAD --)" \
@@ -10,7 +25,7 @@
 fi
 
 ./tools/version.sh --release &&
-mvn clean package
+mvn clean package $include_docs
 rc=$?
 ./tools/version.sh --reset