Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ private int createTemporaryFunction() {
FunctionUtils.addFunctionResources(resources);

Class<?> udfClass = getUdfClass();
if (!validateIfBlockedUDF(udfClass)) {
return 1;
}

FunctionInfo registered = FunctionRegistry.registerTemporaryUDF(desc.getName(), udfClass, resources);
if (registered != null) {
return 0;
Expand All @@ -79,8 +83,9 @@ private int createTemporaryFunction() {
"FAILED: Class " + desc.getClassName() + " does not implement UDF, GenericUDF, or UDAF");
return 1;
}
} catch (HiveException e) {
context.getConsole().printError("FAILED: " + e.toString());
}
catch (HiveException e) {
context.getConsole().printError("FAILED: Create function: " + e.toString());
LOG.info("create function: ", e);
return 1;
} catch (ClassNotFoundException e) {
Expand All @@ -90,6 +95,23 @@ private int createTemporaryFunction() {
}
}

/**
* Validates if the function being created is from blacklisted UDF.
*
* @return `true` if the UDF is valid and not blocked, `false` otherwise.
*/
private boolean validateIfBlockedUDF(Class<?> udfClass) {
try {
// Function creation with blocked UDFs will fail with SemanticException here
FunctionRegistry.getFunctionInfo(FunctionUtils.getFuncNameFromClass(udfClass));
return true;
} catch (SemanticException e) {
// Log and print error if the UDF is blocked
context.getConsole().printError("FAILED: Create function: " + e.toString());
LOG.info("create function: ", e);
return false;
}
}
private Class<?> getUdfClass() throws ClassNotFoundException {
// get the session specified class loader from SessionState
ClassLoader classLoader = Utilities.getSessionSpecifiedClassLoader();
Expand Down Expand Up @@ -120,7 +142,6 @@ private int createPermanentFunction() throws HiveException, IOException {
if (!addToMetastoreSuccess) {
return 1;
}

return 0;
}

Expand Down Expand Up @@ -172,8 +193,15 @@ private boolean registerFunction(String registeredName) throws SemanticException
HiveConf oldConf = SessionState.get().getConf();
try {
SessionState.get().setConf(context.getConf());
if (!validateIfBlockedUDF(getUdfClass())) {
return false;
}
registered = FunctionRegistry.registerPermanentFunction(registeredName, desc.getClassName(), true,
FunctionUtils.toFunctionResource(desc.getResources()));
} catch (ClassNotFoundException e) {
context.getConsole().printError("FAILED: Class " + desc.getClassName() + " not found");
LOG.info("create function: ", e);
return false;
} catch (RuntimeException ex) {
Throwable t = ex;
while (t.getCause() != null) {
Expand Down
16 changes: 16 additions & 0 deletions ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,22 @@ public static String[] getQualifiedFunctionNameParts(String name) throws HiveExc
return new String[] { dbName, name };
}

/**
* Retrieves the display name of a UDF (User Defined Function) from its class
* by inspecting the `@Description` annotation.
*
* @param udfClass The class of the UDF to inspect.
* @return The name of the UDF as specified in the `name` field of the `@Description` annotation,
* or `null` if the annotation is not present.
*/
public static String getFuncNameFromClass(Class<?> udfClass) {
if (udfClass.isAnnotationPresent(Description.class)) {
Description description = udfClass.getAnnotation(Description.class);
return description.name();
}
return null;
}

/**
* Function type, for permanent functions.
* Currently just JAVA, though we could support Groovy later on.
Expand Down