scriptstacktrace.java

来自「RESIN 3.2 最新源码」· Java 代码 · 共 356 行

JAVA
356
字号
/* * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT.  See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * *   Free Software Foundation, Inc. *   59 Temple Place, Suite 330 *   Boston, MA 02111-1307  USA * * @author Scott Ferguson */package com.caucho.java;import com.caucho.bytecode.Attribute;import com.caucho.bytecode.ByteCodeParser;import com.caucho.bytecode.JavaClass;import com.caucho.bytecode.OpaqueAttribute;import com.caucho.loader.SimpleLoader;import com.caucho.util.L10N;import com.caucho.util.Log;import com.caucho.vfs.ReadStream;import com.caucho.vfs.Vfs;import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.InputStream;import java.io.PrintWriter;import java.util.HashMap;import java.util.WeakHashMap;import java.util.logging.Level;import java.util.logging.Logger;/** * Prints a stack trace using JSR-45 */public class ScriptStackTrace {  private static final L10N L = new L10N(ScriptStackTrace.class);  private static final Logger log = Log.open(ScriptStackTrace.class);    private static WeakHashMap<Class,LineMap> _scriptMap    = new WeakHashMap<Class,LineMap>();    /**   * Filter a stack trace, replacing names.   */  public static void printStackTrace(Throwable e, PrintWriter out)  {    StackTraceElement lastHead = null;    ClassLoader loader = SimpleLoader.create(WorkDir.getLocalWorkDir());        while (true) {      if (e.getMessage() != null)	out.println(e.getClass().getName() + ": " + e.getMessage());      else	out.println(e.getClass().getName());      StackTraceElement []trace = e.getStackTrace();      StackTraceElement nextHead = trace.length > 0 ? trace[0] : null;      for (int i = 0; i < trace.length; i++) {	if (trace[i].equals(lastHead))	  break;		out.print("\tat ");	printStackTraceElement(trace[i], out, loader);      }      lastHead = nextHead;      Throwable cause = e.getCause();      if (cause != null) {	out.print("Caused by: ");	e = cause;      }      else	break;    }  }  /**   * Prints a single stack trace element.   */  private static void printStackTraceElement(StackTraceElement trace,					     PrintWriter out,					     ClassLoader loader)  {    try {      LineMap map = getScriptLineMap(trace.getClassName(), loader);      if (map != null) {	LineMap.Line line = map.getLine(trace.getLineNumber());	if (line != null) {	  out.print(trace.getClassName() + "." + trace.getMethodName());	  out.print("(" + line.getSourceFilename() + ":");	  out.println(line.getSourceLine(trace.getLineNumber()) + ")");	  return;	}      }    } catch (Throwable e) {    }        out.println(trace);  }  /**   * Loads the local line map for a class.   */  public static LineMap getScriptLineMap(String className, ClassLoader loader)  {    try {      Class cl = loader.loadClass(className);      LineMap map = _scriptMap.get(cl);      if (map == null) {	map = loadScriptMap(cl);	_scriptMap.put(cl, map);      }      return map;    } catch (Throwable e) {      return null;    }  }    /**   * Loads the script map for a class   */  private static LineMap loadScriptMap(Class cl)  {    ClassLoader loader = cl.getClassLoader();    if (loader == null)      return new LineMap(); // null map        try {      String pathName = cl.getName().replace('.', '/') + ".class";      InputStream is = loader.getResourceAsStream(pathName);      if (is == null)	return null;            try {	JavaClass jClass = new ByteCodeParser().parse(is);	Attribute attr = jClass.getAttribute("SourceDebugExtension");	if (attr == null) {	  int p = cl.getName().indexOf('$');	  	  if (p > 0) {	    String className = cl.getName().substring(0, p);	    return loadScriptMap(loader.loadClass(className));	  }	  return new LineMap();	}	else if (attr instanceof OpaqueAttribute) {	  byte []value = ((OpaqueAttribute) attr).getValue();	  ByteArrayInputStream bis = new ByteArrayInputStream(value);	  ReadStream rs = Vfs.openRead(bis);	  rs.setEncoding("UTF-8");	  try {	    return parseSmap(rs);	  } finally {	    rs.close();	  }	}	else	  throw new IllegalStateException(L.l("Expected opaque attribute at '{0}'",					      attr));      } finally {	if (is != null)	  is.close();      }    } catch (Throwable e) {      log.log(Level.FINER, e.toString(), e);      return new LineMap(); // null map    }  }  /**   * Parses the SMAP file.   */  private static LineMap parseSmap(ReadStream is)    throws IOException  {    String smap = is.readln();    if (! smap.equals("SMAP"))      throw new IOException(L.l("Illegal header"));          String outputFile = is.readln().trim();    String defaultStratum = is.readln().trim();    String stratum = defaultStratum;    HashMap<String,String> fileMap = new HashMap<String,String>();    LineMap lineMap = new LineMap(outputFile);          loop:    while (true) {      int ch = is.read();      if (ch < 0)	break;      if (ch != '*')	throw new IOException(L.l("unexpected character '{0}'",				  String.valueOf((char) ch)));      int code = is.read();      String value = is.readln();      switch (code) {      case 'E':	break loop;      case 'S':	stratum = value.trim();	break;      case 'F':	while ((ch = is.read()) > 0 && ch != '*') {	  if (ch == '+') {	    String first = is.readln().trim();	    String second = is.readln().trim();	    int p = first.indexOf(' ');	    String key = first.substring(0, p);	    String file = first.substring(p + 1).trim();	    if (fileMap.size() == 0)	      fileMap.put("", second);	    fileMap.put(key, second);	  }	  else {	    String first = is.readln().trim();	  	    int p = first.indexOf(' ');	    String key = first.substring(0, p);	    String file = first.substring(p + 1).trim();	    if (fileMap.size() == 0)	      fileMap.put("", file);	    fileMap.put(key, file);	  }	}	if (ch == '*')	  is.unread();	break;      case 'L':	while ((ch = is.read()) != '*' && ch > 0) {	  is.unread();	  	  String line = is.readln().trim();	  addMap(line, fileMap, lineMap);	}	if (ch == '*')	  is.unread();	break;	      default:	while ((ch = is.read()) != '*') {	  is.readln();	}	if (ch == '*')	  is.unread();	break;      }    }            return lineMap;  }  private static void addMap(String line,			     HashMap<String,String> fileMap,			     LineMap lineMap)  {    int colon = line.indexOf(':');    if (colon < 0)      return;    int hash = line.indexOf('#');    int startLine = 0;    String fileId = "";    int repeatCount = 1;    if (hash < 0)      startLine = Integer.parseInt(line.substring(0, colon));    else {      startLine = Integer.parseInt(line.substring(0, hash));      int comma = line.indexOf(',', hash);      if (comma > 0 && comma < colon) {	fileId = line.substring(hash + 1, comma).trim();	repeatCount = Integer.parseInt(line.substring(comma + 1, colon));      }      else	fileId = line.substring(hash + 1, colon).trim();    }    int outputLine = -1;    int outputIncrement = 1;    int comma = line.indexOf(',', colon);    if (comma > 0) {      outputLine = Integer.parseInt(line.substring(colon + 1, comma));      outputIncrement = Integer.parseInt(line.substring(comma + 1));    }    else      outputLine = Integer.parseInt(line.substring(colon + 1));    String file = fileMap.get(fileId);    lineMap.addLine(startLine, file, repeatCount, outputLine, outputIncrement);  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?