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.common.utils.StringUtils.*;
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)
055         e = ((InvocationTargetException)e).getCause();
056      if (e instanceof SerializeException)
057         return (SerializeException)e;
058      return new SerializeException(e);
059   }
060
061   /**
062    * Constructor.
063    *
064    * @param session The serializer session to extract information from.
065    * @param message The exception message containing {@link MessageFormat}-style arguments.
066    * @param args Optional {@link MessageFormat}-style arguments.
067    */
068   public SerializeException(SerializerSession session, String message, Object...args) {
069      super(getMessage(session, message, args));
070   }
071
072   /**
073    * Constructor.
074    *
075    * @param message The exception message containing {@link MessageFormat}-style arguments.
076    * @param args Optional {@link MessageFormat}-style arguments.
077    */
078   public SerializeException(String message, Object...args) {
079      super(getMessage(null, message, args));
080   }
081
082   /**
083    * Constructor.
084    *
085    * @param session The serializer session to extract information from.
086    * @param causedBy The inner exception.
087    */
088   public SerializeException(SerializerSession session, Exception causedBy) {
089      super(causedBy, getMessage(session, causedBy.getMessage()));
090   }
091
092   /**
093    * Constructor.
094    *
095    * @param causedBy The inner exception.
096    */
097   public SerializeException(Throwable causedBy) {
098      super(causedBy, getMessage(null, causedBy.getMessage()));
099   }
100
101   private static String getMessage(SerializerSession session, String msg, Object... args) {
102      msg = format(msg, args);
103      if (session != null) {
104         Map<String,Object> m = session.getLastLocation();
105         if (m != null && ! m.isEmpty())
106            msg = "Serialize exception occurred at " + Json5Serializer.DEFAULT.toString(m) + ".  " + msg;
107      }
108      return msg;
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 /* Throwable */
131   public synchronized SerializeException initCause(Throwable cause) {
132      super.initCause(cause);
133      return this;
134   }
135}