1   /*
2    * Copyright 2003 - 2013 The eFaps Team
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   * Revision:        $Rev$
17   * Last Changed:    $Date$
18   * Last Changed By: $Author$
19   */
20  
21  package org.efaps.util;
22  
23  import java.io.PrintStream;
24  import java.io.PrintWriter;
25  import java.sql.SQLException;
26  
27  import org.apache.commons.lang3.ArrayUtils;
28  
29  /**
30   * The class is the exception class used to throw exception. This exceptions
31   * are shown in the user interface (web browser). The exception text stands
32   * in the properties. The key value in the property is the name of the class
33   * ({@link #className}) plus the id ({@link #id}) plus the strings <i>.Id</i>,
34   * <i>.Error</i> and <i>.Action</i> to show the user a internationalized
35   * description of the exception.
36   *
37   * @author The eFaps Team
38   * @version $Id$
39   */
40  public class EFapsException
41      extends Exception
42  {
43      /**
44       * Unique identifier used to serialize this class.
45       */
46      private static final long serialVersionUID = 1906998311318776048L;
47  
48      /**
49       * The instance variable stores the class name where the exception occurs.
50       *
51       * @see #getClassName()
52       */
53      private final Class<?> className;
54  
55      /**
56       * The instance variable stores the id (key) of the exception.
57       *
58       * @see #getId()
59       */
60      private final String id;
61  
62      /**
63       * The instance variable stores the arguments replaced in the error text.
64       *
65       * @see #getArgs()
66       */
67      private final Object[] args;
68  
69      /**
70       * @param _className  name of class in which the exception is thrown
71       * @param _id         id of the exception which is thrown
72       * @param _args       argument arrays
73       */
74      public EFapsException(final Class<?> _className,
75                            final String _id,
76                            final Object... _args)
77      {
78          super("error in " + _className.getName() + "(" + _id + "," + ArrayUtils.toString(_args, "Null ARRAY ") + ")");
79          this.id = _id;
80          this.className = _className;
81          if (_args != null && _args.length > 0 && _args[0] instanceof Throwable)  {
82              initCause((Throwable) _args[0]);
83          }
84          this.args = _args;
85      }
86  
87      /**
88       * @param _message      message of the exception
89       * @param _cause        cause
90       */
91      public EFapsException(final String _message,
92                            final Throwable _cause)
93      {
94          super(_message, _cause);
95          if (_cause instanceof EFapsException) {
96              final EFapsException cause = (EFapsException) _cause;
97              this.id = cause.getId();
98              this.className = cause.getClassName();
99              this.args = cause.getArgs();
100         } else {
101             this.id = null;
102             this.className = null;
103             this.args = null;
104         }
105     }
106 
107     /**
108      * If a caused exception is a {@link SQLException}, also all next
109      * exceptions of the {@link SQLException}'s are printed into the stack
110      * trace.
111      *
112      * @param _stream <code>PrintStream</code> to use for output
113      * @see #makeInfo() to get all information about this EFapsException
114      */
115     @Override
116     public void printStackTrace(final PrintStream _stream)
117     {
118         _stream.append(makeInfo());
119         super.printStackTrace(_stream);
120         if ((getCause() != null) && (getCause() instanceof SQLException))  {
121             SQLException ex = (SQLException) getCause();
122             ex = ex.getNextException();
123             while (ex != null)  {
124                 _stream.append("Next SQL Exception is: ");
125                 ex.printStackTrace(_stream);
126                 ex = ex.getNextException();
127             }
128         }
129     }
130 
131     /**
132      * If a caused exception is a {@link SQLException}, also all next
133      * exceptions of the {@link SQLException}'s are printed into the stack
134      * trace.
135      *
136      * @param _writer <code>PrintWriter</code> to use for output
137      * @see #makeInfo() to get all information about this EFapsException
138      */
139     @Override
140     public void printStackTrace(final PrintWriter _writer)
141     {
142         _writer.append(makeInfo());
143         if (this.className != null)  {
144             _writer.append("Thrown within class ").append(this.className.getName()).append('\n');
145         }
146         super.printStackTrace(_writer);
147         if ((getCause() != null) && (getCause() instanceof SQLException))  {
148             SQLException ex = (SQLException) getCause();
149             ex = ex.getNextException();
150             while (ex != null)  {
151                 _writer.append("Next SQL Exception is: ");
152                 ex.printStackTrace(_writer);
153                 ex = ex.getNextException();
154             }
155         }
156     }
157 
158     /**
159      * Prepares a string of all information of this EFapsException. The
160      * returned string includes information about the class which throws this
161      * exception, the exception id and all arguments.
162      *
163      * @return string representation about the EFapsException
164      */
165     protected String makeInfo()
166     {
167         final StringBuilder str = new StringBuilder();
168         if (this.className != null)  {
169             str.append("Thrown within class ").append(this.className.getName()).append('\n');
170         }
171         if (this.id != null)  {
172             str.append("Id of Exception is ").append(this.id).append('\n');
173         }
174         if ((this.args != null) && (this.args.length > 0))  {
175             str.append("Arguments are:\n");
176             for (Integer index = 0; index < this.args.length; index++)  {
177                 final String arg = (this.args[index] == null)
178                                    ? "null"
179                                    : this.args[index].toString();
180                 str.append("\targs[").append(index.toString()).append("] = '").append(arg).append("'\n");
181             }
182         }
183         return str.toString();
184     }
185 
186     /**
187      * This is the getter method for instance variable {@link #className}.
188      *
189      * @return value of instance variable {@link #className}
190      * @see #className
191      */
192     public Class<?> getClassName()
193     {
194         return this.className;
195     }
196 
197     /**
198      * This is the getter method for instance variable {@link #id}.
199      *
200      * @return value of instance variable {@link #id}
201      * @see #id
202      */
203     public String getId()
204     {
205         return this.id;
206     }
207 
208     /**
209      * This is the getter method for instance variable {@link #args}.
210      *
211      * @return value of instance variable {@link #args}
212      * @see #args
213      */
214     public Object[] getArgs()
215     {
216         return this.args;
217     }
218 }