001/* 002 * (C) Copyright 2013 Nuxeo SA (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl-2.1.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * vpasquier <vpasquier@nuxeo.com> 016 * slacoin <slacoin@nuxeo.com> 017 */ 018package org.nuxeo.ecm.automation.core.trace; 019 020import java.io.BufferedWriter; 021import java.io.IOException; 022import java.io.OutputStream; 023import java.io.OutputStreamWriter; 024import java.io.Writer; 025import java.util.Arrays; 026import java.util.Calendar; 027import java.util.List; 028 029import org.apache.commons.logging.Log; 030import org.apache.commons.logging.LogFactory; 031 032/** 033 * @since 5.7.3 034 */ 035public class TracePrinter { 036 037 private static final Log log = LogFactory.getLog(TracePrinter.class); 038 039 protected final BufferedWriter writer; 040 041 protected String preamble = ""; 042 043 public TracePrinter(Writer writer) { 044 this.writer = new BufferedWriter(writer); 045 } 046 047 public TracePrinter(OutputStream out) { 048 this(new OutputStreamWriter(out)); 049 } 050 051 protected void printLine(String line) throws IOException { 052 writer.write(preamble + line); 053 } 054 055 protected void printHeading(String heading) throws IOException { 056 printLine(System.getProperty("line.separator") + System.getProperty("line.separator") + "****** " + heading 057 + " ******"); 058 } 059 060 public void print(Trace trace) throws IOException { 061 StringBuilder sb = new StringBuilder(); 062 printHeading("chain"); 063 if (trace.error != null) { 064 sb.append(System.getProperty("line.separator")); 065 if (trace.getParent() != null) { 066 sb.append("Parent Chain ID: "); 067 sb.append(trace.getParent().getChainId()); 068 sb.append(System.getProperty("line.separator")); 069 } 070 sb.append("Name: "); 071 sb.append(trace.getChain().getId()); 072 if (trace.getChain().getAliases() != null && trace.getChain().getAliases().length > 0) { 073 sb.append(System.getProperty("line.separator")); 074 sb.append("Aliases: "); 075 sb.append(Arrays.toString(trace.getChain().getAliases())); 076 } 077 sb.append(System.getProperty("line.separator")); 078 sb.append("Exception: "); 079 sb.append(trace.error.getClass().getSimpleName()); 080 sb.append(System.getProperty("line.separator")); 081 sb.append("Caught error: "); 082 sb.append(trace.error.getMessage()); 083 sb.append(System.getProperty("line.separator")); 084 sb.append("Caused by: "); 085 sb.append(trace.error.getCause()); 086 printLine(sb.toString()); 087 } else { 088 sb.append(System.getProperty("line.separator")); 089 if (trace.getParent() != null) { 090 sb.append("Parent Chain ID: "); 091 sb.append(trace.getParent().getChainId()); 092 sb.append(System.getProperty("line.separator")); 093 } 094 sb.append("Name: "); 095 sb.append(trace.getChain().getId()); 096 sb.append(System.getProperty("line.separator")); 097 sb.append("Produced output type: "); 098 sb.append(trace.output == null ? "Void" : trace.output.getClass().getSimpleName()); 099 printLine(sb.toString()); 100 } 101 StringBuilder stringBuilder = new StringBuilder(); 102 stringBuilder.append(System.getProperty("line.separator")); 103 stringBuilder.append("****** Hierarchy calls ******"); 104 stringBuilder.append(System.getProperty("line.separator")); 105 displayOperationTreeCalls(trace.operations, stringBuilder); 106 printLine(stringBuilder.toString()); 107 print(trace.operations); 108 writer.flush(); 109 } 110 111 public void print(List<Call> calls) throws IOException { 112 for (Call call : calls) { 113 print(call); 114 } 115 } 116 117 public void print(Call call) throws IOException { 118 printCall(call); 119 } 120 121 public void printCall(Call call) { 122 try { 123 StringBuilder sb = new StringBuilder(); 124 sb.append(System.getProperty("line.separator")); 125 sb.append(System.getProperty("line.separator")); 126 sb.append("****** " + call.getType().getId() + " ******"); 127 sb.append(System.getProperty("line.separator")); 128 sb.append("Chain ID: "); 129 sb.append(call.getChainId()); 130 if (call.getAliases() != null) { 131 sb.append(System.getProperty("line.separator")); 132 sb.append("Chain Aliases: "); 133 sb.append(call.getAliases()); 134 } 135 sb.append(System.getProperty("line.separator")); 136 sb.append("Class: "); 137 sb.append(call.getType().getType().getSimpleName()); 138 sb.append(System.getProperty("line.separator")); 139 sb.append("Method: '"); 140 sb.append(call.getMethod().getMethod().getName()); 141 sb.append("' | Input Type: "); 142 sb.append(call.getMethod().getConsume()); 143 sb.append(" | Output Type: "); 144 sb.append(call.getMethod().getProduce()); 145 sb.append(System.getProperty("line.separator")); 146 sb.append("Input: "); 147 sb.append(call.getInput()); 148 if (!call.getParmeters().isEmpty()) { 149 sb.append(System.getProperty("line.separator")); 150 sb.append("Parameters "); 151 for (String parameter : call.getParmeters().keySet()) { 152 sb.append(" | "); 153 sb.append("Name: "); 154 sb.append(parameter); 155 sb.append(", Value: "); 156 Object value = call.getParmeters().get(parameter); 157 if (value instanceof Call.ExpressionParameter) { 158 value = String.format("Expr:(id=%s | value=%s)", 159 ((Call.ExpressionParameter) call.getParmeters().get(parameter)).getParameterId(), 160 ((Call.ExpressionParameter) call.getParmeters().get(parameter)).getParameterValue()); 161 } 162 sb.append(value); 163 } 164 } 165 if (!call.getVariables().isEmpty()) { 166 sb.append(System.getProperty("line.separator")); 167 sb.append("Context Variables"); 168 for (String keyVariable : call.getVariables().keySet()) { 169 sb.append(" | "); 170 sb.append("Key: "); 171 sb.append(keyVariable); 172 sb.append(", Value: "); 173 Object variable = call.getVariables().get(keyVariable); 174 if (variable instanceof Calendar) { 175 sb.append(((Calendar) variable).getTime()); 176 } else { 177 sb.append(variable); 178 } 179 } 180 } 181 printLine(sb.toString()); 182 sb = new StringBuilder(); 183 if (!call.getNested().isEmpty()) { 184 sb.append(System.getProperty("line.separator")); 185 printHeading("start sub chain"); 186 for (Trace trace : call.getNested()) { 187 print(trace); 188 } 189 sb.append(System.getProperty("line.separator")); 190 printHeading("end sub chain"); 191 } 192 printLine(sb.toString()); 193 } catch (IOException e) { 194 log.error("Nuxeo TracePrinter cannot write traces output", e); 195 } 196 } 197 198 public void litePrint(Trace trace) throws IOException { 199 StringBuilder sb = new StringBuilder(); 200 printHeading("chain"); 201 if (trace.error != null) { 202 sb.append(System.getProperty("line.separator")); 203 if (trace.getParent() != null) { 204 sb.append("Parent Chain ID: "); 205 sb.append(trace.getParent().getChainId()); 206 sb.append(System.getProperty("line.separator")); 207 } 208 sb.append("Name: "); 209 sb.append(trace.getChain().getId()); 210 if (trace.getChain().getAliases() != null && trace.getChain().getAliases().length > 0) { 211 sb.append(System.getProperty("line.separator")); 212 sb.append("Aliases: "); 213 sb.append(Arrays.toString(trace.getChain().getAliases())); 214 } 215 sb.append(System.getProperty("line.separator")); 216 sb.append("Exception: "); 217 sb.append(trace.error.getClass().getSimpleName()); 218 sb.append(System.getProperty("line.separator")); 219 sb.append("Caught error: "); 220 sb.append(trace.error.getMessage()); 221 sb.append(System.getProperty("line.separator")); 222 sb.append("Caused by: "); 223 sb.append(trace.error.getCause()); 224 } 225 sb.append(System.getProperty("line.separator")); 226 sb.append("****** Hierarchy calls ******"); 227 printLine(sb.toString()); 228 litePrintCall(trace.operations); 229 writer.flush(); 230 } 231 232 public void litePrintCall(List<Call> calls) throws IOException { 233 StringBuilder stringBuilder = new StringBuilder(); 234 stringBuilder.append(System.getProperty("line.separator")); 235 try { 236 displayOperationTreeCalls(calls, stringBuilder); 237 printLine(stringBuilder.toString()); 238 stringBuilder = new StringBuilder(); 239 for (Call call : calls) { 240 if (!call.getNested().isEmpty()) { 241 stringBuilder.append(System.getProperty("line.separator")); 242 printHeading("start sub chain"); 243 for (Trace trace : call.getNested()) { 244 litePrint(trace); 245 } 246 stringBuilder.append(System.getProperty("line.separator")); 247 printHeading("end sub chain"); 248 } 249 } 250 printLine(stringBuilder.toString()); 251 } catch (IOException e) { 252 log.error("Nuxeo TracePrinter cannot write traces output", e); 253 } 254 } 255 256 private void displayOperationTreeCalls(List<Call> calls, StringBuilder stringBuilder) { 257 String tabs = "\t"; 258 for (Call call : calls) { 259 stringBuilder.append(tabs); 260 stringBuilder.append(call.getType().getType().getName()); 261 stringBuilder.append(System.getProperty("line.separator")); 262 tabs += "\t"; 263 } 264 } 265 266}