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 */ 017 018package org.apache.commons.io; 019 020import java.io.IOException; 021import java.util.Collections; 022import java.util.Iterator; 023import java.util.List; 024import java.util.Objects; 025 026/** 027 * An IOException based on a list of Throwable causes. 028 * <p> 029 * The first exception in the list is used as this exception's cause and is accessible with the usual 030 * {@link #getCause()} while the complete list is accessible with {@link #getCauseList()}. 031 * </p> 032 * 033 * @since 2.7 034 */ 035public class IOExceptionList extends IOException implements Iterable<Throwable> { 036 037 private static final long serialVersionUID = 1L; 038 039 /** 040 * Throws this exception if the list is not null or empty. 041 * 042 * @param causeList The list to test. 043 * @param message The detail message, see {@link #getMessage()}. 044 * @throws IOExceptionList if the list is not null or empty. 045 * @since 2.12.0 046 */ 047 public static void checkEmpty(final List<? extends Throwable> causeList, final Object message) throws IOExceptionList { 048 if (!isEmpty(causeList)) { 049 throw new IOExceptionList(Objects.toString(message, null), causeList); 050 } 051 } 052 053 private static boolean isEmpty(final List<? extends Throwable> causeList) { 054 return size(causeList) == 0; 055 } 056 057 private static int size(final List<? extends Throwable> causeList) { 058 return causeList != null ? causeList.size() : 0; 059 } 060 061 private static String toMessage(final List<? extends Throwable> causeList) { 062 return String.format("%,d exception(s): %s", size(causeList), causeList); 063 } 064 065 private final List<? extends Throwable> causeList; 066 067 /** 068 * Constructs a new exception caused by a list of exceptions. 069 * 070 * @param causeList a list of cause exceptions. 071 */ 072 public IOExceptionList(final List<? extends Throwable> causeList) { 073 this(toMessage(causeList), causeList); 074 } 075 076 /** 077 * Constructs a new exception caused by a list of exceptions. 078 * 079 * @param message The detail message, see {@link #getMessage()}. 080 * @param causeList a list of cause exceptions. 081 * @since 2.9.0 082 */ 083 public IOExceptionList(final String message, final List<? extends Throwable> causeList) { 084 super(message != null ? message : toMessage(causeList), isEmpty(causeList) ? null : causeList.get(0)); 085 this.causeList = causeList == null ? Collections.emptyList() : causeList; 086 } 087 088 /** 089 * Gets the cause exception at the given index. 090 * 091 * @param <T> type of exception to return. 092 * @param index index in the cause list. 093 * @return The list of causes. 094 */ 095 public <T extends Throwable> T getCause(final int index) { 096 return (T) causeList.get(index); 097 } 098 099 /** 100 * Gets the cause exception at the given index. 101 * 102 * @param <T> type of exception to return. 103 * @param index index in the cause list. 104 * @param clazz type of exception to return. 105 * @return The list of causes. 106 */ 107 public <T extends Throwable> T getCause(final int index, final Class<T> clazz) { 108 return clazz.cast(getCause(index)); 109 } 110 111 /** 112 * Gets the cause list. 113 * 114 * @param <T> type of exception to return. 115 * @return The list of causes. 116 */ 117 public <T extends Throwable> List<T> getCauseList() { 118 return (List<T>) causeList; 119 } 120 121 /** 122 * Works around Throwable and Generics, may fail at runtime depending on the argument value. 123 * 124 * @param <T> type of exception to return. 125 * @param clazz the target type 126 * @return The list of causes. 127 */ 128 public <T extends Throwable> List<T> getCauseList(final Class<T> clazz) { 129 return (List<T>) causeList; 130 } 131 132 @Override 133 public Iterator<Throwable> iterator() { 134 return getCauseList().iterator(); 135 } 136 137}