Package com.caucho.java

Source Code of com.caucho.java.ScriptStackTrace

/*
* Copyright (c) 1998-2010 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);
  }
}
TOP

Related Classes of com.caucho.java.ScriptStackTrace

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.