001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package org.apache.oozie.coord.input.logic; 020 021import java.util.Date; 022 023import org.apache.commons.jexl2.Expression; 024import org.apache.commons.jexl2.JexlContext; 025import org.apache.commons.jexl2.JexlEngine; 026import org.apache.commons.jexl2.NamespaceResolver; 027import org.apache.commons.lang.StringUtils; 028import org.apache.oozie.CoordinatorActionBean; 029import org.apache.oozie.ErrorCode; 030import org.apache.oozie.command.CommandException; 031import org.apache.oozie.coord.CoordUtils; 032import org.apache.oozie.coord.SyncCoordAction; 033import org.apache.oozie.coord.input.dependency.CoordPullInputDependency; 034import org.apache.oozie.coord.input.dependency.CoordPushInputDependency; 035import org.apache.oozie.util.ELEvaluator; 036import org.apache.oozie.util.LogUtils; 037import org.apache.oozie.util.XLog; 038import org.apache.oozie.util.XmlUtils; 039import org.jdom.Element; 040import org.jdom.JDOMException; 041 042public class CoordInputLogicEvaluatorUtil { 043 044 private CoordinatorActionBean coordAction = null; 045 private XLog log = XLog.getLog(getClass()); 046 047 public CoordInputLogicEvaluatorUtil(CoordinatorActionBean coordAction) { 048 this.coordAction = coordAction; 049 LogUtils.setLogInfo(coordAction); 050 051 } 052 053 public CoordInputLogicEvaluatorUtil() { 054 } 055 056 /** 057 * Check pull missing dependencies. 058 * 059 * @return true, if successful 060 * @throws JDOMException the JDOM exception 061 */ 062 public boolean checkPullMissingDependencies() throws JDOMException { 063 JexlEngine jexl = new OozieJexlEngine(); 064 065 String expression = CoordUtils.getInputLogic(coordAction.getActionXml().toString()); 066 if (StringUtils.isEmpty(expression)) { 067 return true; 068 } 069 Expression e = jexl.createExpression(expression); 070 071 JexlContext jc = new OozieJexlParser(jexl, new CoordInputLogicBuilder(new CoordInputLogicEvaluatorPhaseOne( 072 coordAction, coordAction.getPullInputDependencies()))); 073 CoordInputLogicEvaluatorResult result = (CoordInputLogicEvaluatorResult) e.evaluate(jc); 074 log.debug("Input logic expression for [{0}] and evaluate result is [{1}]", expression, result.getStatus()); 075 076 if (result.isWaiting()) { 077 return false; 078 } 079 return result.isTrue(); 080 } 081 082 /** 083 * Validate input logic. 084 * 085 * @throws JDOMException the JDOM exception 086 * @throws CommandException in case of error 087 */ 088 public void validateInputLogic() throws JDOMException, CommandException { 089 JexlEngine jexl = new OozieJexlEngine(); 090 String expression = CoordUtils.getInputLogic(coordAction.getActionXml().toString()); 091 if (StringUtils.isEmpty(expression)) { 092 return; 093 } 094 Expression e = jexl.createExpression(expression); 095 JexlContext jc = new OozieJexlParser(jexl, new CoordInputLogicBuilder( 096 new CoordInputLogicEvaluatorPhaseValidate(coordAction))); 097 try { 098 Object result = e.evaluate(jc); 099 log.debug("Input logic expression is [{0}] and evaluate result is [{1}]", expression, result); 100 101 } 102 catch (RuntimeException re) { 103 throw new CommandException(ErrorCode.E1028, re.getCause().getMessage()); 104 } 105 106 } 107 108 /** 109 * Get input dependencies. 110 * 111 * @param name the name 112 * @param syncCoordAction the sync coord action 113 * @return the string 114 * @throws JDOMException the JDOM exception 115 */ 116 public String getInputDependencies(String name, SyncCoordAction syncCoordAction) throws JDOMException { 117 JexlEngine jexl = new OozieJexlEngine(); 118 119 CoordinatorActionBean coordAction = new CoordinatorActionBean(); 120 ELEvaluator eval = ELEvaluator.getCurrent(); 121 coordAction.setId(syncCoordAction.getActionId()); 122 Element eJob = XmlUtils.parseXml(eval.getVariable(".actionInputLogic").toString()); 123 String expression = new InputLogicParser().parseWithName(eJob, name); 124 125 Expression e = jexl.createExpression(expression); 126 127 CoordPullInputDependency pull = (CoordPullInputDependency) syncCoordAction.getPullDependencies(); 128 CoordPushInputDependency push = (CoordPushInputDependency) syncCoordAction.getPushDependencies(); 129 130 coordAction.setPushInputDependencies(push); 131 132 coordAction.setPullInputDependencies(pull); 133 134 JexlContext jc = new OozieJexlParser(jexl, new CoordInputLogicBuilder(new CoordInputLogicEvaluatorPhaseThree( 135 coordAction, eval))); 136 CoordInputLogicEvaluatorResult result = (CoordInputLogicEvaluatorResult) e.evaluate(jc); 137 138 if (result == null || !result.isTrue()) { 139 log.debug("Input logic expression for [{0}] is [{1}] and it is not resolved", name, expression); 140 return "${coord:dataIn('" + name + "')}"; 141 } 142 else { 143 log.debug("Input logic expression for [{0}] is [{1}] and evaluate result is [{2}]", name, expression, 144 result.getStatus()); 145 return result.getDataSets(); 146 } 147 148 } 149 150 /** 151 * Check push dependencies. 152 * 153 * @return true, if successful 154 * @throws JDOMException the JDOM exception 155 */ 156 public boolean checkPushDependencies() throws JDOMException { 157 JexlEngine jexl = new OozieJexlEngine(); 158 159 String expression = CoordUtils.getInputLogic(coordAction.getActionXml().toString()); 160 if (StringUtils.isEmpty(expression)) { 161 return true; 162 } 163 164 Expression e = jexl.createExpression(expression); 165 JexlContext jc = new OozieJexlParser(jexl, new CoordInputLogicBuilder(new CoordInputLogicEvaluatorPhaseOne( 166 coordAction, coordAction.getPushInputDependencies()))); 167 CoordInputLogicEvaluatorResult result = (CoordInputLogicEvaluatorResult) e.evaluate(jc); 168 log.debug("Input logic expression for [{0}] and evaluate result is [{1}]", expression, result.getStatus()); 169 170 if (result.isWaiting()) { 171 return false; 172 } 173 return result.isTrue(); 174 } 175 176 /** 177 * Check unresolved. 178 * 179 * @param actualTime the actual time 180 * @return true, if successful 181 * @throws JDOMException the JDOM exception 182 */ 183 public boolean checkUnResolved(Date actualTime) throws JDOMException { 184 JexlEngine jexl = new OozieJexlEngine(); 185 186 String expression = CoordUtils.getInputLogic(coordAction.getActionXml().toString()); 187 if (StringUtils.isEmpty(expression)) { 188 return true; 189 } 190 191 Expression e = jexl.createExpression(expression); 192 JexlContext jc = new OozieJexlParser(jexl, new CoordInputLogicBuilder(new CoordInputLogicEvaluatorPhaseTwo( 193 coordAction, actualTime))); 194 CoordInputLogicEvaluatorResult result = (CoordInputLogicEvaluatorResult) e.evaluate(jc); 195 log.debug("Input logic expression for [{0}] and evaluate result is [{1}]", expression, result.getStatus()); 196 197 if (result.isWaiting()) { 198 return false; 199 } 200 return result.isTrue(); 201 202 } 203 204 public class OozieJexlParser implements JexlContext, NamespaceResolver { 205 private final JexlEngine jexl; 206 private final CoordInputLogicBuilder object; 207 208 @Override 209 public Object resolveNamespace(String name) { 210 return object; 211 } 212 213 public OozieJexlParser(JexlEngine engine, CoordInputLogicBuilder wrapped) { 214 this.jexl = engine; 215 this.object = wrapped; 216 } 217 218 public Object get(String name) { 219 return jexl.getProperty(object, name); 220 } 221 222 public void set(String name, Object value) { 223 jexl.setProperty(object, name, value); 224 } 225 226 public boolean has(String name) { 227 return jexl.getUberspect().getPropertyGet(object, name, null) != null; 228 } 229 230 } 231 232}