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.action.hadoop; 020 021import java.util.List; 022 023import org.apache.hadoop.conf.Configuration; 024import org.apache.hadoop.fs.Path; 025import org.apache.oozie.action.ActionExecutorException; 026import org.jdom.Element; 027import org.jdom.Namespace; 028 029public class ShellActionExecutor extends JavaActionExecutor { 030 031 /** 032 * Config property name to set the child environment 033 */ 034 public String OOZIE_LAUNCHER_CHILD_ENV = "mapred.child.env"; 035 036 public ShellActionExecutor() { 037 super("shell"); 038 } 039 040 @SuppressWarnings("rawtypes") 041 @Override 042 public List<Class> getLauncherClasses() { 043 return null; 044 } 045 046 @Override 047 protected String getLauncherMain(Configuration launcherConf, Element actionXml) { 048 return launcherConf.get(LauncherMapper.CONF_OOZIE_ACTION_MAIN_CLASS, ShellMain.class.getName()); 049 } 050 051 @SuppressWarnings("unchecked") 052 @Override 053 Configuration setupActionConf(Configuration actionConf, Context context, Element actionXml, Path appPath) 054 throws ActionExecutorException { 055 super.setupActionConf(actionConf, context, actionXml, appPath); 056 Namespace ns = actionXml.getNamespace(); 057 058 String exec = actionXml.getChild("exec", ns).getTextTrim(); 059 String execName = new Path(exec).getName(); 060 actionConf.set(ShellMain.CONF_OOZIE_SHELL_EXEC, execName); 061 062 // Setting Shell command's arguments 063 setListInConf("argument", actionXml, actionConf, ShellMain.CONF_OOZIE_SHELL_ARGS, false); 064 // Setting Shell command's environment variable key=value 065 setListInConf("env-var", actionXml, actionConf, ShellMain.CONF_OOZIE_SHELL_ENVS, true); 066 067 // Setting capture output flag 068 actionConf.setBoolean(ShellMain.CONF_OOZIE_SHELL_CAPTURE_OUTPUT, 069 actionXml.getChild("capture-output", ns) != null); 070 071 return actionConf; 072 } 073 074 /** 075 * This method read a list of tag from an XML element and set the 076 * Configuration accordingly 077 * 078 * @param tag 079 * @param actionXml 080 * @param actionConf 081 * @param key 082 * @param checkKeyValue 083 * @throws ActionExecutorException 084 */ 085 protected void setListInConf(String tag, Element actionXml, Configuration actionConf, String key, 086 boolean checkKeyValue) throws ActionExecutorException { 087 String[] strTagValue = null; 088 Namespace ns = actionXml.getNamespace(); 089 List<Element> eTags = actionXml.getChildren(tag, ns); 090 if (eTags != null && eTags.size() > 0) { 091 strTagValue = new String[eTags.size()]; 092 for (int i = 0; i < eTags.size(); i++) { 093 strTagValue[i] = eTags.get(i).getTextTrim(); 094 if (checkKeyValue) { 095 checkPair(strTagValue[i]); 096 } 097 } 098 } 099 MapReduceMain.setStrings(actionConf, key, strTagValue); 100 } 101 102 /** 103 * Check if the key=value pair is appropriately formatted 104 * @param pair 105 * @throws ActionExecutorException 106 */ 107 private void checkPair(String pair) throws ActionExecutorException { 108 String[] varValue = pair.split("="); 109 if (varValue == null || varValue.length <= 1) { 110 throw new ActionExecutorException(ActionExecutorException.ErrorType.FAILED, "JA010", 111 "Wrong ENV format [{0}] in <env-var> , key=value format expected ", pair); 112 } 113 } 114 115 @Override 116 protected Configuration setupLauncherConf(Configuration conf, Element actionXml, Path appPath, Context context) 117 throws ActionExecutorException { 118 super.setupLauncherConf(conf, actionXml, appPath, context); 119 conf.setBoolean("mapreduce.job.complete.cancel.delegation.tokens", true); 120 addDefaultChildEnv(conf); 121 return conf; 122 } 123 124 /** 125 * This method sets the PATH to current working directory for the launched 126 * map task from where shell command will run. 127 * 128 * @param conf 129 */ 130 protected void addDefaultChildEnv(Configuration conf) { 131 String envValues = "PATH=.:$PATH"; 132 updateProperty(conf, OOZIE_LAUNCHER_CHILD_ENV, envValues); 133 } 134 135 /** 136 * Utility method to append the new value to any property. 137 * 138 * @param conf 139 * @param propertyName 140 * @param appendValue 141 */ 142 private void updateProperty(Configuration conf, String propertyName, String appendValue) { 143 if (conf != null) { 144 String val = conf.get(propertyName, ""); 145 if (val.length() > 0) { 146 val += ","; 147 } 148 val += appendValue; 149 conf.set(propertyName, val); 150 LOG.debug("action conf is updated with default value for property " + propertyName + ", old value :" 151 + conf.get(propertyName, "") + ", new value :" + val); 152 } 153 } 154 155}