Revision: 9361
Author: fre...@google.com
Date: Mon Dec 6 09:48:07 2010
Log: Modifications to StackTraceDeobfuscator:
- Introduces a new protected method, getSymbolMapInputStream(), to obtain a
symbol map InputStream for a given permutation strong name, to be
overridden by subclasses.
- Makes the deobfuscateStackTrace() convenience method public
- Multiple lookups for a given permutations's, non-existent or broken,
symbol map file no longer results in repeated attempt to access or parse
the same file
- Prevent NPE due to parse() method returning null
- Javadoc additions
Review at http://gwt-code-reviews.appspot.com/1189801
Review by: sce...@google.com
http://code.google.com/p/google-web-toolkit/source/detail?r=9361
Modified:
/trunk/user/src/com/google/gwt/logging/server/StackTraceDeobfuscator.java
=======================================
---
/trunk/user/src/com/google/gwt/logging/server/StackTraceDeobfuscator.java
Thu Dec 2 11:11:38 2010
+++
/trunk/user/src/com/google/gwt/logging/server/StackTraceDeobfuscator.java
Mon Dec 6 09:48:07 2010
@@ -18,8 +18,10 @@
import java.io.BufferedReader;
import java.io.File;
-import java.io.FileReader;
+import java.io.FileInputStream;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.LogRecord;
@@ -30,12 +32,13 @@
* Deobfuscates stack traces on the server side. This class requires that
you
* have turned on emulated stack traces and moved your symbolMap files to a
* place accessible by your server. More concretely, you must compile with
the
- * -extra command line option, copy the symbolMaps directory to somewhere
your
- * server side code has access to it, and then set the symbolMapsDirectory
in
- * this class through the constructor, or the setter method.
- * For example, this variable could be set to "WEB-INF/classes/symbolMaps/"
- * if you copied the symbolMaps directory to there or compiled your
application
- * using <code>-extra war/WEB-INF/classes/</code>.
+ * <code>-extra</code> command line option, copy the
<code>symbolMaps</code>
+ * directory to somewhere your server side code has access to it, and then
set
+ * the symbolMapsDirectory in this class through the constructor, or the
setter
+ * method. For example, this variable could be set to
+ * "WEB-INF/classes/symbolMaps/", if you copied the symbolMaps directory to
+ * there or compiled your application using
+ * <code>-extra war/WEB-INF/classes/</code>.
*
* TODO(unnurg): Combine this code with similar code in JUnitHostImpl
*/
@@ -65,6 +68,13 @@
setSymbolMapsDirectory(symbolMapsDirectory);
}
+ /**
+ * Best effort resymbolization of a log record's stack trace.
+ *
+ * @param lr the log record to resymbolize
+ * @param strongName the GWT permutation strong name
+ * @return the best effort resymbolized log record
+ */
public LogRecord deobfuscateLogRecord(LogRecord lr, String strongName) {
if (lr.getThrown() != null && strongName != null) {
lr.setThrown(deobfuscateThrowable(lr.getThrown(), strongName));
@@ -72,6 +82,30 @@
return lr;
}
+ /**
+ * 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 StackTraceElement[] deobfuscateStackTrace(
+ StackTraceElement[] st, String strongName) {
+ 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 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 StackTraceElement resymbolize(StackTraceElement ste,
String strongName) {
SymbolMap map = loadSymbolMap(strongName);
@@ -84,6 +118,16 @@
String[] ref = parse(
parts[0].substring(0, parts[0].lastIndexOf(')') + 1));
+ String declaringClass;
+ String methodName;
+ 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"
String filename = "Unknown".equals(parts[3]) ? null
: parts[3].substring(parts[3].lastIndexOf('/') + 1);
@@ -98,7 +142,8 @@
lineNumber = Integer.parseInt(parts[4]);
}
- return new StackTraceElement(ref[0], ref[1], filename, lineNumber);
+ return new StackTraceElement(
+ declaringClass, methodName, filename, lineNumber);
}
}
// If anything goes wrong, just return the unobfuscated element
@@ -109,14 +154,23 @@
// permutations are unique, no need to clear the symbolMaps hash map
this.symbolMapsDirectory = new File(symbolMapsDirectory);
}
-
- private StackTraceElement[] deobfuscateStackTrace(
- StackTraceElement[] st, String strongName) {
- StackTraceElement[] newSt = new StackTraceElement[st.length];
- for (int i = 0; i < st.length; i++) {
- newSt[i] = resymbolize(st[i], strongName);
- }
- return newSt;
+
+ /**
+ * 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 in the
+ * symbolMapsDirectory.
+ *
+ * @param permutationStrongName the GWT permutation strong name
+ * @return a new {...@link InputStream}
+ * @throws IOException
+ */
+ protected InputStream getSymbolMapInputStream(String
permutationStrongName)
+ throws IOException {
+ String filename = symbolMapsDirectory.getCanonicalPath()
+ + File.separatorChar + permutationStrongName + ".symbolMap";
+ return new FileInputStream(filename);
}
private Throwable deobfuscateThrowable(Throwable old, String strongName)
{
@@ -142,9 +196,8 @@
String line;
try {
- String filename = symbolMapsDirectory.getCanonicalPath()
- + File.separatorChar + strongName + ".symbolMap";
- BufferedReader bin = new BufferedReader(new FileReader(filename));
+ BufferedReader bin = new BufferedReader(
+ new InputStreamReader(getSymbolMapInputStream(strongName)));
try {
while ((line = bin.readLine()) != null) {
if (line.charAt(0) == '#') {
@@ -158,13 +211,23 @@
bin.close();
}
} catch (IOException e) {
- toReturn = null;
+ // use empty symbol map to avoid repeated lookups
+ toReturn = new SymbolMap();
}
symbolMaps.put(strongName, toReturn);
return toReturn;
}
-
+
+ /**
+ * Extracts the declaring class and method name from a JSNI ref, or null
if
+ * the information cannot be extracted.
+ *
+ * @see com.google.gwt.dev.util.JsniRef
+ * @param refString symbol map reference string
+ * @return a string array contains the declaring class and method name,
or
+ * null when the regex match fails
+ */
private String[] parse(String refString) {
Matcher matcher = JsniRefPattern.matcher(refString);
if (!matcher.matches()) {
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors