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 */ 018 019package org.nuxeo.ecm.automation.core.trace; 020 021import java.util.LinkedList; 022import java.util.Stack; 023 024import org.nuxeo.ecm.automation.OperationCallback; 025import org.nuxeo.ecm.automation.OperationException; 026import org.nuxeo.ecm.automation.OperationType; 027 028/** 029 * Automation Abstract tracer recording all automation execution traces. 030 * 031 * @since 5.9.1 032 */ 033public abstract class BasedTracer implements OperationCallback { 034 035 protected final TracerFactory factory; 036 037 protected final LinkedList<Call> calls = new LinkedList<Call>(); 038 039 protected Stack<Trace> callingStacks = new Stack<Trace>(); 040 041 protected Call parent; 042 043 protected OperationType chain; 044 045 protected Trace trace; 046 047 protected Boolean printable; 048 049 protected BasedTracer(TracerFactory factory, Boolean printable) { 050 this.factory = factory; 051 this.printable = printable; 052 } 053 054 protected void pushContext(OperationType newChain) { 055 if (chain != null) { 056 callingStacks.push(new Trace(parent, chain, calls)); 057 parent = calls.isEmpty() ? null : calls.getLast(); 058 calls.clear(); 059 } 060 chain = newChain; 061 } 062 063 protected void popContext() { 064 calls.clear(); 065 if (callingStacks.isEmpty()) { 066 parent = null; 067 chain = null; 068 return; 069 } 070 Trace trace = callingStacks.pop(); 071 parent = trace.parent; 072 chain = trace.chain; 073 calls.addAll(trace.operations); 074 } 075 076 protected void saveTrace(Trace popped) { 077 if (parent == null) { 078 trace = popped; 079 chain = null; 080 calls.clear(); 081 factory.onTrace(popped); 082 } else { 083 parent.nested.add(popped); 084 popContext(); 085 } 086 } 087 088 @Override 089 public void onChain(OperationType chain) { 090 pushContext(chain); 091 } 092 093 @Override 094 public void onOutput(Object output) { 095 saveTrace(new Trace(parent, chain, calls, output)); 096 } 097 098 @Override 099 public void onError(OperationException error) { 100 saveTrace(new Trace(parent, chain, calls, error)); 101 } 102 103 @Override 104 public Trace getTrace() { 105 return trace; 106 } 107 108 @Override 109 public String getFormattedText() { 110 return printable ? trace.getFormattedText() : ""; 111 } 112}