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

org.apache.hadoop.hive.ql.hooks.HiveHooks Maven / Gradle / Ivy

There is a newer version: 4.0.1
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

package org.apache.hadoop.hive.ql.hooks;

import com.google.common.annotations.VisibleForTesting;
import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hadoop.hive.ql.exec.Utilities;
import org.apache.hadoop.hive.ql.session.SessionState;
import org.apache.hive.common.util.HiveStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *  Loads and stores different kinds of hooks, provides {@link HiveHooks#addHook(HookContext.HookType, Object)}} to
 *  add hook alone or {@link HiveHooks#getHooks(HookContext.HookType, Class)} to get all hooks
 *  corresponding to the specific hook type.
 */
public class HiveHooks {
  private static final Logger LOG = LoggerFactory.getLogger(HiveHooks.class);
  private final HiveConf conf;
  private final Map typeHooks;
  private SessionState.LogHelper console;

  public HiveHooks(HiveConf conf) {
    this.conf = conf;
    this.typeHooks = new HashMap<>();
  }

  public HiveHooks(HiveConf conf, SessionState.LogHelper console) {
    this(conf);
    this.console = console;
  }

  /**
   * Loads the configured hooks corresponding to the specific hook type.
   * @param type hook type
   */
  @VisibleForTesting
  void loadHooksFromConf(HookContext.HookType type) {
    Hooks hooks = typeHooks.get(type);
    if (hooks == null) {
      typeHooks.put(type, hooks = new Hooks());
      List hookList = hooks.getHooks();
      HiveConf.ConfVars confVar = type.getConfVar();
      Collection csHooks = conf.getStringCollection(confVar.varname);
      try {
        for (String clzName : csHooks) {
          Class hookCls = Class.forName(clzName.trim(), true, Utilities.getSessionSpecifiedClassLoader());
          if (type.getHookClass().isAssignableFrom(hookCls)) {
            Object hookObj = hookCls.newInstance();
            hookList.add(hookObj);
          } else {
            String message = "The class: " + clzName + " should be the subclass of " + type.getHookClass().getName()
                + ", as the type: " + type + " defined";
            logErrorMessage(message);
            throw new ClassCastException(clzName + " cannot be cast to " + type.getHookClass().getName());
          }
        }
      } catch(Exception e) {
        String message = "Error loading hooks(" + confVar + "): " + HiveStringUtils.stringifyException(e);
        throw new RuntimeException(message, e);
      }
    }
  }

  private void logErrorMessage(String message) {
    if (console != null) {
      console.printError(message);
    } else {
      LOG.error(message);
    }
  }

  /**
   * Add the hook corresponding to the specific hook type.
   * @param type The hook type
   * @param hook The hook that will be added
   */
  public void addHook(HookContext.HookType type, Object hook) {
    if (type.getHookClass().isAssignableFrom(hook.getClass())) {
      loadHooksFromConf(type);
      typeHooks.get(type).addHook(hook);
    } else {
      String message = "Error adding hook: " + hook.getClass().getName() + " into type: " + type +
          ", as the hook doesn't implement or extend: " + type.getHookClass().getName();
      logErrorMessage(message);
      throw new IllegalArgumentException(message);
    }
  }

  /**
   * Get all hooks corresponding to the specific hook type.
   * @param type The hook type
   * @param clazz The hook class of returning hooks
   * @param  The generic type of the hooks
   * @return List of hooks
   */
  public  List getHooks(HookContext.HookType type, Class clazz) {
    if (!type.getHookClass().isAssignableFrom(clazz)) {
      String message = "The arg class: " + clazz.getName() + " should be the same as, "
          + "or the subclass of " + type.getHookClass().getName()
          + ", as the type: " + type + " defined";
      logErrorMessage(message);
      throw new IllegalArgumentException(message);
    }
    loadHooksFromConf(type);
    return typeHooks.get(type).getHooks();
  }

  @VisibleForTesting
  List getHooks(HookContext.HookType type, boolean loadFromConf) {
    if (loadFromConf) {
      return getHooks(type);
    }
    return typeHooks.getOrDefault(type, new Hooks()).getHooks();
  }

  public List getHooks(HookContext.HookType type) {
    return getHooks(type, type.getHookClass());
  }

  /**
   * Inner class which keeps track of the hooks that be loaded or added,
   * should not be used outside the class
   * @param  the generic type of hooks
   */
  private class Hooks {
    private List hooks = new ArrayList();
    void addHook(T hook) {
      this.hooks.add(hook);
    }

    List getHooks() {
      return this.hooks;
    }
  }
  
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy