1 16 package com.google.gwt.dev.util.log; 17 18 import com.google.gwt.core.ext.TreeLogger; 19 20 import java.util.ArrayList ; 21 import java.util.HashSet ; 22 23 26 public abstract class AbstractTreeLogger implements TreeLogger { 27 28 static final String OUT_OF_MEMORY_MSG = "Out of memory; to increase the " 30 + "amount of memory, use the -Xmx flag at startup (java -Xmx128M ...)"; 31 32 private static class UncommittedBranchData { 33 34 public final Throwable caught; 35 36 public final String message; 37 public final TreeLogger.Type type; 38 39 public UncommittedBranchData(Type type, String message, Throwable exception) { 40 caught = exception; 41 this.message = message; 42 this.type = type; 43 } 44 } 45 46 public static String getStackTraceAsString(Throwable e) { 47 StringBuffer message = new StringBuffer (); 51 Throwable currentCause = e; 52 String causedBy = ""; 53 HashSet seenCauses = new HashSet (); 54 while (currentCause != null && !seenCauses.contains(currentCause)) { 55 seenCauses.add(currentCause); 56 57 StackTraceElement [] trace = currentCause.getStackTrace(); 58 message.append(causedBy); 59 causedBy = "\nCaused by: "; message.append(currentCause.getClass().getName()); 61 message.append(": " + currentCause.getMessage()); 62 StackTraceElement [] stackElems = findMeaningfulStackTraceElements(trace); 63 if (stackElems != null) { 64 for (int i = 0; i < stackElems.length; ++i) { 65 message.append("\n\tat "); 66 message.append(stackElems[i].toString()); 67 } 68 } 69 70 currentCause = currentCause.getCause(); 71 } 72 return message.toString(); 73 } 74 75 private static StackTraceElement [] findMeaningfulStackTraceElements( 76 StackTraceElement [] elems) { 77 ArrayList goodElems = new ArrayList (); 78 StackTraceElement prevElem = null; 79 for (int i = 0; i < elems.length; i++) { 80 StackTraceElement elem = elems[i]; 81 if (elem.getLineNumber() > 0) { 82 goodElems.add(elem); 83 if (goodElems.size() < 10 84 || prevElem.getClassName().equals(elem.getClassName())) { 85 prevElem = elem; 87 } else { 88 break; 90 } 91 } 92 } 93 if (goodElems.size() > 0) { 94 return (StackTraceElement []) goodElems.toArray(new StackTraceElement [goodElems.size()]); 95 } else { 96 return null; 97 } 98 } 99 100 public int indexWithinMyParent; 101 102 private TreeLogger.Type logLevel = TreeLogger.ALL; 103 104 private int nextChildIndex; 105 106 private final Object nextChildIndexLock = new Object (); 107 108 private AbstractTreeLogger parent; 109 110 private UncommittedBranchData uncommitted; 111 112 115 protected AbstractTreeLogger() { 116 } 117 118 122 public final synchronized TreeLogger branch(TreeLogger.Type type, String msg, 123 Throwable caught) { 124 125 if (msg == null) { 126 msg = "(Null branch message)"; 127 } 128 129 int childIndex = allocateNextChildIndex(); 132 133 AbstractTreeLogger childLogger = doBranch(); 135 136 childLogger.logLevel = logLevel; 138 139 childLogger.indexWithinMyParent = childIndex; 142 143 childLogger.parent = this; 146 147 childLogger.uncommitted = new UncommittedBranchData(type, msg, caught); 152 153 if (causedByOutOfMemory(caught)) { 160 type = TreeLogger.ERROR; 161 childLogger.log(type, OUT_OF_MEMORY_MSG, null); 162 } 163 164 if (isLoggable(type)) { 167 childLogger.commitMyBranchEntryInMyParentLogger(); 171 } 172 173 return childLogger; 174 } 175 176 public final int getBranchedIndex() { 177 return indexWithinMyParent; 178 } 179 180 public final AbstractTreeLogger getParentLogger() { 181 return parent; 182 } 183 184 public final synchronized boolean isLoggable(TreeLogger.Type type) { 185 return !type.isLowerPriorityThan(logLevel); 186 } 187 188 193 public final synchronized void log(TreeLogger.Type type, String msg, 194 Throwable caught) { 195 196 if (msg == null) { 197 msg = "(Null log message)"; 198 } 199 200 if (causedByOutOfMemory(caught)) { 203 branch(TreeLogger.ERROR, msg, caught); 204 return; 205 } 206 207 int childIndex = allocateNextChildIndex(); 208 if (isLoggable(type)) { 209 commitMyBranchEntryInMyParentLogger(); 210 doLog(childIndex, type, msg, caught); 211 } 212 } 213 214 219 public final synchronized void setMaxDetail(TreeLogger.Type type) { 220 if (type == null) { 221 type = TreeLogger.INFO; 222 } 223 logLevel = type; 224 } 225 226 public String toString() { 227 return getLoggerId(); 228 } 229 230 233 protected abstract AbstractTreeLogger doBranch(); 234 235 239 protected abstract void doCommitBranch( 240 AbstractTreeLogger childBeingCommitted, TreeLogger.Type type, String msg, 241 Throwable caught); 242 243 248 protected abstract void doLog(int indexOfLogEntryWithinParentLogger, 249 TreeLogger.Type type, String msg, Throwable caught); 250 251 private int allocateNextChildIndex() { 252 synchronized (nextChildIndexLock) { 253 return nextChildIndex++; 255 } 256 } 257 258 265 private boolean causedByOutOfMemory(Throwable t) { 266 267 while (t != null) { 268 if (t instanceof OutOfMemoryError ) { 269 return true; 270 } 271 t = t.getCause(); 272 } 273 274 return false; 275 } 276 277 281 private synchronized void commitMyBranchEntryInMyParentLogger() { 282 if (parent != null) { 285 if (uncommitted != null) { 286 parent.commitMyBranchEntryInMyParentLogger(); 289 290 parent.doCommitBranch(this, uncommitted.type, uncommitted.message, 293 uncommitted.caught); 294 295 uncommitted = null; 298 } 299 } 300 } 301 302 private String getLoggerId() { 303 if (parent != null) { 304 if (parent.parent == null) { 305 return parent.getLoggerId() + getBranchedIndex(); 307 } else { 308 return parent.getLoggerId() + "." + getBranchedIndex(); 310 } 311 } else { 312 return "#"; 314 } 315 } 316 } 317 | Popular Tags |