Make symbolMaps for StackTraceDeobfuscator lookup more robust

Users can specify the symbolMaps location for the RequestFactoryServlet
by adding an init-param  symbolMapsDirectory to the web.xml. However
the RequestFactoryServlet only passes the user specified directory to
the Logging class. This does not work in WAR deployment scenarios.
To solve this, the RequestFactoryServlet will check if a
symbolMapsResourcePath init parameter is defined and pass it to
ServletContext#getResource to retrieve the correct URL to the
symbolMaps directory.

Bug: #6363
Bug-Link: https://github.com/gwtproject/gwt/issues/6363
Change-Id: I916b687ab59b703f8aee85bd7ea1e96f828c0186
diff --git a/user/src/com/google/web/bindery/requestfactory/server/Logging.java b/user/src/com/google/web/bindery/requestfactory/server/Logging.java
index faf7fdc..c2aea95 100644
--- a/user/src/com/google/web/bindery/requestfactory/server/Logging.java
+++ b/user/src/com/google/web/bindery/requestfactory/server/Logging.java
@@ -63,6 +63,16 @@
     deobfuscator = StackTraceDeobfuscator.fromFileSystem(dir);
   }
 
+  /**
+   * This function is only for server-side use which is why it's not in the
+   * LoggingRequest interface.
+   *
+   * @param stackTraceDeobfuscator the StackTraceDeobfuscator instance to use
+   */
+  public static void setStackTraceDeobfuscator(StackTraceDeobfuscator stackTraceDeobfuscator) {
+    deobfuscator =  stackTraceDeobfuscator;
+  }
+
   private String id = "";
 
   private Integer version = 0;
diff --git a/user/src/com/google/web/bindery/requestfactory/server/RequestFactoryServlet.java b/user/src/com/google/web/bindery/requestfactory/server/RequestFactoryServlet.java
index 15ad741..9d87acb 100644
--- a/user/src/com/google/web/bindery/requestfactory/server/RequestFactoryServlet.java
+++ b/user/src/com/google/web/bindery/requestfactory/server/RequestFactoryServlet.java
@@ -15,11 +15,13 @@
  */
 package com.google.web.bindery.requestfactory.server;
 
+import com.google.gwt.core.server.StackTraceDeobfuscator;
 import com.google.gwt.user.server.rpc.RPCServletUtils;
 import com.google.web.bindery.requestfactory.shared.RequestFactory;
 
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.net.MalformedURLException;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -153,7 +155,15 @@
 
   private void ensureConfig() {
     String symbolMapsDirectory = getServletConfig().getInitParameter("symbolMapsDirectory");
-    if (symbolMapsDirectory != null) {
+    String symbolMapsResourcePath = getServletConfig().getInitParameter("symbolMapsResourcePath");
+    if (symbolMapsResourcePath != null) {
+      try {
+        Logging.setStackTraceDeobfuscator(
+            StackTraceDeobfuscator.fromUrl(getServletContext().getResource(symbolMapsResourcePath)));
+      } catch (MalformedURLException e) {
+        log.log(Level.WARNING, "Failed to get the symbolMaps resource", e);
+      }
+    } else if (symbolMapsDirectory != null) {
       Logging.setSymbolMapsDirectory(symbolMapsDirectory);
     }
   }