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.input; 018 019import java.io.IOException; 020import java.io.Reader; 021import java.io.Serializable; 022import java.util.UUID; 023 024import org.apache.commons.io.TaggedIOException; 025 026/** 027 * A reader decorator that tags potential exceptions so that the reader that caused the exception can easily be 028 * identified. This is done by using the {@link TaggedIOException} class to wrap all thrown {@link IOException}s. See 029 * below for an example of using this class. 030 * 031 * <pre> 032 * TaggedReader reader = new TaggedReader(...); 033 * try { 034 * // Processing that may throw an IOException either from this reader 035 * // or from some other IO activity like temporary files, etc. 036 * processReader(reader); 037 * } catch (IOException e) { 038 * if (reader.isCauseOf(e)) { 039 * // The exception was caused by this reader. 040 * // Use e.getCause() to get the original exception. 041 * } else { 042 * // The exception was caused by something else. 043 * } 044 * } 045 * </pre> 046 * <p> 047 * Alternatively, the {@link #throwIfCauseOf(Throwable)} method can be used to let higher levels of code handle the 048 * exception caused by this reader while other processing errors are being taken care of at this lower level. 049 * </p> 050 * 051 * <pre> 052 * TaggedReader reader = new TaggedReader(...); 053 * try { 054 * processReader(reader); 055 * } catch (IOException e) { 056 * reader.throwIfCauseOf(e); 057 * // ... or process the exception that was caused by something else 058 * } 059 * </pre> 060 * <h2>Deprecating Serialization</h2> 061 * <p> 062 * <em>Serialization is deprecated and will be removed in 3.0.</em> 063 * </p> 064 * 065 * @see TaggedIOException 066 * @since 2.7 067 */ 068public class TaggedReader extends ProxyReader { 069 070 /** 071 * The unique tag associated with exceptions from reader. 072 */ 073 private final Serializable tag = UUID.randomUUID(); 074 075 /** 076 * Constructs a tagging decorator for the given reader. 077 * 078 * @param proxy reader to be decorated 079 */ 080 public TaggedReader(final Reader proxy) { 081 super(proxy); 082 } 083 084 /** 085 * Tags any IOExceptions thrown, wrapping and re-throwing. 086 * 087 * @param e The IOException thrown 088 * @throws IOException if an I/O error occurs. 089 */ 090 @Override 091 protected void handleIOException(final IOException e) throws IOException { 092 throw new TaggedIOException(e, tag); 093 } 094 095 /** 096 * Tests if the given exception was caused by this reader. 097 * 098 * @param exception an exception 099 * @return {@code true} if the exception was thrown by this reader, {@code false} otherwise 100 */ 101 public boolean isCauseOf(final Throwable exception) { 102 return TaggedIOException.isTaggedWith(exception, tag); 103 } 104 105 /** 106 * Re-throws the original exception thrown by this reader. This method first checks whether the given exception is a 107 * {@link TaggedIOException} wrapper created by this decorator, and then unwraps and throws the original wrapped 108 * exception. Returns normally if the exception was not thrown by this reader. 109 * 110 * @param throwable an exception 111 * @throws IOException original exception, if any, thrown by this reader 112 */ 113 public void throwIfCauseOf(final Throwable throwable) throws IOException { 114 TaggedIOException.throwCauseIfTaggedWith(throwable, tag); 115 } 116 117}