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 package org.apache.oozie.util; 019 020 import java.util.Iterator; 021 import java.util.regex.Matcher; 022 import java.util.regex.Pattern; 023 import org.apache.oozie.ErrorCode; 024 import org.jdom.Element; 025 import org.jdom.Namespace; 026 027 import org.apache.hadoop.conf.Configuration; 028 029 /** 030 * Utility class to parse and verify the <parameters> section in a workflow or coordinator job 031 */ 032 public abstract class ParameterVerifier 033 { 034 private static final Pattern nsVersionPattern = Pattern.compile("uri:oozie:(workflow|coordinator|bundle):(\\d+.\\d+)"); 035 036 private static final double workflowMinVersion = 0.4; 037 private static final double coordinatorMinVersion = 0.4; 038 private static final double bundleMinVersion = 0.2; 039 040 /** 041 * Verify the parameters section (if supported in the schema) 042 * 043 * @param conf The job configuration 044 * @param rootElement The root element of the workflow, coordinator, or bundle definition 045 * @throws ParameterVerifierException If required parameters are not defined and have no default values, or if a name is empty 046 */ 047 public static void verifyParameters(Configuration conf, Element rootElement) throws ParameterVerifierException { 048 ParamChecker.notNull(conf, "conf"); 049 if (rootElement == null) { 050 return; 051 } 052 053 if (supportsParameters(rootElement.getNamespaceURI())) { 054 Element params = rootElement.getChild("parameters", rootElement.getNamespace()); 055 if (params != null) { 056 int numMissing = 0; 057 StringBuilder missingParameters = new StringBuilder(); 058 Namespace paramsNs = params.getNamespace(); 059 Iterator<Element> it = params.getChildren("property", paramsNs).iterator(); 060 while (it.hasNext()) { 061 Element prop = it.next(); 062 String name = prop.getChildTextTrim("name", paramsNs); 063 if (name != null) { 064 if (name.isEmpty()) { 065 throw new ParameterVerifierException(ErrorCode.E0739); 066 } 067 if (conf.get(name) == null) { 068 String defaultValue = prop.getChildTextTrim("value", paramsNs); 069 if (defaultValue != null) { 070 conf.set(name, defaultValue); 071 } else { 072 missingParameters.append(name); 073 missingParameters.append(", "); 074 numMissing++; 075 } 076 } 077 } 078 } 079 if (numMissing > 0) { 080 missingParameters.setLength(missingParameters.length() - 2); //remove the trailing ", " 081 throw new ParameterVerifierException(ErrorCode.E0738, numMissing, missingParameters.toString()); 082 } 083 } else { 084 // Log a warning when the <parameters> section is missing 085 XLog.getLog(ParameterVerifier.class).warn("The application does not define formal parameters in its XML " 086 + "definition"); 087 } 088 } 089 } 090 091 static boolean supportsParameters(String namespaceURI) { 092 boolean supports = false; 093 Matcher m = nsVersionPattern.matcher(namespaceURI); 094 if (m.matches() && m.groupCount() == 2) { 095 String type = m.group(1); 096 double ver = Double.parseDouble(m.group(2)); 097 supports = ((type.equals("workflow") && ver >= workflowMinVersion) || 098 (type.equals("coordinator") && ver >= coordinatorMinVersion) || 099 (type.equals("bundle") && ver >= bundleMinVersion)); 100 } 101 return supports; 102 } 103 }