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