All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.oozie.service.ELService Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (c) 2010 Yahoo! Inc. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License. See accompanying LICENSE file.
 */
package org.apache.oozie.service;

import org.apache.oozie.util.XLog;
import org.apache.oozie.util.ELEvaluator;
import org.apache.oozie.ErrorCode;
import org.apache.hadoop.conf.Configuration;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * The ELService creates {@link ELEvaluator} instances preconfigured with constants and functions defined in the
 * configuration. 

The following configuration parameters control the EL service:

{@link #CONF_CONSTANTS} list * of constant definitions to be available for EL evaluations.

{@link #CONF_FUNCTIONS} list of function definitions * to be available for EL evalations.

Definitions must be separated by a comma, definitions are trimmed.

The * syntax for a constant definition is PREFIX:NAME=CLASS_NAME#CONSTANT_NAME.

The syntax for a constant * definition is PREFIX:NAME=CLASS_NAME#METHOD_NAME. */ public class ELService implements Service { public static final String CONF_PREFIX = Service.CONF_PREFIX + "ELService."; public static final String CONF_CONSTANTS = CONF_PREFIX + "constants."; public static final String CONF_EXT_CONSTANTS = CONF_PREFIX + "ext.constants."; public static final String CONF_FUNCTIONS = CONF_PREFIX + "functions."; public static final String CONF_EXT_FUNCTIONS = CONF_PREFIX + "ext.functions."; public static final String CONF_GROUPS = CONF_PREFIX + "groups"; private final XLog log = XLog.getLog(getClass()); //, private HashMap> constants; //, private HashMap> functions; private static class ELConstant { private String name; private Object value; private ELConstant(String prefix, String name, Object value) { if (prefix.length() > 0) { name = prefix + ":" + name; } this.name = name; this.value = value; } } private static class ELFunction { private String prefix; private String name; private Method method; private ELFunction(String prefix, String name, Method method) { this.prefix = prefix; this.name = name; this.method = method; } } private List extractConstants(Configuration conf, String key) throws ServiceException { List list = new ArrayList(); if (conf.get(key, "").trim().length() > 0) { for (String function : conf.getStrings(key)) { String[] parts = parseDefinition(function); list.add(new ELConstant(parts[0], parts[1], findConstant(parts[2], parts[3]))); log.trace("Registered prefix:constant[{0}:{1}] for class#field[{2}#{3}]", (Object[]) parts); } } return list; } private List extractFunctions(Configuration conf, String key) throws ServiceException { List list = new ArrayList(); if (conf.get(key, "").trim().length() > 0) { for (String function : conf.getStrings(key)) { String[] parts = parseDefinition(function); list.add(new ELFunction(parts[0], parts[1], findMethod(parts[2], parts[3]))); log.trace("Registered prefix:constant[{0}:{1}] for class#field[{2}#{3}]", (Object[]) parts); } } return list; } /** * Initialize the EL service. * * @param services services instance. * @throws ServiceException thrown if the EL service could not be initialized. */ @Override public synchronized void init(Services services) throws ServiceException { log.trace("Constants and functions registration"); constants = new HashMap>(); functions = new HashMap>(); //Get the list of group names from configuration file // defined in the property tag: oozie.service.ELSerice.groups //String []groupList = services.getConf().get(CONF_GROUPS, "").trim().split(","); String[] groupList = services.getConf().getStrings(CONF_GROUPS, ""); //For each group, collect the required functions and constants // and store it into HashMap for (String group : groupList) { List tmpConstants = new ArrayList(); tmpConstants.addAll(extractConstants(services.getConf(), CONF_CONSTANTS + group)); tmpConstants.addAll(extractConstants(services.getConf(), CONF_EXT_CONSTANTS + group)); constants.put(group, tmpConstants); List tmpFunctions = new ArrayList(); tmpFunctions.addAll(extractFunctions(services.getConf(), CONF_FUNCTIONS + group)); tmpFunctions.addAll(extractFunctions(services.getConf(), CONF_EXT_FUNCTIONS + group)); functions.put(group, tmpFunctions); } } /** * Destroy the EL service. */ @Override public void destroy() { constants = null; functions = null; } /** * Return the public interface for EL service. * * @return {@link ELService}. */ @Override public Class getInterface() { return ELService.class; } /** * Return an {@link ELEvaluator} pre-configured with the constants and functions for the specific group of * EL-functions and variables defined in the configuration. If the group name doesn't exist, * IllegalArgumentException is thrown * * @param group: Name of the group of required EL Evaluator. * @return a preconfigured {@link ELEvaluator}. */ public ELEvaluator createEvaluator(String group) { ELEvaluator.Context context = new ELEvaluator.Context(); boolean groupDefined = false; if (constants.containsKey(group)) { for (ELConstant constant : constants.get(group)) { context.setVariable(constant.name, constant.value); } groupDefined = true; } if (functions.containsKey(group)) { for (ELFunction function : functions.get(group)) { context.addFunction(function.prefix, function.name, function.method); } groupDefined = true; } if (groupDefined == false) { throw new IllegalArgumentException("Group " + group + " is not defined"); } return new ELEvaluator(context); } private static String[] parseDefinition(String str) throws ServiceException { try { str = str.trim(); if (!str.contains(":")) { str = ":" + str; } String[] parts = str.split(":"); String prefix = parts[0]; parts = parts[1].split("="); String name = parts[0]; parts = parts[1].split("#"); String klass = parts[0]; String method = parts[1]; return new String[]{prefix, name, klass, method}; } catch (Exception ex) { throw new ServiceException(ErrorCode.E0110, str, ex.getMessage(), ex); } } public static Method findMethod(String className, String methodName) throws ServiceException { Method method = null; try { Class klass = Thread.currentThread().getContextClassLoader().loadClass(className); for (Method m : klass.getMethods()) { if (m.getName().equals(methodName)) { method = m; break; } } if (method == null) { throw new ServiceException(ErrorCode.E0111, className, methodName); } if ((method.getModifiers() & (Modifier.PUBLIC | Modifier.STATIC)) != (Modifier.PUBLIC | Modifier.STATIC)) { throw new ServiceException(ErrorCode.E0112, className, methodName); } } catch (ClassNotFoundException ex) { throw new ServiceException(ErrorCode.E0113, className); } return method; } public static Object findConstant(String className, String constantName) throws ServiceException { try { Class klass = Thread.currentThread().getContextClassLoader().loadClass(className); Field field = klass.getField(constantName); if ((field.getModifiers() & (Modifier.PUBLIC | Modifier.STATIC)) != (Modifier.PUBLIC | Modifier.STATIC)) { throw new ServiceException(ErrorCode.E0114, className, constantName); } return field.get(null); } catch (IllegalAccessException ex) { throw new IllegalArgumentException(ex); } catch (NoSuchFieldException ex) { throw new ServiceException(ErrorCode.E0115, className, constantName); } catch (ClassNotFoundException ex) { throw new ServiceException(ErrorCode.E0113, className); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy