package org.talend.components.simplefileio.runtime.ugi; import java.io.IOException; import java.security.PrivilegedAction; import java.security.PrivilegedExceptionAction; import javax.security.auth.login.LoginException; import org.apache.hadoop.mapreduce.lib.input.InvalidInputException; import org.apache.hadoop.security.AccessControlException; import org.talend.components.simplefileio.SimpleFileIOErrorCode; import org.talend.daikon.exception.TalendRuntimeException; /** * Wraps a {@link UgiDoAs} to convert any exceptions that may be encountered during the actions execution into * {@link org.talend.daikon.exception.TalendRuntimeException}. */ public class UgiExceptionHandler extends UgiDoAs { public enum AccessType { Read, Write } private final UgiDoAs wrapped; private final AccessType accessType; private final String username; private final String path; public UgiExceptionHandler(UgiDoAs wrapped, AccessType type, String username, String path) { this.wrapped = wrapped; this.accessType = type; this.username = username; this.path = path; } @Override public <T> T doAs(PrivilegedExceptionAction<T> action) throws Exception { try { return wrapped.doAs(action); } catch (AccessControlException e) { throw createFrom(e); } catch (InvalidInputException e) { throw createFrom(e); } catch (LoginException e) { throw createFrom(e); } catch (IOException e) { Exception ex = createFromOrNull(e); if (ex != null) throw ex; throw e; } catch (RuntimeException e) { throw adapt(e); } } @Override public <T> T doAs(PrivilegedAction<T> action) { try { return wrapped.doAs(action); } catch (RuntimeException e) { // This is typically an UndeclaredThrowableException or // PipelineExecutionException. throw adapt(e); } } private RuntimeException adapt(RuntimeException e) { if (e.getCause() instanceof AccessControlException) return createFrom((AccessControlException) e.getCause()); if (e.getCause() instanceof LoginException) return createFrom((LoginException) e.getCause()); if (e.getCause() instanceof InvalidInputException) return createFrom((InvalidInputException) e.getCause()); if (e.getCause() instanceof IOException) { RuntimeException ex = createFromOrNull((IOException) e.getCause()); if (ex != null) return ex; } return e; } private TalendRuntimeException createFrom(AccessControlException cause) { if (accessType == AccessType.Read) return SimpleFileIOErrorCode.createInputNotAuthorized(cause, username, path); return SimpleFileIOErrorCode.createOutputNotAuthorized(cause, username, path); } private TalendRuntimeException createFrom(LoginException cause) { // TODO: more specific method for keytab login errors. if (accessType == AccessType.Read) return SimpleFileIOErrorCode.createInputNotAuthorized(cause, username, path); return SimpleFileIOErrorCode.createOutputNotAuthorized(cause, username, path); } private TalendRuntimeException createFrom(InvalidInputException cause) { // TODO: more specific method for file not found errors. if (accessType == AccessType.Read) return SimpleFileIOErrorCode.createInputNotAuthorized(cause, username, path); return SimpleFileIOErrorCode.createOutputNotAuthorized(cause, username, path); } private TalendRuntimeException createFromOrNull(IOException cause) { if (cause.getMessage().startsWith("Mkdirs failed to create ") && cause.getMessage().contains("(exists=false")) throw SimpleFileIOErrorCode.createOutputNotAuthorized(cause, username, path); return null; } }