001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.internal; 014 015import java.text.*; 016 017import org.apache.juneau.*; 018import org.apache.juneau.reflect.*; 019 020/** 021 * Various utility methods for creating and working with throwables. 022 */ 023public class ThrowableUtils { 024 025 /** 026 * Throws an {@link IllegalArgumentException} if the specified object is <jk>null</jk>. 027 * 028 * @param o The object to check. 029 * @param msg The message of the IllegalArgumentException. 030 * @param args Optional {@link MessageFormat}-style arguments. 031 * @throws IllegalArgumentException Constructed exception. 032 */ 033 public static void assertNotNull(Object o, String msg, Object...args) throws IllegalArgumentException { 034 if (o == null) 035 throw new BasicIllegalArgumentException(msg, args); 036 } 037 038 /** 039 * Throws an {@link IllegalArgumentException} if the specified field is <jk>null</jk>. 040 * 041 * @param fieldValue The object to check. 042 * @param fieldName The name of the field. 043 * @throws IllegalArgumentException Constructed exception. 044 */ 045 public static void assertFieldNotNull(Object fieldValue, String fieldName) throws IllegalArgumentException { 046 if (fieldValue == null) 047 throw new IllegalArgumentException("Field '"+fieldName+"' cannot be null."); 048 } 049 050 /** 051 * Throws an {@link IllegalArgumentException} if the specified field is <c><=0</c>. 052 * 053 * @param fieldValue The object to check. 054 * @param fieldName The name of the field. 055 * @throws IllegalArgumentException Constructed exception. 056 */ 057 public static void assertFieldPositive(int fieldValue, String fieldName) throws IllegalArgumentException { 058 if (fieldValue <= 0) 059 throw new IllegalArgumentException("Field '"+fieldName+"' must be a positive integer."); 060 } 061 062 /** 063 * Shortcut for calling <code><jk>new</jk> IllegalArgumentException(MessageFormat.<jsm>format</jsm>(msg, args));</code> 064 * 065 * @param msg The message of the IllegalArgumentException. 066 * @param args Optional {@link MessageFormat}-style arguments. 067 * @throws IllegalArgumentException Constructed exception. 068 */ 069 public static void illegalArg(String msg, Object...args) throws IllegalArgumentException { 070 throw new BasicIllegalArgumentException(msg, args); 071 } 072 073 /** 074 * Throws an exception if the specified thread ID is not the same as the current thread. 075 * 076 * @param threadId The ID of the thread to compare against. 077 * @param msg The message of the IllegalStateException. 078 * @param args Optional {@link MessageFormat}-style arguments. 079 * @throws IllegalStateException Constructed exception. 080 */ 081 public static void assertSameThread(long threadId, String msg, Object...args) throws IllegalStateException { 082 if (Thread.currentThread().getId() != threadId) 083 throw new BasicIllegalArgumentException(msg, args); 084 } 085 086 /** 087 * Throws an assertion error if the specified throwable or throwable causes do not contain the specified message string. 088 * 089 * @param t The throwable to check. 090 * @param msg The message text to check for. 091 * @throws AssertionError Assertion failed. 092 */ 093 public static void assertExceptionContainsMessage(Throwable t, String msg) throws AssertionError { 094 Throwable t2 = t; 095 while (t2 != null) { 096 if (t2.getMessage() != null && t2.getMessage().contains(msg)) 097 return; 098 t2 = t2.getCause(); 099 } 100 t.printStackTrace(); 101 throw new BasicAssertionError(t, "Throwable did not contain the expected message. Message=[{0}]", msg); 102 } 103 104 /** 105 * Same as {@link Throwable#getCause()} but searches the throwable chain for an exception of the specified type. 106 * 107 * @param c The throwable type to search for. 108 * @param <T> The throwable type to search for. 109 * @param t The throwable to search. 110 * @return The exception, or <jk>null</jk> if not found. 111 */ 112 @SuppressWarnings("unchecked") 113 public static <T extends Throwable> T getCause(Class<T> c, Throwable t) { 114 while (t != null) { 115 t = t.getCause(); 116 if (c.isInstance(t)) 117 return (T)t; 118 } 119 return null; 120 } 121 122 /** 123 * Given a list of available throwable types, attempts to create and throw the exception based on name. 124 * 125 * @param name The exception name. Can be a simple name or fully-qualified. 126 * @param message The exception message passed to the exception constructor. 127 * @param throwables The list of available throwable classes to choose from. 128 * @throws Throwable The thrown exception if it was possible to create. 129 */ 130 public static void throwException(String name, String message, Class<?>...throwables) throws Throwable { 131 if (name != null) 132 for (Class<?> t : throwables) 133 if (t.getName().endsWith(name)) 134 doThrow(t, message); 135 } 136 137 private static void doThrow(Class<?> t, String msg) throws Throwable { 138 ConstructorInfo c = null; 139 ClassInfo ci = ClassInfo.of(t); 140 if (msg != null) { 141 c = ci.getPublicConstructor(String.class); 142 if (c != null) 143 throw c.<Throwable>invoke(msg); 144 c = ci.getPublicConstructor(Object.class); 145 if (c != null) 146 throw c.<Throwable>invoke(msg); 147 } 148 c = ci.getPublicConstructor(); 149 if (c != null) 150 throw c.<Throwable>invoke(); 151 } 152}