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 | } |