com.gemstone.gemfire.distributed.internal.ReplyException Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gemfire-core Show documentation
Show all versions of gemfire-core Show documentation
SnappyData store based off Pivotal GemFireXD
/*
* Copyright (c) 2010-2015 Pivotal Software, Inc. All rights reserved.
*
* Licensed 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. See accompanying
* LICENSE file.
*/
package com.gemstone.gemfire.distributed.internal;
import com.gemstone.gemfire.GemFireCheckedException;
import com.gemstone.gemfire.GemFireException;
import com.gemstone.gemfire.InternalGemFireException;
import com.gemstone.gemfire.SerializationException;
import com.gemstone.gemfire.distributed.DistributedMember;
import com.gemstone.gemfire.distributed.internal.membership.InternalDistributedMember;
import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
/**
* Exception thrown when a DistributionMessage is processed to be propagated
* back to the sender of the message.
* @author Eric Zoerner
*
*/
public class ReplyException extends GemFireException {
private static final long serialVersionUID = -4410839793809166071L;
private static final String REMOTE_MEMBER_TOKEN = "Remote Member";
private transient InternalDistributedMember sender;
/**
* Creates a new instance of ReplyException
without detail message.
*
* Used by serialization
*/
public ReplyException() {
}
/**
* Constructs an instance of ReplyException
with the specified detail message.
* @param msg the detail message.
*/
public ReplyException(String msg) {
super(msg);
}
/**
* Constructs an instance of ReplyException
with the specified detail message
* and cause.
* @param msg the detail message.
* @param cause the causal Throwable
*/
public ReplyException(String msg, Throwable cause) {
super(msg, cause);
}
/**
* Constructs an instance of ReplyException
with the specified cause.
* @param cause the causal Throwable
*/
public ReplyException(Throwable cause) {
super(cause);
}
/** After expected reply exceptions have already been handled,
* call this method to handle this exception as unexpected,
* i.e. converts to an appropriate runtime exception and throws it.
* If there is a a causal exception, then this method will
* throw that instead of the ReplyException.
*/
public void handleAsUnexpected() {
Throwable c = getCause();
if (c == null) {
throw new InternalGemFireException(LocalizedStrings.ReplyException_UNEXPECTED_EXCEPTION_ON_MEMBER_0.toLocalizedString(getSender()), this);
}
if (c instanceof RuntimeException) {
fixUpRemoteEx(c);
throw (RuntimeException)c;
}
if (c instanceof Error) {
fixUpRemoteEx(c);
throw (Error)c;
}
if (c instanceof ClassNotFoundException) {
//for bug 43602
throw new SerializationException("Class not found", c);
}
throw new InternalGemFireException(LocalizedStrings.ReplyException_UNEXPECTED_EXCEPTION_ON_MEMBER_0.toLocalizedString(getSender()), c);
}
/**
* Fixes a remote exception that this ReplyException has wrapped. Adds the
* local stack frames. The remote stack elements have the sender id info.
*
* @param t Remote exception to fix up
* @since 5.1
*/
public void fixUpRemoteEx(Throwable t) {
fixUpRemoteEx(t, getSender());
}
/**
* Fixes a remote exception that this ReplyException has wrapped. Adds the
* local stack frames. The remote stack elements have the sender id info.
*
* @param t Remote exception to fix up
* @since 5.1
*/
public static void fixUpRemoteEx(Throwable t, DistributedMember sender) {
GemFireCacheImpl cache = GemFireCacheImpl.getInstance();
if (sender == null || (cache != null && sender.equals(cache.getMyId()))) {
return;
}
String senderId = sender.toString();
addSenderInfo(t, senderId);
StackTraceElement[] remoteStack = t.getStackTrace();
StackTraceElement[] localStack = Thread.currentThread().getStackTrace();
int localStartIdx = 0;
if (localStartIdx < localStack.length) {
// pop off the fixUpRemoteEx frame
localStartIdx++;
if (localStartIdx < localStack.length) {
// pop off the handleAsUnexpected frame
localStartIdx++;
}
}
// do not consider localStartIdx no. of elements.
StackTraceElement[] newStack = new StackTraceElement[remoteStack.length +
localStack.length -
localStartIdx];
int i = 0;
for (; i < remoteStack.length; i++) {
newStack[i] = remoteStack[i];
}
for (int j=2; i < newStack.length; j++, i++) {
newStack[i] = localStack[j];
}
t.setStackTrace(newStack);
// also set the origin in the underlying exception
if (t instanceof GemFireException) {
((GemFireException)t).setOrigin(sender);
}
else if (t instanceof GemFireCheckedException) {
((GemFireCheckedException)t).setOrigin(sender);
}
}
/**
* Adds the sender information to the stack trace elements of the given
* exception. Also traverses recursively over the 'cause' for adding this
* sender information.
*
* @param toModify
* Throwable instance to modify the stack trace elements
* @param senderId
* id of the sender member
*/
private static void addSenderInfo(Throwable toModify, String senderId) {
StackTraceElement[] stackTrace = toModify.getStackTrace();
StackTraceElement element = null;
for (int i = 0; i < stackTrace.length; i++) {
element = stackTrace[i];
if (!element.getClassName().startsWith(REMOTE_MEMBER_TOKEN)) {
stackTrace[i] = new StackTraceElement(
REMOTE_MEMBER_TOKEN + " '"+ senderId +
"' in " + element.getClassName(),
element.getMethodName(),
element.getFileName(),
element.getLineNumber());
}
}
toModify.setStackTrace(stackTrace);
Throwable cause = toModify.getCause();
if (cause != null) {
addSenderInfo(cause, senderId);
}
}
/**
* Sets the member that threw the received exception
* @param sendr the member that threw the exception
* @since 6.0
*/
public synchronized void setSenderIfNull(InternalDistributedMember sendr) {
if (this.sender == null) {
this.sender = sendr;
}
}
/**
* Gets the member which threw the exception
* @return the throwing member
* @since 6.0
*/
public synchronized InternalDistributedMember getSender() {
return this.sender;
}
@Override
public String getMessage() {
InternalDistributedMember s = getSender();
String m = super.getMessage();
return (s!=null) ? ("From " + s + ": " + m) : m;
}
}