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.juneau.commons.reflect;
018
019import static org.apache.juneau.commons.utils.Utils.*;
020
021import java.lang.reflect.*;
022import java.text.*;
023
024/**
025 * A {@link RuntimeException} wrapper around common reflection exceptions.
026 *
027 * <p>
028 * This exception is used to wrap checked exceptions that commonly occur when using Java reflection APIs,
029 * converting them into unchecked exceptions for easier handling in bean-processing code.
030 *
031 * <h5 class='section'>Wrapped Exceptions:</h5>
032 * <ul>
033 *    <li>{@link InstantiationException}
034 *    <li>{@link IllegalAccessException}
035 *    <li>{@link IllegalArgumentException}
036 *    <li>{@link InvocationTargetException}
037 *    <li>{@link NoSuchMethodException}
038 *    <li>{@link SecurityException}
039 * </ul>
040 *
041 * <p>
042 * The exception message can optionally include the class name of the bean that caused the exception,
043 * making it easier to identify the source of reflection errors in complex bean hierarchies.
044 *
045 * <h5 class='section'>Example:</h5>
046 * <p class='bjava'>
047 *    <jk>try</jk> {
048 *       Constructor&lt;?&gt; <jv>c</jv> = MyBean.<jk>class</jk>.getConstructor();
049 *       <jv>c</jv>.newInstance();
050 *    } <jk>catch</jk> (Exception <jv>e</jv>) {
051 *       <jk>throw new</jk> BeanRuntimeException(<jv>e</jv>, MyBean.<jk>class</jk>, <js>"Failed to instantiate bean"</js>);
052 *    }
053 * </p>
054 */
055public class BeanRuntimeException extends RuntimeException {
056
057   private static final long serialVersionUID = 1L;
058
059   private static String getMessage(Throwable cause, Class<?> c, String msg, Object...args) {
060      if (nn(msg))
061         return (c == null ? "" : cn(c) + ": ") + f(msg, args);
062      if (nn(cause))
063         return (c == null ? "" : cn(c) + ": ") + cause.getMessage();
064      return null;
065   }
066
067   /**
068    * Constructor.
069    *
070    * @param c The class name of the bean that caused the exception.
071    * @param message The error message.
072    * @param args Arguments passed in to the {@code String.format()} method.
073    */
074   public BeanRuntimeException(Class<?> c, String message, Object...args) {
075      this(null, c, message, args);
076   }
077
078   /**
079    * Constructor.
080    *
081    * @param message The error message.
082    */
083   public BeanRuntimeException(String message) {
084      this((Throwable)null, null, message);
085   }
086
087   /**
088    * Constructor.
089    *
090    * @param message The error message.
091    * @param args Arguments passed in to the {@code String.format()} method.
092    */
093   public BeanRuntimeException(String message, Object...args) {
094      this(null, null, message, args);
095   }
096
097   /**
098    * Constructor.
099    *
100    * @param cause The initial cause of the exception.
101    */
102   public BeanRuntimeException(Throwable cause) {
103      this(cause, null, null);
104   }
105
106   /**
107    * Constructor.
108    *
109    * @param cause The cause of this exception.
110    * @param c The class name of the bean that caused the exception.
111    * @param message The {@link MessageFormat}-style message.
112    * @param args Optional {@link MessageFormat}-style arguments.
113    */
114   public BeanRuntimeException(Throwable cause, Class<?> c, String message, Object...args) {
115      super(getMessage(cause, c, message, args), cause);
116   }
117}