1 /** 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package org.apache.hadoop.ipc; 20 21 import java.io.IOException; 22 import java.lang.reflect.Constructor; 23 24 import org.xml.sax.Attributes; 25 26 public class RemoteException extends IOException { 27 /** For java.io.Serializable */ 28 private static final long serialVersionUID = 1L; 29 30 private String className; 31 RemoteException(String className, String msg)32 public RemoteException(String className, String msg) { 33 super(msg); 34 this.className = className; 35 } 36 getClassName()37 public String getClassName() { 38 return className; 39 } 40 41 /** 42 * If this remote exception wraps up one of the lookupTypes 43 * then return this exception. 44 * <p> 45 * Unwraps any IOException. 46 * 47 * @param lookupTypes the desired exception class. 48 * @return IOException, which is either the lookupClass exception or this. 49 */ unwrapRemoteException(Class<?>.... lookupTypes)50 public IOException unwrapRemoteException(Class<?>... lookupTypes) { 51 if(lookupTypes == null) 52 return this; 53 for(Class<?> lookupClass : lookupTypes) { 54 if(!lookupClass.getName().equals(getClassName())) 55 continue; 56 try { 57 return instantiateException(lookupClass.asSubclass(IOException.class)); 58 } catch(Exception e) { 59 // cannot instantiate lookupClass, just return this 60 return this; 61 } 62 } 63 // wrapped up exception is not in lookupTypes, just return this 64 return this; 65 } 66 67 /** 68 * Instantiate and return the exception wrapped up by this remote exception. 69 * 70 * <p> This unwraps any <code>Throwable</code> that has a constructor taking 71 * a <code>String</code> as a parameter. 72 * Otherwise it returns this. 73 * 74 * @return <code>Throwable 75 */ unwrapRemoteException()76 public IOException unwrapRemoteException() { 77 try { 78 Class<?> realClass = Class.forName(getClassName()); 79 return instantiateException(realClass.asSubclass(IOException.class)); 80 } catch(Exception e) { 81 // cannot instantiate the original exception, just return this 82 } 83 return this; 84 } 85 instantiateException(Class<? extends IOException> cls)86 private IOException instantiateException(Class<? extends IOException> cls) 87 throws Exception { 88 Constructor<? extends IOException> cn = cls.getConstructor(String.class); 89 cn.setAccessible(true); 90 String firstLine = this.getMessage(); 91 int eol = firstLine.indexOf('\n'); 92 if (eol>=0) { 93 firstLine = firstLine.substring(0, eol); 94 } 95 IOException ex = cn.newInstance(firstLine); 96 ex.initCause(this); 97 return ex; 98 } 99 100 /** Create RemoteException from attributes */ valueOf(Attributes attrs)101 public static RemoteException valueOf(Attributes attrs) { 102 return new RemoteException(attrs.getValue("class"), 103 attrs.getValue("message")); 104 } 105 } 106