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.marshall.serializer;
018
019import static org.apache.juneau.commons.utils.Shorts.*;
020
021import java.lang.reflect.*;
022import java.util.*;
023
024import org.apache.juneau.marshall.*;
025import org.apache.juneau.marshall.marshaller.*;
026
027/**
028 * General exception thrown whenever an error occurs during serialization.
029 *
030 * <h5 class='section'>See Also:</h5><ul>
031 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/SerializersAndParsers">Serializers and Parsers</a>
032
033 * </ul>
034 *
035 * @serial exclude
036 */
037@SuppressWarnings({
038   "java:S110" // Deep inheritance inherent to the exception hierarchy
039})
040public class SerializeException extends BasicRuntimeException {
041
042   private static final long serialVersionUID = 1L;
043
044   /**
045    * Creator method.
046    *
047    * <p>
048    * If the throwable is already a {@link SerializeException}, we simply return that exception as-is.
049    * If the throwable is an {@link InvocationTargetException}, we unwrap the thrown exception.
050    * Otherwise we create a new {@link SerializeException}.
051    *
052    * @param e The exception being wrapped or unwrapped.
053    *    Must not be <jk>null</jk>.
054    * @return The specified throwable wrapped or unwrapped as a {@link SerializeException} (may be the same instance if it already was one).
055    */
056   public static SerializeException create(Throwable e) {
057      if (e instanceof InvocationTargetException e2)
058         e = e2.getCause();
059      if (e instanceof SerializeException e2)
060         return e2;
061      return new SerializeException(e);
062   }
063
064   private static String getMessage(SerializerSession session, String msg, Object...args) {
065      msg = f(msg, args);
066      if (nn(session)) {
067         Map<String,Object> m = session.getLastLocation();
068         if (nn(m) && ! m.isEmpty())
069            msg = "Serialize exception occurred at " + Json5.of(m) + ".  " + msg;
070      }
071      return msg;
072   }
073
074   /**
075    * Constructor.
076    *
077    * @param session The serializer session to extract information from.
078    *    Can be <jk>null</jk> (the message is not augmented with location info).
079    * @param causedBy The inner exception.
080    *    Must not be <jk>null</jk>.
081    */
082   public SerializeException(SerializerSession session, Exception causedBy) {
083      super(causedBy, getMessage(session, causedBy.getMessage()));
084   }
085
086   /**
087    * Constructor.
088    *
089    * @param session The serializer session to extract information from.
090    *    Can be <jk>null</jk> (the message is not augmented with location info).
091    * @param message The exception message containing {@link String#format(String, Object...) String.format}-style (<c>%s</c>) arguments.
092    * @param args Optional {@link String#format(String, Object...) String.format}-style arguments.
093    */
094   public SerializeException(SerializerSession session, String message, Object...args) {
095      super(getMessage(session, message, args));
096   }
097
098   /**
099    * Constructor.
100    *
101    * @param message The exception message containing {@link String#format(String, Object...) String.format}-style (<c>%s</c>) arguments.
102    * @param args Optional {@link String#format(String, Object...) String.format}-style arguments.
103    */
104   public SerializeException(String message, Object...args) {
105      super(getMessage(null, message, args));
106   }
107
108   /**
109    * Constructor.
110    *
111    * @param causedBy The inner exception.
112    *    Must not be <jk>null</jk>.
113    */
114   public SerializeException(Throwable causedBy) {
115      super(causedBy, getMessage(null, causedBy.getMessage()));
116   }
117
118   /**
119    * Returns the highest-level <c>SerializeException</c> in the stack trace.
120    * Useful for JUnit testing of error conditions.
121    *
122    * @return The root serialize exception, or this exception if there isn't one.
123    */
124   public SerializeException getRootCause() {
125      SerializeException t = this;
126      while (! (t.getCause() == null || ! (t.getCause() instanceof SerializeException t2)))
127         t = t2;
128      return t;
129   }
130
131   /**
132    * Sets the inner cause for this exception.
133    *
134    * @param cause The inner cause.
135    * @return This object.
136    */
137   @Override /* Overridden from Throwable */
138   public synchronized SerializeException initCause(Throwable cause) {
139      super.initCause(cause);
140      return this;
141   }
142
143   @Override /* Overridden from BasicRuntimeException */
144   public SerializeException setMessage(String message, Object...args) {
145      super.setMessage(message, args);
146      return this;
147   }
148}