Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package org.jruby.runtime.backtrace;
  
  import java.util.List;
  import java.util.Map;
  
  import org.jruby.Ruby;
 
 public class BacktraceData implements Serializable {
     private final StackTraceElement[] javaTrace;
     private final BacktraceElement[] rubyTrace;
     private final boolean fullTrace;
     private final boolean maskNative;
     private final boolean includeNonFiltered;
 
     private final Pattern FILTER_CLASSES = Pattern.compile("^(org\\.jruby)|(sun\\.reflect)");
 
     public BacktraceData(StackTraceElement[] javaTraceBacktraceElement[] rubyTraceboolean fullTraceboolean maskNativeboolean includeNonFiltered) {
         this. = javaTrace;
         this. = rubyTrace;
         this. = fullTrace;
         this. = includeNonFiltered;
         this. = maskNative;
     }
 
     public static final BacktraceData EMPTY = new BacktraceData(
             new StackTraceElement[0],
             new BacktraceElement[0],
             false,
             false,
             false);
 
     public RubyStackTraceElement[] getBacktrace(Ruby runtime) {
         if ( == null) {
              = transformBacktrace(runtime.getBoundMethods());
         }
         return ;
     }
 
     private RubyStackTraceElement[] transformBacktrace(Map<StringMap<StringString>> boundMethods) {
 
         // used for duplicating the previous Ruby frame when masking native calls
         boolean dupFrame = false;
         String dupFrameName = null;
 
         // a running index into the Ruby backtrace stack, incremented for each
         // interpreter frame we encounter in the Java backtrace.
         int rubyFrameIndex =  == null ? -1 : . - 1;
 
         // loop over all elements in the Java stack trace
         for (int i = 0; i < .i++) {
 
             StackTraceElement element = [i];
 
             // skip unnumbered frames
             int line = element.getLineNumber();
             if (line == -1) continue;
 
             String className = element.getClassName();
             String methodName = element.getMethodName();
             String filename = element.getFileName();
 
             if (filename != null) {
 
                 // Don't process .java files
                 if (!filename.endsWith(".java")) {
 
                     boolean compiled = false;
                     int index = -1;
 
                     // Check for compiled name markers
                     // FIXME: Formalize jitted method structure so this isn't quite as hacky
                     if (className.startsWith(.)) {
 
                         // JIT-compiled code
                         compiled = true;
 
                         // pull out and demangle the method name
                         String tmpClassName = className;
                         int start = ..length() + 1;
                         int hash = tmpClassName.indexOf(.start);
                         int end = tmpClassName.lastIndexOf("_");
                         className = tmpClassName.substring(starthash);
                         methodName = tmpClassName.substring(hash + ..length(), end);
 
                     } else if ((index = methodName.indexOf("$RUBY$")) >= 0) {
 
                         // AOT-compiled code
                         compiled = true;
 
                         // pull out and demangle the method name
                         index += "$RUBY$".length();
                         if (methodName.indexOf("SYNTHETIC"index) == index) {
                            methodName = methodName.substring(index + "SYNTHETIC".length());
                        } else {
                            methodName = methodName.substring(index);
                        }
                    }
                    // demangle any JVM-prohibited names
                    methodName = JavaNameMangler.demangleMethodName(methodName);
                    // root body gets named (root)
                    if (methodName.equals("__file__")) methodName = "(root)";
                    // construct Ruby trace element
                    RubyStackTraceElement rubyElement = new RubyStackTraceElement(classNamemethodNamefilenamelinefalse);
                    // add duplicate if masking native and previous frame was native (Kernel#caller)
                    if ( && dupFrame) {
                        dupFrame = false;
                        trace.add(new RubyStackTraceElement(classNamedupFrameNamefilenamelinefalse));
                    }
                    trace.add(rubyElement);
                    if (compiled) {
                        // if it's a synthetic call, gobble up parent calls
                        // TODO: need to formalize this better
                        while (element.getMethodName().contains("$RUBY$SYNTHETIC") && ++i < .) {
                            element = [i];
                        }
                    }
                }
            }
            // Java-based Ruby core methods
            String rubyName = null;
            if (
                     || // full traces show all elements
                    (rubyName = getBoundMethodName(boundMethodsclassNamemethodName)) != null // if a bound Java impl, always show
                    ) {
                if (rubyName == nullrubyName = methodName;
                // add package to filename
                filename = packagedFilenameFromElement(filenameclassName);
                // mask .java frames out for e.g. Kernel#caller
                if () {
                    // for Kernel#caller, don't show .java frames in the trace
                    dupFrame = true;
                    dupFrameName = rubyName;
                    continue;
                }
                // construct Ruby trace element
                trace.add(new RubyStackTraceElement(classNamerubyNamefilenamelinefalse));
                // if not full trace, we're done; don't check interpreted marker
                if (!) {
                    continue;
                }
            }
            // Interpreted frames
            if (rubyFrameIndex >= 0 &&
                    ..contains(className) &&
                    ..containsKey(methodName)) {
                // pop interpreter frame
                BacktraceElement rubyFrame = [rubyFrameIndex--];
                // construct Ruby trace element
                RubyStackTraceElement rubyElement = new RubyStackTraceElement("RUBY"rubyFrame.methodrubyFrame.filenamerubyFrame.line + 1, false);
                // dup if masking native and previous frame was native
                if ( && dupFrame) {
                    dupFrame = false;
                    trace.add(new RubyStackTraceElement(rubyElement.getClassName(), dupFrameNamerubyElement.getFileName(), rubyElement.getLineNumber(), rubyElement.isBinding()));
                }
                trace.add(rubyElement);
                continue;
            }
            // if all else fails and this is a non-JRuby element we want to include, add it
            if ( && !isFilteredClass(className)) {
                trace.add(new RubyStackTraceElement(
                        className,
                        methodName,
                        packagedFilenameFromElement(filenameclassName),
                        line,
                        false
                ));
                continue;
            }
        }
        RubyStackTraceElement[] rubyStackTrace = new RubyStackTraceElement[trace.size()];
        return trace.toArray(rubyStackTrace);
    }
    public static String getBoundMethodName(Map<String,Map<String,String>> boundMethodsString classNameString methodName) {
        Map<StringStringjavaToRuby = boundMethods.get(className);
        if (javaToRuby == nullreturn null;
        return javaToRuby.get(methodName);
    }
    private static String packagedFilenameFromElement(String filenameString className) {
        // stick package on the beginning
        if (filename == null) {
            filename = className.replaceAll("\\.""/");
        } else {
            int lastDot = className.lastIndexOf('.');
            if (lastDot != -1) {
                filename = className.substring(0, lastDot + 1).replaceAll("\\.""/") + filename;
            }
        }
        return filename;
    }
    private boolean isFilteredClass(String className) {
        return .matcher(className).find();
    }
New to GrepCode? Check out our FAQ X