/** * * 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.hbase; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.ipc.RemoteException; /** * An immutable class which contains a static method for handling * org.apache.hadoop.ipc.RemoteException exceptions. */ @InterfaceAudience.Private public class RemoteExceptionHandler { /* Not instantiable */ private RemoteExceptionHandler() {super();} /** * Examine passed Throwable. See if its carrying a RemoteException. If so, * run {@link #decodeRemoteException(RemoteException)} on it. Otherwise, * pass back <code>t</code> unaltered. * @param t Throwable to examine. * @return Decoded RemoteException carried by <code>t</code> or * <code>t</code> unaltered. */ public static Throwable checkThrowable(final Throwable t) { Throwable result = t; if (t instanceof RemoteException) { try { result = RemoteExceptionHandler.decodeRemoteException((RemoteException)t); } catch (Throwable tt) { result = tt; } } return result; } /** * Examine passed IOException. See if its carrying a RemoteException. If so, * run {@link #decodeRemoteException(RemoteException)} on it. Otherwise, * pass back <code>e</code> unaltered. * @param e Exception to examine. * @return Decoded RemoteException carried by <code>e</code> or * <code>e</code> unaltered. */ public static IOException checkIOException(final IOException e) { Throwable t = checkThrowable(e); return t instanceof IOException? (IOException)t: new IOException(t); } /** * Converts org.apache.hadoop.ipc.RemoteException into original exception, * if possible. If the original exception is an Error or a RuntimeException, * throws the original exception. * * @param re original exception * @return decoded RemoteException if it is an instance of or a subclass of * IOException, or the original RemoteException if it cannot be decoded. * * @throws IOException indicating a server error ocurred if the decoded * exception is not an IOException. The decoded exception is set as * the cause. * @deprecated Use {@link RemoteException#unwrapRemoteException()} instead. * In fact we should look into deprecating this whole class - St.Ack 2010929 */ public static IOException decodeRemoteException(final RemoteException re) throws IOException { IOException i = re; try { Class<?> c = Class.forName(re.getClassName()); Class<?>[] parameterTypes = { String.class }; Constructor<?> ctor = c.getConstructor(parameterTypes); Object[] arguments = { re.getMessage() }; Throwable t = (Throwable) ctor.newInstance(arguments); if (t instanceof IOException) { i = (IOException) t; } else { i = new IOException("server error"); i.initCause(t); throw i; } } catch (ClassNotFoundException x) { // continue } catch (NoSuchMethodException x) { // continue } catch (IllegalAccessException x) { // continue } catch (InvocationTargetException x) { // continue } catch (InstantiationException x) { // continue } return i; } }