001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.io; 018 019import java.io.IOException; 020import java.io.Serializable; 021 022/** 023 * An {@link IOException} decorator that adds a serializable tag to the 024 * wrapped exception. Both the tag and the original exception can be used 025 * to determine further processing when this exception is caught. 026 * 027 * @since 2.0 028 */ 029@SuppressWarnings("deprecation") // needs to extend deprecated IOExceptionWithCause to preserve binary compatibility 030public class TaggedIOException extends IOExceptionWithCause { 031 032 /** 033 * Generated serial version UID. 034 */ 035 private static final long serialVersionUID = -6994123481142850163L; 036 037 /** 038 * Checks whether the given throwable is tagged with the given tag. 039 * <p> 040 * This check can only succeed if the throwable is a 041 * {@link TaggedIOException} and the tag is {@link Serializable}, but 042 * the argument types are intentionally more generic to make it easier 043 * to use this method without type casts. 044 * <p> 045 * A typical use for this method is in a <code>catch</code> block to 046 * determine how a caught exception should be handled: 047 * <pre> 048 * Serializable tag = ...; 049 * try { 050 * ...; 051 * } catch (Throwable t) { 052 * if (TaggedIOExcepton.isTaggedWith(t, tag)) { 053 * // special processing for tagged exception 054 * } else { 055 * // handling of other kinds of exceptions 056 * } 057 * } 058 * </pre> 059 * 060 * @param throwable The Throwable object to check 061 * @param tag tag object 062 * @return {@code true} if the throwable has the specified tag, 063 * otherwise {@code false} 064 */ 065 public static boolean isTaggedWith(final Throwable throwable, final Object tag) { 066 return tag != null 067 && throwable instanceof TaggedIOException 068 && tag.equals(((TaggedIOException) throwable).tag); 069 } 070 071 /** 072 * Throws the original {@link IOException} if the given throwable is 073 * a {@link TaggedIOException} decorator the given tag. Does nothing 074 * if the given throwable is of a different type or if it is tagged 075 * with some other tag. 076 * <p> 077 * This method is typically used in a <code>catch</code> block to 078 * selectively rethrow tagged exceptions. 079 * <pre> 080 * Serializable tag = ...; 081 * try { 082 * ...; 083 * } catch (Throwable t) { 084 * TaggedIOExcepton.throwCauseIfTagged(t, tag); 085 * // handle other kinds of exceptions 086 * } 087 * </pre> 088 * 089 * @param throwable an exception 090 * @param tag tag object 091 * @throws IOException original exception from the tagged decorator, if any 092 */ 093 public static void throwCauseIfTaggedWith(final Throwable throwable, final Object tag) 094 throws IOException { 095 if (isTaggedWith(throwable, tag)) { 096 throw ((TaggedIOException) throwable).getCause(); 097 } 098 } 099 100 /** 101 * The tag of this exception. 102 */ 103 private final Serializable tag; 104 105 /** 106 * Creates a tagged wrapper for the given exception. 107 * 108 * @param original the exception to be tagged 109 * @param tag tag of this exception 110 */ 111 public TaggedIOException(final IOException original, final Serializable tag) { 112 super(original.getMessage(), original); 113 this.tag = tag; 114 } 115 116 /** 117 * Returns the serializable tag object. 118 * 119 * @return tag object 120 */ 121 public Serializable getTag() { 122 return tag; 123 } 124 125 /** 126 * Returns the wrapped exception. The only difference to the overridden 127 * {@link Throwable#getCause()} method is the narrower return type. 128 * 129 * @return wrapped exception 130 */ 131 @Override 132 public IOException getCause() { 133 return (IOException) super.getCause(); 134 } 135 136}