1 /******************************************************************************* 2 * Copyright (c) 2005, 2017 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 /** 15 * 16 */ 17 package org.eclipse.jdt.internal.junit.ui; 18 19 import java.io.BufferedReader; 20 import java.io.IOException; 21 import java.io.PrintWriter; 22 import java.io.StringReader; 23 import java.io.StringWriter; 24 25 public class TextualTrace { 26 public static final int LINE_TYPE_EXCEPTION = 1; 27 28 public static final int LINE_TYPE_NORMAL = 0; 29 30 public static final int LINE_TYPE_STACKFRAME = 2; 31 32 private final String fTrace; 33 TextualTrace(String trace, String[] filterPatterns)34 public TextualTrace(String trace, String[] filterPatterns) { 35 super(); 36 fTrace = filterStack(trace, filterPatterns); 37 } 38 display(ITraceDisplay display, int maxLabelLength)39 public void display(ITraceDisplay display, int maxLabelLength) { 40 StringReader stringReader = new StringReader(fTrace); 41 BufferedReader bufferedReader = new BufferedReader(stringReader); 42 String line; 43 44 try { 45 // first line contains the thrown exception 46 line = readLine(bufferedReader); 47 if (line == null) 48 return; 49 50 displayWrappedLine(display, maxLabelLength, line, 51 LINE_TYPE_EXCEPTION); 52 53 // the stack frames of the trace 54 while ((line = readLine(bufferedReader)) != null) { 55 int type = isAStackFrame(line) ? LINE_TYPE_STACKFRAME 56 : LINE_TYPE_NORMAL; 57 displayWrappedLine(display, maxLabelLength, line, type); 58 } 59 } catch (IOException e) { 60 display.addTraceLine(LINE_TYPE_NORMAL, fTrace); 61 } 62 } 63 displayWrappedLine(ITraceDisplay display, int maxLabelLength, String line, int type)64 private void displayWrappedLine(ITraceDisplay display, int maxLabelLength, 65 String line, int type) { 66 final int labelLength = line.length(); 67 if (labelLength < maxLabelLength) { 68 display.addTraceLine(type, line); 69 } else { 70 // workaround for bug 74647: JUnit view truncates 71 // failure message 72 display.addTraceLine(type, line.substring(0, maxLabelLength)); 73 int offset = maxLabelLength; 74 while (offset < labelLength) { 75 int nextOffset = Math.min(labelLength, offset + maxLabelLength); 76 display.addTraceLine(LINE_TYPE_NORMAL, line.substring(offset, 77 nextOffset)); 78 offset = nextOffset; 79 } 80 } 81 } 82 filterLine(String[] patterns, String line)83 private boolean filterLine(String[] patterns, String line) { 84 String pattern; 85 int len; 86 for (int i = (patterns.length - 1); i >= 0; --i) { 87 pattern = patterns[i]; 88 len = pattern.length() - 1; 89 if (pattern.charAt(len) == '*') { 90 // strip trailing * from a package filter 91 pattern = pattern.substring(0, len); 92 } else if (Character.isUpperCase(pattern.charAt(0))) { 93 // class in the default package 94 pattern = FailureTrace.FRAME_PREFIX + pattern + '.'; 95 } else { 96 // class names start w/ an uppercase letter after the . 97 final int lastDotIndex = pattern.lastIndexOf('.'); 98 if ((lastDotIndex != -1) 99 && (lastDotIndex != len) 100 && Character.isUpperCase(pattern.charAt(lastDotIndex + 1))) 101 pattern += '.'; // append . to a class filter 102 } 103 104 if (line.indexOf(pattern) > 0) 105 return true; 106 } 107 return false; 108 } 109 filterStack(String stackTrace, String[] filterPatterns)110 private String filterStack(String stackTrace, String[] filterPatterns) { 111 if (filterPatterns.length == 0 || stackTrace == null) 112 return stackTrace; 113 114 StringWriter stringWriter = new StringWriter(); 115 PrintWriter printWriter = new PrintWriter(stringWriter); 116 StringReader stringReader = new StringReader(stackTrace); 117 BufferedReader bufferedReader = new BufferedReader(stringReader); 118 119 String line; 120 String[] patterns = filterPatterns; 121 boolean firstLine= true; 122 try { 123 while ((line= bufferedReader.readLine()) != null) { 124 if (firstLine || !filterLine(patterns, line)) 125 printWriter.println(line); 126 firstLine= false; 127 } 128 } catch (IOException e) { 129 return stackTrace; // return the stack unfiltered 130 } 131 return stringWriter.toString(); 132 } 133 isAStackFrame(String itemLabel)134 private boolean isAStackFrame(String itemLabel) { 135 // heuristic for detecting a stack frame - works for JDK 136 return itemLabel.contains(" at "); //$NON-NLS-1$ 137 } 138 readLine(BufferedReader bufferedReader)139 private String readLine(BufferedReader bufferedReader) throws IOException { 140 String readLine = bufferedReader.readLine(); 141 return readLine == null ? null : readLine.replace('\t', ' '); 142 } 143 } 144