| /* |
| * 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.metadata; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| import org.apache.hadoop.fs.Path; |
| import org.apache.hadoop.hive.ql.parse.Quotation; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| import org.apache.hadoop.conf.Configuration; |
| import org.apache.hadoop.hive.common.JavaUtils; |
| import org.apache.hadoop.hive.conf.HiveConf; |
| import org.apache.hadoop.hive.ql.exec.Utilities; |
| import org.apache.hadoop.hive.ql.exec.tez.TezContext; |
| import org.apache.hadoop.hive.ql.security.HadoopDefaultAuthenticator; |
| import org.apache.hadoop.hive.ql.security.HiveAuthenticationProvider; |
| import org.apache.hadoop.hive.ql.security.authorization.DefaultHiveAuthorizationProvider; |
| import org.apache.hadoop.hive.ql.security.authorization.HiveAuthorizationProvider; |
| import org.apache.hadoop.hive.ql.security.authorization.HiveMetastoreAuthorizationProvider; |
| import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveAuthorizerFactory; |
| import org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.SQLStdHiveAuthorizerFactory; |
| import org.apache.hadoop.io.Text; |
| import org.apache.hadoop.util.ReflectionUtils; |
| import org.apache.hadoop.util.StringUtils; |
| |
| /** |
| * General collection of helper functions. |
| * |
| */ |
| public final class HiveUtils { |
| |
| public static String escapeString(String str) { |
| int length = str.length(); |
| StringBuilder escape = new StringBuilder(length + 16); |
| |
| for (int i = 0; i < length; ++i) { |
| char c = str.charAt(i); |
| switch (c) { |
| case '"': |
| case '\\': |
| escape.append('\\'); |
| escape.append(c); |
| break; |
| case '\b': |
| escape.append('\\'); |
| escape.append('b'); |
| break; |
| case '\f': |
| escape.append('\\'); |
| escape.append('f'); |
| break; |
| case '\n': |
| escape.append('\\'); |
| escape.append('n'); |
| break; |
| case '\r': |
| escape.append('\\'); |
| escape.append('r'); |
| break; |
| case '\t': |
| escape.append('\\'); |
| escape.append('t'); |
| break; |
| default: |
| // Control characeters! According to JSON RFC u0020 |
| if (c < ' ') { |
| String hex = Integer.toHexString(c); |
| escape.append('\\'); |
| escape.append('u'); |
| for (int j = 4; j > hex.length(); --j) { |
| escape.append('0'); |
| } |
| escape.append(hex); |
| } else { |
| escape.append(c); |
| } |
| break; |
| } |
| } |
| return (escape.toString()); |
| } |
| |
| static final byte[] escapeEscapeBytes = "\\\\".getBytes();; |
| static final byte[] escapeUnescapeBytes = "\\".getBytes(); |
| static final byte[] newLineEscapeBytes = "\\n".getBytes();; |
| static final byte[] newLineUnescapeBytes = "\n".getBytes(); |
| static final byte[] carriageReturnEscapeBytes = "\\r".getBytes();; |
| static final byte[] carriageReturnUnescapeBytes = "\r".getBytes(); |
| static final byte[] tabEscapeBytes = "\\t".getBytes();; |
| static final byte[] tabUnescapeBytes = "\t".getBytes(); |
| static final byte[] ctrlABytes = "\u0001".getBytes(); |
| static final Pattern BRANCH = Pattern.compile("branch_(.*)"); |
| |
| |
| public static final Logger LOG = LoggerFactory.getLogger(HiveUtils.class); |
| |
| |
| public static Text escapeText(Text text) { |
| int length = text.getLength(); |
| byte[] textBytes = text.getBytes(); |
| |
| Text escape = new Text(text); |
| escape.clear(); |
| |
| for (int i = 0; i < length; ++i) { |
| int c = text.charAt(i); |
| byte[] escaped; |
| int start; |
| int len; |
| |
| switch (c) { |
| |
| case '\\': |
| escaped = escapeEscapeBytes; |
| start = 0; |
| len = escaped.length; |
| break; |
| |
| case '\n': |
| escaped = newLineEscapeBytes; |
| start = 0; |
| len = escaped.length; |
| break; |
| |
| case '\r': |
| escaped = carriageReturnEscapeBytes; |
| start = 0; |
| len = escaped.length; |
| break; |
| |
| case '\t': |
| escaped = tabEscapeBytes; |
| start = 0; |
| len = escaped.length; |
| break; |
| |
| case '\u0001': |
| escaped = tabUnescapeBytes; |
| start = 0; |
| len = escaped.length; |
| break; |
| |
| default: |
| escaped = textBytes; |
| start = i; |
| len = 1; |
| break; |
| } |
| |
| escape.append(escaped, start, len); |
| |
| } |
| return escape; |
| } |
| |
| public static int unescapeText(Text text) { |
| Text escape = new Text(text); |
| text.clear(); |
| |
| int length = escape.getLength(); |
| byte[] textBytes = escape.getBytes(); |
| |
| boolean hadSlash = false; |
| for (int i = 0; i < length; ++i) { |
| int c = escape.charAt(i); |
| switch (c) { |
| case '\\': |
| if (hadSlash) { |
| text.append(textBytes, i, 1); |
| hadSlash = false; |
| } |
| else { |
| hadSlash = true; |
| } |
| break; |
| case 'n': |
| if (hadSlash) { |
| byte[] newLine = newLineUnescapeBytes; |
| text.append(newLine, 0, newLine.length); |
| } |
| else { |
| text.append(textBytes, i, 1); |
| } |
| hadSlash = false; |
| break; |
| case 'r': |
| if (hadSlash) { |
| byte[] carriageReturn = carriageReturnUnescapeBytes; |
| text.append(carriageReturn, 0, carriageReturn.length); |
| } |
| else { |
| text.append(textBytes, i, 1); |
| } |
| hadSlash = false; |
| break; |
| |
| case 't': |
| if (hadSlash) { |
| byte[] tab = tabUnescapeBytes; |
| text.append(tab, 0, tab.length); |
| } |
| else { |
| text.append(textBytes, i, 1); |
| } |
| hadSlash = false; |
| break; |
| |
| case '\t': |
| if (hadSlash) { |
| text.append(textBytes, i-1, 1); |
| hadSlash = false; |
| } |
| |
| byte[] ctrlA = ctrlABytes; |
| text.append(ctrlA, 0, ctrlA.length); |
| break; |
| |
| default: |
| if (hadSlash) { |
| text.append(textBytes, i-1, 1); |
| hadSlash = false; |
| } |
| |
| text.append(textBytes, i, 1); |
| break; |
| } |
| } |
| return text.getLength(); |
| } |
| |
| public static String lightEscapeString(String str) { |
| int length = str.length(); |
| StringBuilder escape = new StringBuilder(length + 16); |
| |
| for (int i = 0; i < length; ++i) { |
| char c = str.charAt(i); |
| switch (c) { |
| case '\n': |
| escape.append('\\'); |
| escape.append('n'); |
| break; |
| case '\r': |
| escape.append('\\'); |
| escape.append('r'); |
| break; |
| case '\t': |
| escape.append('\\'); |
| escape.append('t'); |
| break; |
| default: |
| escape.append(c); |
| break; |
| } |
| } |
| return (escape.toString()); |
| } |
| |
| /** |
| * Regenerate an identifier as part of unparsing it back to SQL text. |
| */ |
| public static String unparseIdentifier(String identifier, Configuration conf) { |
| // We support arbitrary characters in |
| // identifiers, then we need to escape any backticks |
| // in identifier by doubling them up. |
| Quotation quotation = Quotation.from(conf); |
| if (quotation != Quotation.NONE) { |
| identifier = identifier.replaceAll("`", "``"); |
| } |
| return "`" + identifier + "`"; |
| } |
| |
| public static HiveStorageHandler getStorageHandler( |
| Configuration conf, String className) throws HiveException { |
| |
| if (className == null) { |
| return null; |
| } |
| try { |
| Class<? extends HiveStorageHandler> handlerClass = |
| (Class<? extends HiveStorageHandler>) |
| Class.forName(className, true, Utilities.getSessionSpecifiedClassLoader()); |
| HiveStorageHandler storageHandler = ReflectionUtils.newInstance(handlerClass, conf); |
| return storageHandler; |
| } catch (ClassNotFoundException e) { |
| throw new HiveException("Error in loading storage handler." |
| + e.getMessage(), e); |
| } |
| } |
| |
| private HiveUtils() { |
| // prevent instantiation |
| } |
| |
| @SuppressWarnings("unchecked") |
| public static List<HiveMetastoreAuthorizationProvider> getMetaStoreAuthorizeProviderManagers( |
| Configuration conf, HiveConf.ConfVars authorizationProviderConfKey, |
| HiveAuthenticationProvider authenticator) throws HiveException { |
| |
| String clsStrs = HiveConf.getVar(conf, authorizationProviderConfKey); |
| if(clsStrs == null){ |
| return null; |
| } |
| List<HiveMetastoreAuthorizationProvider> authProviders = new ArrayList<HiveMetastoreAuthorizationProvider>(); |
| for (String clsStr : clsStrs.trim().split(",")) { |
| LOG.info("Adding metastore authorization provider: " + clsStr); |
| authProviders.add((HiveMetastoreAuthorizationProvider) getAuthorizeProviderManager(conf, |
| clsStr, authenticator, false)); |
| } |
| return authProviders; |
| } |
| |
| /** |
| * Create a new instance of HiveAuthorizationProvider |
| * @param conf |
| * @param authzClassName - authorization provider class name |
| * @param authenticator |
| * @param nullIfOtherClass - return null if configuration |
| * does not point to a HiveAuthorizationProvider subclass |
| * @return new instance of HiveAuthorizationProvider |
| * @throws HiveException |
| */ |
| @SuppressWarnings("unchecked") |
| public static HiveAuthorizationProvider getAuthorizeProviderManager( |
| Configuration conf, String authzClassName, |
| HiveAuthenticationProvider authenticator, boolean nullIfOtherClass) throws HiveException { |
| |
| HiveAuthorizationProvider ret = null; |
| try { |
| Class<? extends HiveAuthorizationProvider> cls = null; |
| if (authzClassName == null || authzClassName.trim().equals("")) { |
| cls = DefaultHiveAuthorizationProvider.class; |
| } else { |
| Class<?> configClass = Class.forName(authzClassName, true, JavaUtils.getClassLoader()); |
| if(nullIfOtherClass && !HiveAuthorizationProvider.class.isAssignableFrom(configClass) ){ |
| return null; |
| } |
| cls = (Class<? extends HiveAuthorizationProvider>)configClass; |
| } |
| if (cls != null) { |
| ret = ReflectionUtils.newInstance(cls, conf); |
| } |
| } catch (Exception e) { |
| throw new HiveException(e); |
| } |
| ret.setAuthenticator(authenticator); |
| return ret; |
| } |
| |
| |
| /** |
| * Return HiveAuthorizerFactory used by new authorization plugin interface. |
| * @param conf |
| * @param authorizationProviderConfKey |
| * @return |
| * @throws HiveException if HiveAuthorizerFactory specified in configuration could not |
| */ |
| public static HiveAuthorizerFactory getAuthorizerFactory( |
| Configuration conf, HiveConf.ConfVars authorizationProviderConfKey) |
| throws HiveException { |
| |
| Class<? extends HiveAuthorizerFactory> cls = conf.getClass(authorizationProviderConfKey.varname, |
| SQLStdHiveAuthorizerFactory.class, HiveAuthorizerFactory.class); |
| |
| if(cls == null){ |
| //should not happen as default value is set |
| throw new HiveException("Configuration value " + authorizationProviderConfKey.varname |
| + " is not set to valid HiveAuthorizerFactory subclass" ); |
| } |
| |
| HiveAuthorizerFactory authFactory = ReflectionUtils.newInstance(cls, conf); |
| return authFactory; |
| } |
| |
| @SuppressWarnings("unchecked") |
| public static HiveAuthenticationProvider getAuthenticator( |
| Configuration conf, HiveConf.ConfVars authenticatorConfKey |
| ) throws HiveException { |
| |
| String clsStr = HiveConf.getVar(conf, authenticatorConfKey); |
| |
| HiveAuthenticationProvider ret = null; |
| try { |
| Class<? extends HiveAuthenticationProvider> cls = null; |
| if (clsStr == null || clsStr.trim().equals("")) { |
| cls = HadoopDefaultAuthenticator.class; |
| } else { |
| cls = (Class<? extends HiveAuthenticationProvider>) Class.forName( |
| clsStr, true, JavaUtils.getClassLoader()); |
| } |
| if (cls != null) { |
| ret = ReflectionUtils.newInstance(cls, conf); |
| } |
| } catch (Exception e) { |
| throw new HiveException(e); |
| } |
| return ret; |
| } |
| |
| public static String getLocalDirList(Configuration conf) { |
| if (HiveConf.getVar(conf, HiveConf.ConfVars.HIVE_EXECUTION_ENGINE).equals("tez")) { |
| TezContext tezContext = (TezContext) TezContext.get(); |
| if (tezContext != null && tezContext.getTezProcessorContext() != null) { |
| return StringUtils.arrayToString(tezContext.getTezProcessorContext().getWorkDirs()); |
| } // otherwise fall back to return null, i.e. to use local tmp dir only |
| } |
| |
| return null; |
| } |
| |
| public static String getReplPolicy(String dbName) { |
| if ((dbName == null) || (dbName.isEmpty())) { |
| return "*.*"; |
| } else { |
| return dbName.toLowerCase() + ".*"; |
| } |
| } |
| |
| public static Path getDumpPath(Path root, String dbName, String tableName) { |
| assert (dbName != null); |
| if ((tableName != null) && (!tableName.isEmpty())) { |
| return new Path(root, dbName + "." + tableName); |
| } |
| return new Path(root, dbName); |
| } |
| |
| public static String getTableBranch(String branchName) { |
| Matcher branch = BRANCH.matcher(branchName); |
| if (branch.matches()) { |
| return branch.group(1); |
| } |
| return null; |
| } |
| } |