TaggedIOException.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.io;

  18. import java.io.IOException;
  19. import java.io.Serializable;

  20. /**
  21.  * An {@link IOException} decorator that adds a serializable tag to the
  22.  * wrapped exception. Both the tag and the original exception can be used
  23.  * to determine further processing when this exception is caught.
  24.  *
  25.  * @since 2.0
  26.  */
  27. @SuppressWarnings("deprecation") // needs to extend deprecated IOExceptionWithCause to preserve binary compatibility
  28. public class TaggedIOException extends IOExceptionWithCause {

  29.     /**
  30.      * Generated serial version UID.
  31.      */
  32.     private static final long serialVersionUID = -6994123481142850163L;

  33.     /**
  34.      * Checks whether the given throwable is tagged with the given tag.
  35.      * <p>
  36.      * This check can only succeed if the throwable is a
  37.      * {@link TaggedIOException} and the tag is {@link Serializable}, but
  38.      * the argument types are intentionally more generic to make it easier
  39.      * to use this method without type casts.
  40.      * <p>
  41.      * A typical use for this method is in a {@code catch} block to
  42.      * determine how a caught exception should be handled:
  43.      * <pre>
  44.      * Serializable tag = ...;
  45.      * try {
  46.      *     ...;
  47.      * } catch (Throwable t) {
  48.      *     if (TaggedIOException.isTaggedWith(t, tag)) {
  49.      *         // special processing for tagged exception
  50.      *     } else {
  51.      *         // handling of other kinds of exceptions
  52.      *     }
  53.      * }
  54.      * </pre>
  55.      *
  56.      * @param throwable The Throwable object to check
  57.      * @param tag tag object
  58.      * @return {@code true} if the throwable has the specified tag,
  59.      * otherwise {@code false}
  60.      */
  61.     public static boolean isTaggedWith(final Throwable throwable, final Object tag) {
  62.         return tag != null
  63.             && throwable instanceof TaggedIOException
  64.             && tag.equals(((TaggedIOException) throwable).tag);
  65.     }

  66.     /**
  67.      * Throws the original {@link IOException} if the given throwable is
  68.      * a {@link TaggedIOException} decorator the given tag. Does nothing
  69.      * if the given throwable is of a different type or if it is tagged
  70.      * with some other tag.
  71.      * <p>
  72.      * This method is typically used in a {@code catch} block to
  73.      * selectively rethrow tagged exceptions.
  74.      * <pre>
  75.      * Serializable tag = ...;
  76.      * try {
  77.      *     ...;
  78.      * } catch (Throwable t) {
  79.      *     TaggedIOException.throwCauseIfTagged(t, tag);
  80.      *     // handle other kinds of exceptions
  81.      * }
  82.      * </pre>
  83.      *
  84.      * @param throwable an exception
  85.      * @param tag tag object
  86.      * @throws IOException original exception from the tagged decorator, if any
  87.      */
  88.     public static void throwCauseIfTaggedWith(final Throwable throwable, final Object tag)
  89.             throws IOException {
  90.         if (isTaggedWith(throwable, tag)) {
  91.             throw ((TaggedIOException) throwable).getCause();
  92.         }
  93.     }

  94.     /**
  95.      * The tag of this exception.
  96.      */
  97.     private final Serializable tag;

  98.     /**
  99.      * Constructs a tagged wrapper for the given exception.
  100.      *
  101.      * @param original the exception to be tagged
  102.      * @param tag tag of this exception
  103.      */
  104.     public TaggedIOException(final IOException original, final Serializable tag) {
  105.         super(original.getMessage(), original);
  106.         this.tag = tag;
  107.     }

  108.     /**
  109.      * Returns the wrapped exception. The only difference to the overridden
  110.      * {@link Throwable#getCause()} method is the narrower return type.
  111.      *
  112.      * @return wrapped exception
  113.      */
  114.     @Override
  115.     public synchronized IOException getCause() {
  116.         return (IOException) super.getCause();
  117.     }

  118.     /**
  119.      * Returns the serializable tag object.
  120.      *
  121.      * @return tag object
  122.      */
  123.     public Serializable getTag() {
  124.         return tag;
  125.     }

  126. }