/* * 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 com.sun.jini.constants; import java.io.ObjectStreamException; import java.net.NoRouteToHostException; import java.net.PortUnreachableException; import java.net.ProtocolException; import java.rmi.RemoteException; import java.rmi.ConnectIOException; import java.rmi.NoSuchObjectException; import java.rmi.MarshalException; import java.rmi.UnmarshalException; import java.rmi.UnexpectedException; import java.rmi.UnknownHostException; import java.rmi.ServerException; import java.rmi.ServerError; import net.jini.io.UnsupportedConstraintException; /** * Various constants useful in processing exceptions * * @author Sun Microsystems, Inc. * */ public class ThrowableConstants { /** * Value returned by <code>retryable</code> to indicate that the * passed <code>Throwable</code> does not provide any new * information on the state of the object that threw it. * @see #retryable */ final static public int INDEFINITE = 0; /** * Value returned by <code>retryable</code> to indicate that the * passed <code>Throwable</code> implies that retrying the * operation that threw the <code>Throwable</code> with the same * arguments and the same expected return value would not be * fruitful. * @see #retryable */ final static public int BAD_INVOCATION = 1; /** * Value returned by <code>retryable</code> to indicate that the * passed <code>Throwable</code> implies that any further * operations on the object that threw the <code>Throwable</code> * would not be fruitful. * @see #retryable */ final static public int BAD_OBJECT = 2; /** * Value returned by <code>retryable</code> to indicate that the * passed <code>Throwable</code> was of a type that could not be * classified. * @see #retryable */ final static public int UNCATEGORIZED = 3; /** * Attempt to classify the passed <code>Throwable</code> in terms of * what it implies about the probability of success of future operations * on the object that threw the exception. <p> * * Note, the classification used by this method tends to assume * the worst. For exceptions that represent conditions that could * get better by themselves but probably will not, it will return * <code>BAD_OBJECT</code> or <code>BAD_INVOCATION</code> instead * of <code>INDEFINITE</code>. This makes it suitable for * situations where it is better to give up, fail early, and * notify the next layer up that something is wrong than to * continue silently and retry. It is probably not a good choice * for situations where the stakes are higher, like deciding when * to give up on a prepared transaction. * * @return <code>INDEFINITE</code>, <code>BAD_INVOCATION</code>, * or <code>BAD_OBJECT</code> if the exception is a * <code>RuntimeException</code>, <code>Error</code>, or * <code>java.rmi.RemoteException</code> depending on the details of * the <code>Throwable</code>. Otherwise return * <code>UNCATEGORIZED</code> * @throws NullPointerException if the passed <code>Throwable</code> is * <code>null</code> */ public static int retryable(Throwable t) { if (t == null) throw new NullPointerException("Must pass a non-null Throwable"); if (t instanceof RuntimeException) { return BAD_INVOCATION; } if (t instanceof Error) { if ((t instanceof OutOfMemoryError) || (t instanceof LinkageError)) { return INDEFINITE; } if (t instanceof StackOverflowError) return BAD_INVOCATION; return BAD_OBJECT; } if (t instanceof RemoteException) { final RemoteException re = (RemoteException)t; if (re instanceof NoSuchObjectException || re instanceof UnexpectedException || re instanceof UnknownHostException) { return BAD_OBJECT; } final Throwable detail = re.detail; if (detail == null) return INDEFINITE; if (re instanceof MarshalException || re instanceof UnmarshalException) { if (detail instanceof ObjectStreamException) return BAD_INVOCATION; final int drs = retryable(detail); if (drs == BAD_OBJECT || drs == BAD_INVOCATION) return BAD_INVOCATION; return INDEFINITE; } if (re instanceof ConnectIOException) { if (detail instanceof NoRouteToHostException || detail instanceof PortUnreachableException || detail instanceof ProtocolException) { return BAD_OBJECT; } if (detail instanceof UnsupportedConstraintException || detail instanceof ObjectStreamException) { return BAD_INVOCATION; } return INDEFINITE; } if (re instanceof ServerException) { final int drs = retryable(detail); if (drs == BAD_OBJECT) return BAD_INVOCATION; return drs; } if (re instanceof ServerError) { return retryable(detail); } return INDEFINITE; } return UNCATEGORIZED; } }