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     */
017    package org.apache.commons.math;
018    
019    import java.io.EOFException;
020    import java.io.IOException;
021    import java.io.PrintStream;
022    import java.io.PrintWriter;
023    import java.text.MessageFormat;
024    import java.text.ParseException;
025    import java.util.ConcurrentModificationException;
026    import java.util.Locale;
027    import java.util.NoSuchElementException;
028    import java.util.Set;
029    
030    import org.apache.commons.math.exception.util.Localizable;
031    import org.apache.commons.math.exception.util.LocalizedFormats;
032    
033    /**
034    * Base class for commons-math unchecked exceptions.
035    *
036    * @version $Id: MathRuntimeException.java 1178040 2011-10-01 16:23:48Z erans $
037    * @since 2.0
038    * @deprecated To be removed before 3.0.  Please do not use in any new code.
039    */
040    public class MathRuntimeException extends RuntimeException {
041    
042        /** Serializable version identifier. */
043        private static final long serialVersionUID = 9058794795027570002L;
044    
045        /** Deprecation message. */
046        private static final String DEPRECATION_MESSAGE = "This class is deprecated; calling this method is a bug.";
047    
048        /**
049         * Pattern used to build the message.
050         */
051        private final Localizable pattern;
052    
053        /**
054         * Arguments used to build the message.
055         */
056        private final Object[] arguments;
057    
058        /**
059         * Constructs a new <code>MathRuntimeException</code> with specified
060         * formatted detail message.
061         * Message formatting is delegated to {@link java.text.MessageFormat}.
062         * @param pattern format specifier
063         * @param arguments format arguments
064         * @since 2.2
065         */
066        public MathRuntimeException(final Localizable pattern, final Object ... arguments) {
067            this.pattern   = pattern;
068            this.arguments = (arguments == null) ? new Object[0] : arguments.clone();
069        }
070    
071        /**
072         * Constructs a new <code>MathRuntimeException</code> with specified
073         * nested <code>Throwable</code> root cause.
074         *
075         * @param rootCause  the exception or error that caused this exception
076         *                   to be thrown.
077         */
078        public MathRuntimeException(final Throwable rootCause) {
079            super(rootCause);
080            this.pattern   = LocalizedFormats.SIMPLE_MESSAGE;
081            this.arguments = new Object[] { (rootCause == null) ? "" : rootCause.getMessage() };
082        }
083    
084        /**
085         * Constructs a new <code>MathRuntimeException</code> with specified
086         * formatted detail message and nested <code>Throwable</code> root cause.
087         * Message formatting is delegated to {@link java.text.MessageFormat}.
088         * @param rootCause the exception or error that caused this exception
089         * to be thrown.
090         * @param pattern format specifier
091         * @param arguments format arguments
092         * @since 2.2
093         */
094        public MathRuntimeException(final Throwable rootCause,
095                                    final Localizable pattern, final Object ... arguments) {
096            super(rootCause);
097            this.pattern   = pattern;
098            this.arguments = (arguments == null) ? new Object[0] : arguments.clone();
099        }
100    
101        /**
102         * Sets a message.
103         *
104         * @param pat Message pattern.
105         * @param args Values for replacing the placeholders in the message
106         * pattern.
107         */
108        public void addMessage(Localizable pat,
109                               Object ... args) {
110            throw new UnsupportedOperationException(DEPRECATION_MESSAGE);
111        }
112    
113        /**
114         * Sets the context (key, value) pair.
115         * Keys are assumed to be unique within an instance. If the same key is
116         * assigned a new value, the previous one will be lost.
117         *
118         * @param key Context key (not null).
119         * @param value Context value.
120         */
121        public void setContext(String key, Object value) {
122            throw new UnsupportedOperationException(DEPRECATION_MESSAGE);
123        }
124    
125        /**
126         * Gets the value associated to the given context key.
127         *
128         * @param key Context key.
129         * @return the context value or {@code null} if the key does not exist.
130         */
131        public Object getContext(String key) {
132            throw new UnsupportedOperationException(DEPRECATION_MESSAGE);
133        }
134    
135        /**
136         * Gets all the keys stored in the exception
137         *
138         * @return the set of keys.
139         */
140        public Set<String> getContextKeys() {
141            throw new UnsupportedOperationException(DEPRECATION_MESSAGE);
142        }
143    
144        /**
145         * Builds a message string by from a pattern and its arguments.
146         * @param locale Locale in which the message should be translated
147         * @param pattern format specifier
148         * @param arguments format arguments
149         * @return a message string
150         * @since 2.2
151         */
152        private static String buildMessage(final Locale locale, final Localizable pattern,
153                                           final Object ... arguments) {
154            return new MessageFormat(pattern.getLocalizedString(locale), locale).format(arguments);
155        }
156    
157        /** Gets the message in a specified locale.
158         *
159         * @param locale Locale in which the message should be translated
160         *
161         * @return localized message
162         */
163        public String getMessage(final Locale locale) {
164            if (pattern != null) {
165                return buildMessage(locale, pattern, arguments);
166            }
167            return "";
168        }
169    
170        /**
171         * Gets the message in a conventional US locale.
172         *
173         * @return localized message
174         */
175        @Override
176        public String getMessage() {
177            return getMessage(Locale.US);
178        }
179    
180        /**
181         * Gets the message in the system default locale.
182         *
183         * @return localized message
184         */
185        @Override
186        public String getLocalizedMessage() {
187            return getMessage(Locale.getDefault());
188        }
189    
190        /**
191         * Prints the stack trace of this exception to the standard error stream.
192         */
193        @Override
194        public void printStackTrace() {
195            printStackTrace(System.err);
196        }
197    
198        /**
199         * Prints the stack trace of this exception to the specified stream.
200         *
201         * @param out  the <code>PrintStream</code> to use for output
202         */
203        @Override
204        public void printStackTrace(final PrintStream out) {
205            synchronized (out) {
206                PrintWriter pw = new PrintWriter(out, false);
207                printStackTrace(pw);
208                // Flush the PrintWriter before it's GC'ed.
209                pw.flush();
210            }
211        }
212    
213        /**
214         * Constructs a new <code>ArithmeticException</code> with specified formatted detail message.
215         * Message formatting is delegated to {@link java.text.MessageFormat}.
216         * @param pattern format specifier
217         * @param arguments format arguments
218         * @return built exception
219         * @since 2.2
220         */
221        public static ArithmeticException createArithmeticException(final Localizable pattern,
222                                                                    final Object ... arguments) {
223            return new ArithmeticException() {
224    
225                /** Serializable version identifier. */
226                private static final long serialVersionUID = 5305498554076846637L;
227    
228                /** {@inheritDoc} */
229                @Override
230                public String getMessage() {
231                    return buildMessage(Locale.US, pattern, arguments);
232                }
233    
234                /** {@inheritDoc} */
235                @Override
236                public String getLocalizedMessage() {
237                    return buildMessage(Locale.getDefault(), pattern, arguments);
238                }
239    
240            };
241        }
242    
243        /**
244         * Constructs a new <code>ArrayIndexOutOfBoundsException</code> with specified formatted detail message.
245         * Message formatting is delegated to {@link java.text.MessageFormat}.
246         * @param pattern format specifier
247         * @param arguments format arguments
248         * @return built exception
249         * @since 2.2
250         */
251        public static ArrayIndexOutOfBoundsException createArrayIndexOutOfBoundsException(final Localizable pattern,
252                                                                                          final Object ... arguments) {
253            return new ArrayIndexOutOfBoundsException() {
254    
255                /** Serializable version identifier. */
256                private static final long serialVersionUID = 6718518191249632175L;
257    
258                /** {@inheritDoc} */
259                @Override
260                public String getMessage() {
261                    return buildMessage(Locale.US, pattern, arguments);
262                }
263    
264                /** {@inheritDoc} */
265                @Override
266                public String getLocalizedMessage() {
267                    return buildMessage(Locale.getDefault(), pattern, arguments);
268                }
269    
270            };
271        }
272    
273        /**
274         * Constructs a new <code>EOFException</code> with specified formatted detail message.
275         * Message formatting is delegated to {@link java.text.MessageFormat}.
276         * @param pattern format specifier
277         * @param arguments format arguments
278         * @return built exception
279         * @since 2.2
280         */
281        public static EOFException createEOFException(final Localizable pattern,
282                                                      final Object ... arguments) {
283            return new EOFException() {
284    
285                /** Serializable version identifier. */
286                private static final long serialVersionUID = 6067985859347601503L;
287    
288                /** {@inheritDoc} */
289                @Override
290                public String getMessage() {
291                    return buildMessage(Locale.US, pattern, arguments);
292                }
293    
294                /** {@inheritDoc} */
295                @Override
296                public String getLocalizedMessage() {
297                    return buildMessage(Locale.getDefault(), pattern, arguments);
298                }
299    
300            };
301        }
302    
303        /**
304         * Constructs a new <code>IOException</code> with specified nested
305         * <code>Throwable</code> root cause.
306         * <p>This factory method allows chaining of other exceptions within an
307         * <code>IOException</code> even for Java 5. The constructor for
308         * <code>IOException</code> with a cause parameter was introduced only
309         * with Java 6.</p>
310         * @param rootCause the exception or error that caused this exception
311         * to be thrown.
312         * @return built exception
313         */
314        public static IOException createIOException(final Throwable rootCause) {
315            IOException ioe = new IOException(rootCause.getLocalizedMessage());
316            ioe.initCause(rootCause);
317            return ioe;
318        }
319    
320        /**
321         * Constructs a new <code>IllegalArgumentException</code> with specified formatted detail message.
322         * Message formatting is delegated to {@link java.text.MessageFormat}.
323         * @param pattern format specifier
324         * @param arguments format arguments
325         * @return built exception
326         * @since 2.2
327         */
328        public static IllegalArgumentException createIllegalArgumentException(final Localizable pattern,
329                                                                              final Object ... arguments) {
330            return new IllegalArgumentException() {
331    
332                /** Serializable version identifier. */
333                private static final long serialVersionUID = -4284649691002411505L;
334    
335                /** {@inheritDoc} */
336                @Override
337                public String getMessage() {
338                    return buildMessage(Locale.US, pattern, arguments);
339                }
340    
341                /** {@inheritDoc} */
342                @Override
343                public String getLocalizedMessage() {
344                    return buildMessage(Locale.getDefault(), pattern, arguments);
345                }
346    
347            };
348        }
349    
350        /**
351         * Constructs a new <code>IllegalArgumentException</code> with specified nested
352         * <code>Throwable</code> root cause.
353         * @param rootCause the exception or error that caused this exception
354         * to be thrown.
355         * @return built exception
356         */
357        public static IllegalArgumentException createIllegalArgumentException(final Throwable rootCause) {
358            IllegalArgumentException iae = new IllegalArgumentException(rootCause.getLocalizedMessage());
359            iae.initCause(rootCause);
360            return iae;
361        }
362    
363        /**
364         * Constructs a new <code>IllegalStateException</code> with specified formatted detail message.
365         * Message formatting is delegated to {@link java.text.MessageFormat}.
366         * @param pattern format specifier
367         * @param arguments format arguments
368         * @return built exception
369         * @since 2.2
370         */
371        public static IllegalStateException createIllegalStateException(final Localizable pattern,
372                                                                        final Object ... arguments) {
373            return new IllegalStateException() {
374    
375                /** Serializable version identifier. */
376                private static final long serialVersionUID = 6880901520234515725L;
377    
378                /** {@inheritDoc} */
379                @Override
380                public String getMessage() {
381                    return buildMessage(Locale.US, pattern, arguments);
382                }
383    
384                /** {@inheritDoc} */
385                @Override
386                public String getLocalizedMessage() {
387                    return buildMessage(Locale.getDefault(), pattern, arguments);
388                }
389    
390            };
391        }
392    
393        /**
394         * Constructs a new <code>ConcurrentModificationException</code> with specified formatted detail message.
395         * Message formatting is delegated to {@link java.text.MessageFormat}.
396         * @param pattern format specifier
397         * @param arguments format arguments
398         * @return built exception
399         * @since 2.2
400         */
401        public static ConcurrentModificationException createConcurrentModificationException(final Localizable pattern,
402                                                                                            final Object ... arguments) {
403            return new ConcurrentModificationException() {
404    
405                /** Serializable version identifier. */
406                private static final long serialVersionUID = -1878427236170442052L;
407    
408                /** {@inheritDoc} */
409                @Override
410                public String getMessage() {
411                    return buildMessage(Locale.US, pattern, arguments);
412                }
413    
414                /** {@inheritDoc} */
415                @Override
416                public String getLocalizedMessage() {
417                    return buildMessage(Locale.getDefault(), pattern, arguments);
418                }
419    
420            };
421        }
422    
423        /**
424         * Constructs a new <code>NoSuchElementException</code> with specified formatted detail message.
425         * Message formatting is delegated to {@link java.text.MessageFormat}.
426         * @param pattern format specifier
427         * @param arguments format arguments
428         * @return built exception
429         * @since 2.2
430         */
431        public static NoSuchElementException createNoSuchElementException(final Localizable pattern,
432                                                                          final Object ... arguments) {
433            return new NoSuchElementException() {
434    
435                /** Serializable version identifier. */
436                private static final long serialVersionUID = 1632410088350355086L;
437    
438                /** {@inheritDoc} */
439                @Override
440                public String getMessage() {
441                    return buildMessage(Locale.US, pattern, arguments);
442                }
443    
444                /** {@inheritDoc} */
445                @Override
446                public String getLocalizedMessage() {
447                    return buildMessage(Locale.getDefault(), pattern, arguments);
448                }
449    
450            };
451        }
452    
453        /**
454         * Constructs a new <code>ParseException</code> with specified
455         * formatted detail message.
456         * Message formatting is delegated to {@link java.text.MessageFormat}.
457         * @param offset offset at which error occurred
458         * @param pattern format specifier
459         * @param arguments format arguments
460         * @return built exception
461         * @since 2.2
462         */
463        public static ParseException createParseException(final int offset,
464                                                          final Localizable pattern,
465                                                          final Object ... arguments) {
466            return new ParseException(null, offset) {
467    
468                /** Serializable version identifier. */
469                private static final long serialVersionUID = 8153587599409010120L;
470    
471                /** {@inheritDoc} */
472                @Override
473                public String getMessage() {
474                    return buildMessage(Locale.US, pattern, arguments);
475                }
476    
477                /** {@inheritDoc} */
478                @Override
479                public String getLocalizedMessage() {
480                    return buildMessage(Locale.getDefault(), pattern, arguments);
481                }
482    
483            };
484        }
485    
486        /** Create an {@link java.lang.RuntimeException} for an internal error.
487         * @param cause underlying cause
488         * @return an {@link java.lang.RuntimeException} for an internal error
489         */
490        public static RuntimeException createInternalError(final Throwable cause) {
491    
492            final String argument = "https://issues.apache.org/jira/browse/MATH";
493    
494            return new RuntimeException(cause) {
495    
496                /** Serializable version identifier. */
497                private static final long serialVersionUID = -201865440834027016L;
498    
499                /** {@inheritDoc} */
500                @Override
501                public String getMessage() {
502                    return buildMessage(Locale.US, LocalizedFormats.INTERNAL_ERROR, argument);
503                }
504    
505                /** {@inheritDoc} */
506                @Override
507                public String getLocalizedMessage() {
508                    return buildMessage(Locale.getDefault(), LocalizedFormats.INTERNAL_ERROR, argument);
509                }
510    
511            };
512    
513        }
514    
515    }