001/* 002 * (C) Copyright 2013 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * vpasquier <vpasquier@nuxeo.com> 018 * slacoin <slacoin@nuxeo.com> 019 */ 020package org.nuxeo.ecm.automation.core.trace; 021 022import java.util.Arrays; 023import java.util.HashMap; 024import java.util.LinkedList; 025import java.util.List; 026import java.util.Map; 027 028import org.apache.commons.logging.Log; 029import org.apache.commons.logging.LogFactory; 030import org.nuxeo.ecm.automation.OperationContext; 031import org.nuxeo.ecm.automation.OperationType; 032import org.nuxeo.ecm.automation.core.impl.InvokableMethod; 033import org.nuxeo.ecm.automation.core.scripting.Expression; 034 035/** 036 * @since 5.7.3 037 */ 038public class Call { 039 040 private static final Log log = LogFactory.getLog(Call.class); 041 042 /** 043 * Black listing of mvel expressions which should not be evaluated by the Automation traces for debugging purpose 044 * 045 * @since 8.1 046 */ 047 public static final String[] MVEL_BLACK_LIST_EXPR = new String[] { "getNextId" }; 048 049 protected final String chainId; 050 051 protected final String aliases; 052 053 protected final OperationType type; 054 055 protected final List<Trace> nested = new LinkedList<Trace>(); 056 057 protected final Details details; 058 059 060 protected Call(OperationType chain, OperationType op, Details details) { 061 type = op; 062 chainId = chain.getId(); 063 aliases = Arrays.toString(chain.getAliases()); 064 this.details = details; 065 } 066 067 public Call(OperationType chain, OperationType op) { 068 this(chain, op, new Details()); 069 } 070 071 public Call(OperationType chain, OperationContext context, OperationType type, InvokableMethod method, 072 Map<String, Object> parms) { 073 this(chain, type, new Details(context, method, parms)); 074 } 075 076 protected static class Details { 077 078 protected final Map<String, Object> parameters = new HashMap<>(); 079 080 protected final Map<String, Object> variables = new HashMap<>(); 081 082 protected final InvokableMethod method; 083 084 protected final Object input; 085 086 protected Object output; 087 088 protected Details() { 089 method = null; 090 input = null; 091 } 092 093 protected Details(OperationContext context, InvokableMethod method, Map<String, Object> parms) { 094 this.method = method; 095 input = context.getInput(); 096 variables.putAll(context); 097 parms.forEach(new Evaluator(context)::inject); 098 } 099 100 protected class Evaluator { 101 102 protected final OperationContext context; 103 104 protected Evaluator(OperationContext context) { 105 this.context = context; 106 } 107 108 protected void inject(String key, Object value) { 109 if (!(value instanceof Expression)) { 110 parameters.put(key, value); 111 return; 112 } 113 Expression exp = (Expression) value; 114 for (String mvelExpr : MVEL_BLACK_LIST_EXPR) { 115 if (exp.getExpr().contains(mvelExpr)) { 116 parameters.put(key, new ExpressionParameter(key, 117 String.format("Cannot be evaluated in traces when using '%s' expression", mvelExpr))); 118 return; 119 } 120 } 121 try { 122 parameters.put(key, new ExpressionParameter(key, exp.eval(context))); 123 return; 124 } catch (RuntimeException e) { 125 log.warn("Cannot evaluate mvel expression for parameter: " + key, e); 126 } 127 } 128 } 129 130 131 } 132 133 /** 134 * @since 7.1 135 */ 136 public static class ExpressionParameter { 137 138 protected final String parameterId; 139 140 protected final Object parameterValue; 141 142 public ExpressionParameter(String parameterId, Object parameterValue) { 143 this.parameterId = parameterId; 144 this.parameterValue = parameterValue; 145 } 146 147 public Object getParameterValue() { 148 return parameterValue; 149 } 150 151 public String getParameterId() { 152 153 return parameterId; 154 } 155 } 156 157 public OperationType getType() { 158 return type; 159 } 160 161 public InvokableMethod getMethod() { 162 return details.method; 163 } 164 165 public Map<String, Object> getParameters() { 166 return details.parameters; 167 } 168 169 public Map<String, Object> getVariables() { 170 return details.variables; 171 } 172 173 public Object getInput() { 174 return details.input; 175 } 176 177 public Object getOutput() { 178 return details.output; 179 } 180 181 public List<Trace> getNested() { 182 return nested; 183 } 184 185 public String getChainId() { 186 return chainId; 187 } 188 189 public String getAliases() { 190 return aliases; 191 } 192 193}