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