View Javadoc

1   /*
2    *  jDTAUS Core Messages
3    *  Copyright (C) 2005 Christian Schulte
4    *  <cs@schulte.it>
5    *
6    *  This library is free software; you can redistribute it and/or
7    *  modify it under the terms of the GNU Lesser General Public
8    *  License as published by the Free Software Foundation; either
9    *  version 2.1 of the License, or any later version.
10   *
11   *  This library is distributed in the hope that it will be useful,
12   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   *  Lesser General Public License for more details.
15   *
16   *  You should have received a copy of the GNU Lesser General Public
17   *  License along with this library; if not, write to the Free Software
18   *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19   *
20   */
21  package org.jdtaus.core.messages;
22  
23  import java.io.InvalidObjectException;
24  import java.io.ObjectStreamException;
25  import java.util.Locale;
26  import org.jdtaus.core.container.ContainerFactory;
27  import org.jdtaus.core.text.Message;
28  
29  /**
30   * {@code Message} stating that an exception occured.
31   * <p>The {@code Throwable} passed to the constructor of this class is used to
32   * determine the message's format arguments. For chained exceptions, that is,
33   * {@code getCause()} returns a non-{@code null} value, the root cause is used.
34   * </p>
35   *
36   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
37   * @version $JDTAUS: ExceptionMessage.java 8788 2012-12-03 02:15:13Z schulte $
38   */
39  public final class ExceptionMessage extends Message
40  {
41      //--Constants---------------------------------------------------------------
42  
43      /** Serial version UID for backwards compatibility with 1.0.x classes. */
44      private static final long serialVersionUID = 3771927969335656661L;
45  
46      //---------------------------------------------------------------Constants--
47      //--ExceptionMessage--------------------------------------------------------
48  
49      /**
50       * Throwable of the message.
51       * @serial
52       */
53      private final Throwable throwable;
54  
55      /**
56       * Root cause to report.
57       * @serial
58       */
59      private Throwable rootCause;
60  
61      /**
62       * Creates a new {@code ExceptionMessage} taking the {@code Throwable} to
63       * report.
64       *
65       * @param throwable the {@code Throwable} to report.
66       *
67       * @throws NullPointerException if {@code throwable} is {@code null}.
68       */
69      public ExceptionMessage( final Throwable throwable )
70      {
71          if ( throwable == null )
72          {
73              throw new NullPointerException( "throwable" );
74          }
75  
76          Throwable current = throwable;
77          Throwable report = current;
78          while ( ( current = current.getCause() ) != null )
79          {
80              report = current;
81          }
82  
83          this.throwable = throwable;
84          this.rootCause = report;
85      }
86  
87      //--------------------------------------------------------ExceptionMessage--
88      //--Serializable------------------------------------------------------------
89  
90      /**
91       * Takes care of initializing the {@code rootCause} field when constructed
92       * from an 1.0.x object stream.
93       *
94       * @throws ObjectStreamException if no root cause can be resolved.
95       */
96      private Object readResolve() throws ObjectStreamException
97      {
98          if ( this.throwable != null && this.rootCause == null )
99          {
100             Throwable current = this.throwable;
101             Throwable report = current;
102             while ( ( current = current.getCause() ) != null )
103             {
104                 report = current;
105             }
106             this.rootCause = report;
107         }
108         else if ( !( this.throwable != null && this.rootCause != null ) )
109         {
110             throw new InvalidObjectException(
111                 this.getMissingObjectStreamFieldMessage( this.getLocale() ) );
112 
113         }
114 
115         return this;
116     }
117 
118     //------------------------------------------------------------Serializable--
119     //--Message-----------------------------------------------------------------
120 
121     /**
122      * {@inheritDoc}
123      * <p>This method traverses up the chained hierarchy. The arguments
124      * returned are constructed using the root cause.</p>
125      *
126      * @return Strings describing the throwable.
127      * <ul>
128      * <li>[0]: the fully qualified classname of the root cause.</li>
129      * <li>[1]: the classname of the root cause without package.</li>
130      * <li>[2]: the message of the root cause.</li>
131      * </ul>
132      */
133     public Object[] getFormatArguments( final Locale locale )
134     {
135         String name = this.rootCause.getClass().getName();
136         final int lastDot = name.lastIndexOf( '.' );
137 
138         if ( lastDot >= 0 )
139         {
140             name = name.substring( lastDot + 1 );
141         }
142 
143         String message = this.rootCause.getMessage();
144         if ( message == null )
145         {
146             message = this.getNoDetailsAvailableMessage( locale );
147         }
148 
149         return new Object[]
150             {
151                 this.rootCause.getClass().getName(), name, message
152             };
153     }
154 
155     /**
156      * {@inheritDoc}
157      *
158      * @return The corresponding text from the message's {@code ResourceBundle}:
159      * <blockquote><pre>
160      * An {1} occured.
161      * Details: {2}
162      * </pre></blockquote>
163      */
164     public String getText( final Locale locale )
165     {
166         String name = this.rootCause.getClass().getName();
167         final int lastDot = name.lastIndexOf( '.' );
168 
169         if ( lastDot >= 0 )
170         {
171             name = name.substring( lastDot + 1 );
172         }
173 
174         String message = this.rootCause.getMessage();
175         if ( message == null )
176         {
177             message = this.getNoDetailsAvailableMessage( locale );
178         }
179 
180         String text;
181         if ( this.rootCause instanceof Error )
182         {
183             text = this.getErrorInfoMessage( locale, name, message );
184         }
185         else
186         {
187             text = this.getExceptionInfoMessage( locale, name, message );
188         }
189 
190         return text;
191     }
192 
193     //-----------------------------------------------------------------Message--
194     //--Dependencies------------------------------------------------------------
195 
196 // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausDependencies
197     // This section is managed by jdtaus-container-mojo.
198 
199     /**
200      * Gets the configured <code>Locale</code> implementation.
201      *
202      * @return The configured <code>Locale</code> implementation.
203      */
204     private Locale getLocale()
205     {
206         return (Locale) ContainerFactory.getContainer().
207             getDependency( this, "Locale" );
208 
209     }
210 
211 // </editor-fold>//GEN-END:jdtausDependencies
212 
213     //------------------------------------------------------------Dependencies--
214     //--Messages----------------------------------------------------------------
215 
216 // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausMessages
217     // This section is managed by jdtaus-container-mojo.
218 
219     /**
220      * Gets the text of message <code>exceptionInfo</code>.
221      * <blockquote><pre>Eine {0} ist aufgetreten. {1}</pre></blockquote>
222      * <blockquote><pre>A {0} occured. {1}</pre></blockquote>
223      *
224      * @param locale The locale of the message instance to return.
225      * @param exceptionName Name of the exception.
226      * @param exceptionMessage Message of the exception.
227      *
228      * @return Information about an exception.
229      */
230     private String getExceptionInfoMessage( final Locale locale,
231             final java.lang.String exceptionName,
232             final java.lang.String exceptionMessage )
233     {
234         return ContainerFactory.getContainer().
235             getMessage( this, "exceptionInfo", locale,
236                 new Object[]
237                 {
238                     exceptionName,
239                     exceptionMessage
240                 });
241 
242     }
243 
244     /**
245      * Gets the text of message <code>errorInfo</code>.
246      * <blockquote><pre>Ein {0} ist aufgetreten. {1}</pre></blockquote>
247      * <blockquote><pre>A {0} occured. {1}</pre></blockquote>
248      *
249      * @param locale The locale of the message instance to return.
250      * @param errorName Name of the error.
251      * @param errorMessage Message of the error.
252      *
253      * @return Information about an error.
254      */
255     private String getErrorInfoMessage( final Locale locale,
256             final java.lang.String errorName,
257             final java.lang.String errorMessage )
258     {
259         return ContainerFactory.getContainer().
260             getMessage( this, "errorInfo", locale,
261                 new Object[]
262                 {
263                     errorName,
264                     errorMessage
265                 });
266 
267     }
268 
269     /**
270      * Gets the text of message <code>noDetailsAvailable</code>.
271      * <blockquote><pre>Keine Details verfügbar.</pre></blockquote>
272      * <blockquote><pre>No details available.</pre></blockquote>
273      *
274      * @param locale The locale of the message instance to return.
275      *
276      * @return Information that no details are available.
277      */
278     private String getNoDetailsAvailableMessage( final Locale locale )
279     {
280         return ContainerFactory.getContainer().
281             getMessage( this, "noDetailsAvailable", locale, null );
282 
283     }
284 
285     /**
286      * Gets the text of message <code>missingObjectStreamField</code>.
287      * <blockquote><pre>Fehlende Felder im Datenstrom.</pre></blockquote>
288      * <blockquote><pre>Missing fields in object stream.</pre></blockquote>
289      *
290      * @param locale The locale of the message instance to return.
291      *
292      * @return Information that a field in an object stream is missing.
293      */
294     private String getMissingObjectStreamFieldMessage( final Locale locale )
295     {
296         return ContainerFactory.getContainer().
297             getMessage( this, "missingObjectStreamField", locale, null );
298 
299     }
300 
301 // </editor-fold>//GEN-END:jdtausMessages
302 
303     //----------------------------------------------------------------Messages--
304 }