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.yarn.api.records.impl.pb;
20 
21 import java.io.IOException;
22 import java.io.PrintWriter;
23 import java.io.StringWriter;
24 import java.lang.reflect.Constructor;
25 import java.lang.reflect.InvocationTargetException;
26 
27 import org.apache.hadoop.yarn.api.records.SerializedException;
28 import org.apache.hadoop.yarn.exceptions.YarnException;
29 import org.apache.hadoop.yarn.exceptions.YarnRuntimeException;
30 import org.apache.hadoop.yarn.proto.YarnProtos.SerializedExceptionProto;
31 import org.apache.hadoop.yarn.proto.YarnProtos.SerializedExceptionProtoOrBuilder;
32 
33 public class SerializedExceptionPBImpl extends SerializedException {
34 
35   SerializedExceptionProto proto = null;
36   SerializedExceptionProto.Builder builder =
37       SerializedExceptionProto.newBuilder();
38   boolean viaProto = false;
39 
SerializedExceptionPBImpl()40   public SerializedExceptionPBImpl() {
41   }
42 
SerializedExceptionPBImpl(SerializedExceptionProto proto)43   public SerializedExceptionPBImpl(SerializedExceptionProto proto) {
44     this.proto = proto;
45     viaProto = true;
46   }
47 
SerializedExceptionPBImpl(Throwable t)48   private SerializedExceptionPBImpl(Throwable t) {
49     init(t);
50   }
51 
init(String message)52   public void init(String message) {
53     maybeInitBuilder();
54     builder.setMessage(message);
55   }
56 
init(Throwable t)57   public void init(Throwable t) {
58     maybeInitBuilder();
59     if (t == null) {
60       return;
61     }
62 
63     if (t.getCause() == null) {
64     } else {
65       builder.setCause(new SerializedExceptionPBImpl(t.getCause()).getProto());
66     }
67     StringWriter sw = new StringWriter();
68     PrintWriter pw = new PrintWriter(sw);
69     t.printStackTrace(pw);
70     pw.close();
71     if (sw.toString() != null)
72       builder.setTrace(sw.toString());
73     if (t.getMessage() != null)
74       builder.setMessage(t.getMessage());
75     builder.setClassName(t.getClass().getCanonicalName());
76   }
77 
init(String message, Throwable t)78   public void init(String message, Throwable t) {
79     init(t);
80     if (message != null)
81       builder.setMessage(message);
82   }
83 
84   @SuppressWarnings("unchecked")
85   @Override
deSerialize()86   public Throwable deSerialize() {
87 
88     SerializedException cause = getCause();
89     SerializedExceptionProtoOrBuilder p = viaProto ? proto : builder;
90     Class<?> realClass = null;
91     try {
92       realClass = Class.forName(p.getClassName());
93     } catch (ClassNotFoundException e) {
94       throw new YarnRuntimeException(e);
95     }
96     Class classType = null;
97     if (YarnException.class.isAssignableFrom(realClass)) {
98       classType = YarnException.class;
99     } else if (IOException.class.isAssignableFrom(realClass)) {
100       classType = IOException.class;
101     } else if (RuntimeException.class.isAssignableFrom(realClass)) {
102       classType = RuntimeException.class;
103     } else {
104       classType = Exception.class;
105     }
106     return instantiateException(realClass.asSubclass(classType), getMessage(),
107       cause == null ? null : cause.deSerialize());
108   }
109 
110   @Override
getMessage()111   public String getMessage() {
112     SerializedExceptionProtoOrBuilder p = viaProto ? proto : builder;
113     return p.getMessage();
114   }
115 
116   @Override
getRemoteTrace()117   public String getRemoteTrace() {
118     SerializedExceptionProtoOrBuilder p = viaProto ? proto : builder;
119     return p.getTrace();
120   }
121 
122   @Override
getCause()123   public SerializedException getCause() {
124     SerializedExceptionProtoOrBuilder p = viaProto ? proto : builder;
125     if (p.hasCause()) {
126       return new SerializedExceptionPBImpl(p.getCause());
127     } else {
128       return null;
129     }
130   }
131 
getProto()132   public SerializedExceptionProto getProto() {
133     proto = viaProto ? proto : builder.build();
134     viaProto = true;
135     return proto;
136   }
137 
138   @Override
hashCode()139   public int hashCode() {
140     return getProto().hashCode();
141   }
142 
143   @Override
equals(Object other)144   public boolean equals(Object other) {
145     if (other == null) {
146       return false;
147     }
148     if (other.getClass().isAssignableFrom(this.getClass())) {
149       return this.getProto().equals(this.getClass().cast(other).getProto());
150     }
151     return false;
152   }
153 
maybeInitBuilder()154   private void maybeInitBuilder() {
155     if (viaProto || builder == null) {
156       builder = SerializedExceptionProto.newBuilder(proto);
157     }
158     viaProto = false;
159   }
160 
instantiateException( Class<? extends T> cls, String message, Throwable cause)161   private static <T extends Throwable> T instantiateException(
162       Class<? extends T> cls, String message, Throwable cause) {
163     Constructor<? extends T> cn;
164     T ex = null;
165     try {
166       cn = cls.getConstructor(String.class);
167       cn.setAccessible(true);
168       ex = cn.newInstance(message);
169       ex.initCause(cause);
170     } catch (SecurityException e) {
171       throw new YarnRuntimeException(e);
172     } catch (NoSuchMethodException e) {
173       throw new YarnRuntimeException(e);
174     } catch (IllegalArgumentException e) {
175       throw new YarnRuntimeException(e);
176     } catch (InstantiationException e) {
177       throw new YarnRuntimeException(e);
178     } catch (IllegalAccessException e) {
179       throw new YarnRuntimeException(e);
180     } catch (InvocationTargetException e) {
181       throw new YarnRuntimeException(e);
182     }
183     return ex;
184   }
185 }