Goktug Gokdogan has uploaded a new change for review.

  https://gwt-review.googlesource.com/3512


Change subject: Move StackTraceDeobfuscator from core.server.impl to core.server.
......................................................................

Move StackTraceDeobfuscator from core.server.impl to core.server.

This patch moves StackTraceDeobfuscator to core.server as the API is finalized.

Change-Id: Ic84f3b2210e3c40f0f7dc41bdeea9d13bf1a4dc6
---
D user/src/com/google/gwt/core/server/impl/StackTraceDeobfuscator.java
M user/src/com/google/gwt/junit/server/JUnitHostImpl.java
M user/src/com/google/gwt/logging/server/RemoteLoggingServiceImpl.java
M user/src/com/google/gwt/logging/server/RemoteLoggingServiceUtil.java
M user/src/com/google/gwt/logging/server/StackTraceDeobfuscator.java
M user/src/com/google/web/bindery/requestfactory/server/Logging.java
M user/test/com/google/gwt/user/server/rpc/LoggingRPCTestServiceImpl.java
7 files changed, 6 insertions(+), 442 deletions(-)



diff --git a/user/src/com/google/gwt/core/server/impl/StackTraceDeobfuscator.java b/user/src/com/google/gwt/core/server/impl/StackTraceDeobfuscator.java
deleted file mode 100644
index 2d62b5c..0000000
--- a/user/src/com/google/gwt/core/server/impl/StackTraceDeobfuscator.java
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- *
- * 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.
- */
-package com.google.gwt.core.server.impl;
-
-import com.google.gwt.thirdparty.debugging.sourcemap.SourceMapConsumerFactory;
-import com.google.gwt.thirdparty.debugging.sourcemap.SourceMapping;
-import com.google.gwt.thirdparty.debugging.sourcemap.proto.Mapping;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Scanner;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Deobfuscates stack traces on the server side. This class requires that you have turned on - * emulated stack traces, via <code>&lt;set-property name="compiler.stackMode" value="emulated" - * /&gt;</code> in your <code>.gwt.xml</code> module file for browsers that don't support - * sourcemaps or <code>&lt;set-property name="compiler.useSourceMaps" value="true"/&gt;</code> for - * browsers that support it (e.g. Chrome), and moved your symbol map files to a location accessible - * by your server-side code. You can use the GWT compiler <code>-deploy</code> command line - * argument to specify the location of the folder into which the generated <code>symbolMaps</code> - * directory is written. By default, the final <code>symbolMaps</code> directory is
- * <code>war/WEB-INF/deploy/<i>yourmodulename</i>/symbolMaps/</code>.
- */
-public abstract class StackTraceDeobfuscator {
-
-  /**
- * Creates a deobfuscator that loads symbol and source map files under given resource path. Uses
-   * StackTraceObfuscator's {@link ClassLoader}.
-   */
- public static StackTraceDeobfuscator fromResource(String symbolMapsPath) { - final String basePath = symbolMapsPath.endsWith("/") ? symbolMapsPath : symbolMapsPath + "/"; - final ClassLoader classLoader = StackTraceDeobfuscator.class.getClassLoader();
-    return new StackTraceDeobfuscator() {
- protected InputStream openInputStream(String fileName) throws IOException {
-        String filePath = basePath + fileName;
- InputStream inputStream = classLoader.getResourceAsStream(filePath);
-        if (inputStream == null) {
-          throw new IOException("Missing resource: " + filePath);
-        }
-        return inputStream;
-      }
-    };
-  }
-
-  /**
- * Creates a deobfuscator that loads symbol and source map files from the given directory.
-   */
- public static StackTraceDeobfuscator fromFileSystem(final String symbolMapsDirectory) {
-    return new StackTraceDeobfuscator() {
- protected InputStream openInputStream(String fileName) throws IOException { - return new FileInputStream(new File(symbolMapsDirectory, fileName));
-      }
-    };
-  }
-
-  /**
- * Creates a deobfuscator that loads symbol and source map files beneath the given URL.
-   */
-  public static StackTraceDeobfuscator fromUrl(final URL urlPath) {
-    return new StackTraceDeobfuscator() {
- protected InputStream openInputStream(String fileName) throws IOException {
-        return new URL(urlPath, fileName).openStream();
-      }
-    };
-  }
-
-  /**
- * A cache that maps obfuscated symbols to arbitrary non-null string values. The cache can assume - * each (strongName, symbol) pair always maps to the same value (never goes invalid), but must
-   * treat data as an opaque string.
-   */
-  private static class SymbolCache {
- // TODO(srogoff): This SymbolCache implementation never drops old entries. If clients ever need - // to cap memory usage even with lazy loading, consider making SymbolCache an interface. - // This could allow clients to pass their own implementation to the StackTraceDeobfuscator - // constructor, backed by a Guava Cache or other entry-evicting mapping.
-
- private final ConcurrentHashMap<String, HashMap<String, String>> symbolMaps;
-
-    SymbolCache() {
- symbolMaps = new ConcurrentHashMap<String, HashMap<String, String>>();
-    }
-
-    /**
-     * Adds some symbol data to the cache for the given strong name.
-     */
-    void putAll(String strongName, Map<String, String> symbolMap) {
-      if (strongName == null || symbolMap.size() == 0) {
-        return;
-      }
-      symbolMaps.putIfAbsent(strongName, new HashMap<String, String>());
-      HashMap<String, String> existingMap = symbolMaps.get(strongName);
-      synchronized (existingMap) {
-        existingMap.putAll(symbolMap);
-      }
-    }
-
-    /**
- * Returns the data for each of the specified symbols that's currently cached for the given - * strong name. There will be no entry for symbols that are not in the cache. If none of the
-     * symbols are cached, an empty Map is returned.
-     */
-    Map<String, String> getAll(String strongName, Set<String> symbols) {
-      Map<String, String> toReturn = new HashMap<String, String>();
- if (strongName == null || !symbolMaps.containsKey(strongName) || symbols.isEmpty()) {
-        return toReturn;
-      }
-      HashMap<String, String> existingMap = symbolMaps.get(strongName);
-      synchronized (existingMap) {
-        for (String symbol : symbols) {
-          if (existingMap.containsKey(symbol)) {
-            toReturn.put(symbol, existingMap.get(symbol));
-          }
-        }
-      }
-      return toReturn;
-    }
-  }
-
- private static final Pattern JsniRefPattern = Pattern.compile("@?([^:]+)::([^(]+)(\\((.*)\\))?"); - private static final Pattern fragmentIdPattern = Pattern.compile(".*(\\d+)\\.js");
-  private static final int LINE_NUMBER_UNKNOWN = -1;
-  private static final String SYMBOL_DATA_UNKNOWN = "";
-
- private final Map<String, SourceMapping> sourceMaps = new HashMap<String, SourceMapping>();
-  private final SymbolCache symbolCache = new SymbolCache();
-  private boolean lazyLoad = false;
-
-  /**
- * If set to {@code true}, only symbols requested to be deobfuscated are cached and the rest is - * discarded. This provides a large memory savings at the expense of occasional extra disk reads. - * Note that, this will only have effect on symbol maps that haven't been fully loaded yet.
-   */
-  public void setLazyLoad(boolean lazyLoad) {
-    this.lazyLoad = lazyLoad;
-  }
-
-  /**
- * Replaces the stack traces in the given Throwable and its causes with deobfuscated stack traces
-   * wherever possible.
-   *
- * @param throwable the Throwable that needs its stack trace to be deobfuscated
-   * @param strongName the GWT permutation strong name
-   */
- public final void deobfuscateStackTrace(Throwable throwable, String strongName) { - throwable.setStackTrace(resymbolize(throwable.getStackTrace(), strongName));
-    if (throwable.getCause() != null) {
-      deobfuscateStackTrace(throwable.getCause(), strongName);
-    }
-  }
-
-  /**
- * Convenience method which resymbolizes an entire stack trace to extent possible.
-   *
-   * @param st the stack trace to resymbolize
-   * @param strongName the GWT permutation strong name
-   * @return a best effort resymbolized stack trace
-   */
- public final StackTraceElement[] resymbolize(StackTraceElement[] st, String strongName) {
-    if (st == null) {
-      return null;
-    }
-    // Warm the symbol cache for all symbols in this stack trace.
-    Set<String> requiredSymbols = new HashSet<String>();
-    for (StackTraceElement ste : st) {
-      requiredSymbols.add(ste.getMethodName());
-    }
-    loadSymbolMap(strongName, requiredSymbols);
-
-    StackTraceElement[] newSt = new StackTraceElement[st.length];
-    for (int i = 0; i < st.length; i++) {
-      newSt[i] = resymbolize(st[i], strongName);
-    }
-    return newSt;
-  }
-
-  /**
-   * Best effort resymbolization of a single stack trace element.
-   *
-   * @param ste the stack trace element to resymbolize
-   * @param strongName the GWT permutation strong name
-   * @return the best effort resymbolized stack trace element
-   */
- public final StackTraceElement resymbolize(StackTraceElement ste, String strongName) {
-    String declaringClass = null;
-    String methodName = null;
-    String filename = null;
-    int lineNumber = -1;
-    int fragmentId = -1;
-
-    String steFilename = ste.getFileName();
-    String symbolData = loadOneSymbol(strongName, ste.getMethodName());
-
-    boolean sourceMapCapable = false;
-
-    int column = 1;
- // column information is encoded in filename after '@' for sourceMap capable browsers
-    if (steFilename != null) {
-      int columnMarkerIndex = steFilename.indexOf("@");
-      if (columnMarkerIndex != -1) {
-        try {
- column = Integer.parseInt(steFilename.substring(columnMarkerIndex + 1));
-          sourceMapCapable = true;
-        } catch (NumberFormatException nfe) {
-        }
-        steFilename = steFilename.substring(0, columnMarkerIndex);
-      }
-    }
-
-    // first use symbolMap, then refine via sourceMap if possible
-    if (!symbolData.isEmpty()) {
- // jsniIdent, className, memberName, sourceUri, sourceLine, fragmentId
-      String[] parts = symbolData.split(",");
-      if (parts.length == 6) {
-        String[] ref = parse(
-            parts[0].substring(0, parts[0].lastIndexOf(')') + 1));
-
-        if (ref != null) {
-          declaringClass = ref[0];
-          methodName = ref[1];
-        } else {
-          declaringClass = ste.getClassName();
-          methodName = ste.getMethodName();
-        }
-
-        // parts[3] contains the source file URI or "Unknown"
-        filename = "Unknown".equals(parts[3]) ? null
-            : parts[3].substring(parts[3].lastIndexOf('/') + 1);
-
-        lineNumber = ste.getLineNumber();
-
-        /*
-         * When lineNumber is LINE_NUMBER_UNKNOWN, either because
-         * compiler.stackMode is not emulated or
- * compiler.emulatedStack.recordLineNumbers is false, use the method
-         * declaration line number from the symbol map.
-         */
- if (lineNumber == LINE_NUMBER_UNKNOWN || (sourceMapCapable && column == -1)) { - // Safari will send line numbers, with col == -1, we need to use symbolMap in this case
-          lineNumber = Integer.parseInt(parts[4]);
-        }
-
-        fragmentId = Integer.parseInt(parts[5]);
-      }
-    }
-
- // anonymous function, try to use <fragmentNum>.js:line to determine fragment id
-    if (fragmentId == -1 && steFilename != null) {
-      // fragment identifier encoded in filename
-      Matcher matcher = fragmentIdPattern.matcher(steFilename);
-      if (matcher.matches()) {
-        String fragment = matcher.group(1);
-        try {
-          fragmentId = Integer.parseInt(fragment);
-        } catch (Exception e) {
-        }
-      } else if (steFilename.contains(strongName)) {
-        // else it's <strongName>.cache.js which is the 0th fragment
-        fragmentId = 0;
-      }
-    }
-
-    int jsLineNumber = ste.getLineNumber();
-
-    // try to refine location via sourcemap
-    if (sourceMapCapable && fragmentId != -1 && column != -1) {
-      SourceMapping sourceMapping = loadSourceMap(strongName, fragmentId);
-      if (sourceMapping != null && ste.getLineNumber() > -1) {
-        Mapping.OriginalMapping mappingForLine = sourceMapping
-            .getMappingForLine(jsLineNumber, column);
-        if (mappingForLine != null) {
-
- if (declaringClass == null || declaringClass.equals(ste.getClassName())) {
-            declaringClass = mappingForLine.getOriginalFile();
-            methodName = mappingForLine.getIdentifier();
-          }
-          filename = mappingForLine.getOriginalFile();
-          lineNumber = mappingForLine.getLineNumber();
-        }
-      }
-    }
-
-    if (declaringClass != null) {
- return new StackTraceElement(declaringClass, methodName, filename, lineNumber);
-    }
-
-    // If anything goes wrong, just return the unobfuscated element
-    return ste;
-  }
-
- protected InputStream getSourceMapInputStream(String permutationStrongName, int fragmentNumber)
-      throws IOException {
- return openInputStream(permutationStrongName + "_sourceMap" + fragmentNumber + ".json");
-  }
-
-  /**
- * Retrieves a new {@link InputStream} for the given permutation strong name. This implementation, - * which subclasses may override, returns a {@link InputStream} for the <code>
-   * <i>permutation-strong-name</i>.symbolMap</code> file.
-   *
-   * @param permutationStrongName the GWT permutation strong name
-   * @return a new {@link InputStream}
-   */
- protected InputStream getSymbolMapInputStream(String permutationStrongName) throws IOException {
-    return openInputStream(permutationStrongName + ".symbolMap");
-  }
-
-  /**
-   * Opens a new {@link InputStream} for a symbol or source map file.
-   *
-   * @param fileName name of the symbol or source map file
- * @return an input stream for reading the file (doesn't need to be buffered). - * @exception IOException if an I/O error occurs while creating the input stream.
-   */
- protected abstract InputStream openInputStream(String fileName) throws IOException;
-
- private SourceMapping loadSourceMap(String permutationStrongName, int fragmentId) { - SourceMapping toReturn = sourceMaps.get(permutationStrongName + fragmentId);
-    if (toReturn == null) {
-      try {
-        String sourceMapString = loadStreamAsString(
-            getSourceMapInputStream(permutationStrongName, fragmentId));
-        toReturn = SourceMapConsumerFactory.parse(sourceMapString);
-        sourceMaps.put(permutationStrongName + fragmentId, toReturn);
-      } catch (Exception e) {
-      }
-    }
-    return toReturn;
-  }
-
-  private String loadStreamAsString(InputStream stream) {
-    return new Scanner(stream).useDelimiter("\\A").next();
-  }
-
-  private String loadOneSymbol(String strongName, String symbol) {
-    Set<String> symbolSet = new HashSet<String>();
-    symbolSet.add(symbol);
-    Map<String, String> symbolMap = loadSymbolMap(strongName, symbolSet);
-    return symbolMap.get(symbol);
-  }
-
-  /**
- * Returns a symbol map for the given strong name containing symbol data for
-   * all of the given required symbols. First checks the symbol cache, then
- * reads from disk if any symbol is missing. If a symbol cannot be loaded for
-   * some reason, it will be mapped to empty string.
-   */
-  private Map<String, String> loadSymbolMap(
-      String strongName, Set<String> requiredSymbols) {
- Map<String, String> toReturn = symbolCache.getAll(strongName, requiredSymbols);
-    if (toReturn.size() == requiredSymbols.size()) {
-      return toReturn;
-    }
-
-    Set<String> symbolsLeftToFind = new HashSet<String>(requiredSymbols);
-    toReturn = new HashMap<String, String>();
-    String line;
-
-    try {
-      BufferedReader bin = new BufferedReader(
-          new InputStreamReader(getSymbolMapInputStream(strongName)));
-      try {
- while ((line = bin.readLine()) != null && (symbolsLeftToFind.size() > 0 || !lazyLoad)) {
-          if (line.charAt(0) == '#') {
-            continue;
-          }
-          int idx = line.indexOf(',');
-          String symbol = line.substring(0, idx);
-          String symbolData = line.substring(idx + 1);
-          if (requiredSymbols.contains(symbol) || !lazyLoad) {
-            symbolsLeftToFind.remove(symbol);
-            toReturn.put(symbol, symbolData);
-          }
-        }
-      } finally {
-        bin.close();
-      }
-    } catch (IOException e) {
- // If the symbol map isn't found or there's an I/O error reading the file, the returned
-      // mapping may contain some or all empty data (see below).
-    }
-    for (String symbol : symbolsLeftToFind) {
- // Store the empty string in the symbolCache to show we actually looked on disk and couldn't - // find the symbols. This avoids reading disk repeatedly for symbols that can't be translated.
-      toReturn.put(symbol, SYMBOL_DATA_UNKNOWN);
-    }
-
-    symbolCache.putAll(strongName, toReturn);
-    return toReturn;
-  }
-
-  /**
- * Extracts the declaring class and method name from a JSNI ref, or null if the information cannot
-   * be extracted.
-   *
-   * @param refString symbol map reference string
- * @return a string array contains the declaring class and method name, or null when the regex
-   *         match fails
-   * @see com.google.gwt.dev.util.JsniRef
-   */
-  private String[] parse(String refString) {
-    Matcher matcher = JsniRefPattern.matcher(refString);
-    if (!matcher.matches()) {
-      return null;
-    }
-    String className = matcher.group(1);
-    String memberName = matcher.group(2);
-    String[] toReturn = new String[]{className, memberName};
-    return toReturn;
-  }
-}
diff --git a/user/src/com/google/gwt/junit/server/JUnitHostImpl.java b/user/src/com/google/gwt/junit/server/JUnitHostImpl.java
index 0577cbb..a7ba7b5 100644
--- a/user/src/com/google/gwt/junit/server/JUnitHostImpl.java
+++ b/user/src/com/google/gwt/junit/server/JUnitHostImpl.java
@@ -17,7 +17,7 @@

import static com.google.gwt.user.client.rpc.RpcRequestBuilder.MODULE_BASE_HEADER;

-import com.google.gwt.core.server.impl.StackTraceDeobfuscator;
+import com.google.gwt.core.server.StackTraceDeobfuscator;
 import com.google.gwt.junit.JUnitFatalLaunchException;
 import com.google.gwt.junit.JUnitMessageQueue;
 import com.google.gwt.junit.JUnitMessageQueue.ClientInfoExt;
diff --git a/user/src/com/google/gwt/logging/server/RemoteLoggingServiceImpl.java b/user/src/com/google/gwt/logging/server/RemoteLoggingServiceImpl.java
index 15cc374..924dd5b 100644
--- a/user/src/com/google/gwt/logging/server/RemoteLoggingServiceImpl.java
+++ b/user/src/com/google/gwt/logging/server/RemoteLoggingServiceImpl.java
@@ -16,7 +16,7 @@

 package com.google.gwt.logging.server;

-import com.google.gwt.core.server.impl.StackTraceDeobfuscator;
+import com.google.gwt.core.server.StackTraceDeobfuscator;
import com.google.gwt.logging.server.RemoteLoggingServiceUtil.RemoteLoggingException;
 import com.google.gwt.logging.shared.RemoteLoggingService;
 import com.google.gwt.user.server.rpc.RemoteServiceServlet;
diff --git a/user/src/com/google/gwt/logging/server/RemoteLoggingServiceUtil.java b/user/src/com/google/gwt/logging/server/RemoteLoggingServiceUtil.java
index 940cc95..027edd2 100644
--- a/user/src/com/google/gwt/logging/server/RemoteLoggingServiceUtil.java
+++ b/user/src/com/google/gwt/logging/server/RemoteLoggingServiceUtil.java
@@ -16,7 +16,7 @@

 package com.google.gwt.logging.server;

-import com.google.gwt.core.server.impl.StackTraceDeobfuscator;
+import com.google.gwt.core.server.StackTraceDeobfuscator;

 import java.util.logging.LogRecord;
 import java.util.logging.Logger;
diff --git a/user/src/com/google/gwt/logging/server/StackTraceDeobfuscator.java b/user/src/com/google/gwt/logging/server/StackTraceDeobfuscator.java
index 11b3060..1493a69 100644
--- a/user/src/com/google/gwt/logging/server/StackTraceDeobfuscator.java
+++ b/user/src/com/google/gwt/logging/server/StackTraceDeobfuscator.java
@@ -26,7 +26,7 @@
* @deprecated Use com.google.gwt.core.server.StackTraceDeobfuscator instead.
  */
 @Deprecated
-public class StackTraceDeobfuscator extends com.google.gwt.core.server.impl.StackTraceDeobfuscator { +public class StackTraceDeobfuscator extends com.google.gwt.core.server.StackTraceDeobfuscator {

   protected File symbolMapsDirectory;

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 485fb04..2b91b8c 100644
--- a/user/src/com/google/web/bindery/requestfactory/server/Logging.java
+++ b/user/src/com/google/web/bindery/requestfactory/server/Logging.java
@@ -16,7 +16,7 @@

 package com.google.web.bindery.requestfactory.server;

-import com.google.gwt.core.server.impl.StackTraceDeobfuscator;
+import com.google.gwt.core.server.StackTraceDeobfuscator;
 import com.google.gwt.logging.server.RemoteLoggingServiceUtil;
import com.google.gwt.logging.server.RemoteLoggingServiceUtil.RemoteLoggingException;
 import com.google.gwt.user.client.rpc.RpcRequestBuilder;
diff --git a/user/test/com/google/gwt/user/server/rpc/LoggingRPCTestServiceImpl.java b/user/test/com/google/gwt/user/server/rpc/LoggingRPCTestServiceImpl.java
index f08ac46..6facda3 100644
--- a/user/test/com/google/gwt/user/server/rpc/LoggingRPCTestServiceImpl.java +++ b/user/test/com/google/gwt/user/server/rpc/LoggingRPCTestServiceImpl.java
@@ -16,7 +16,7 @@

 package com.google.gwt.user.server.rpc;

-import com.google.gwt.core.server.impl.StackTraceDeobfuscator;
+import com.google.gwt.core.server.StackTraceDeobfuscator;
 import com.google.gwt.junit.linker.JUnitSymbolMapsLinker;
 import com.google.gwt.logging.server.RemoteLoggingServiceUtil;
 import com.google.gwt.user.client.rpc.LoggingRPCTest;

--
To view, visit https://gwt-review.googlesource.com/3512
To unsubscribe, visit https://gwt-review.googlesource.com/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ic84f3b2210e3c40f0f7dc41bdeea9d13bf1a4dc6
Gerrit-PatchSet: 1
Gerrit-Project: gwt
Gerrit-Branch: master
Gerrit-Owner: Goktug Gokdogan <[email protected]>

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors
--- You received this message because you are subscribed to the Google Groups "GWT Contributors" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to