View Javadoc

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  package org.apache.hadoop.hbase.ipc;
19  
20  import java.io.IOException;
21  import java.lang.reflect.Constructor;
22  
23  import org.apache.hadoop.conf.Configuration;
24  import org.apache.hadoop.hbase.DoNotRetryIOException;
25  import org.apache.hadoop.hbase.HBaseConfiguration;
26  import org.apache.hadoop.hbase.classification.InterfaceAudience;
27  import org.apache.hadoop.hbase.classification.InterfaceStability;
28  import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
29  import org.apache.hadoop.hbase.util.DynamicClassLoader;
30  import org.apache.hadoop.ipc.RemoteException;
31  
32  /**
33   * A {@link RemoteException} with some extra information.  If source exception
34   * was a {@link org.apache.hadoop.hbase.DoNotRetryIOException}, 
35   * {@link #isDoNotRetry()} will return true.
36   * <p>A {@link RemoteException} hosts exceptions we got from the server.
37   */
38  @SuppressWarnings("serial")
39  @InterfaceAudience.Public
40  @InterfaceStability.Evolving
41  @edu.umd.cs.findbugs.annotations.SuppressWarnings(
42      value = "DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED", justification = "None. Address sometime.")
43  public class RemoteWithExtrasException extends RemoteException {
44    private final String hostname;
45    private final int port;
46    private final boolean doNotRetry;
47  
48    private final static ClassLoader CLASS_LOADER;
49  
50    static {
51      ClassLoader parent = RemoteWithExtrasException.class.getClassLoader();
52      Configuration conf = HBaseConfiguration.create();
53      CLASS_LOADER = new DynamicClassLoader(conf, parent);
54    }
55  
56    public RemoteWithExtrasException(String className, String msg, final boolean doNotRetry) {
57      this(className, msg, null, -1, doNotRetry);
58    }
59  
60    public RemoteWithExtrasException(String className, String msg, final String hostname,
61        final int port, final boolean doNotRetry) {
62      super(className, msg);
63      this.hostname = hostname;
64      this.port = port;
65      this.doNotRetry = doNotRetry;
66    }
67  
68    @Override
69    public IOException unwrapRemoteException() {
70      Class<?> realClass;
71      try {
72        // try to load a exception class from where the HBase classes are loaded or from Dynamic
73        // classloader.
74        realClass = Class.forName(getClassName(), false, CLASS_LOADER);
75      } catch (ClassNotFoundException cnfe) {
76        try {
77          // cause could be a hadoop exception, try to load from hadoop classpath
78          realClass = Class.forName(getClassName(), false, super.getClass().getClassLoader());
79        } catch (ClassNotFoundException e) {
80          return new DoNotRetryIOException(
81              "Unable to load exception received from server:" + e.getMessage(), this);
82        }
83      }
84      try {
85        return instantiateException(realClass.asSubclass(IOException.class));
86      } catch (Exception e) {
87        return new DoNotRetryIOException(
88            "Unable to instantiate exception received from server:" + e.getMessage(), this);
89      }
90    }
91  
92    private IOException instantiateException(Class<? extends IOException> cls) throws Exception {
93      Constructor<? extends IOException> cn = cls.getConstructor(String.class);
94      cn.setAccessible(true);
95      IOException ex = cn.newInstance(this.getMessage());
96      ex.initCause(this);
97      return ex;
98    }
99  
100   /**
101    * @return null if not set
102    */
103   public String getHostname() {
104     return this.hostname;
105   }
106 
107   /**
108    * @return -1 if not set
109    */
110   public int getPort() {
111     return this.port;
112   }
113 
114   /**
115    * @return True if origin exception was a do not retry type.
116    */
117   public boolean isDoNotRetry() {
118     return this.doNotRetry;
119   }
120 }