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.PrintStream;
020    import java.io.PrintWriter;
021    import java.text.MessageFormat;
022    import java.util.Locale;
023    
024    import org.apache.commons.math.exception.MathThrowable;
025    import org.apache.commons.math.exception.util.DummyLocalizable;
026    import org.apache.commons.math.exception.util.Localizable;
027    import org.apache.commons.math.exception.util.LocalizedFormats;
028    
029    
030    /**
031     * Base class for commons-math checked exceptions.
032     * <p>
033     * Supports nesting, emulating JDK 1.4 behavior if necessary.</p>
034     * <p>
035     * Adapted from <a href="http://commons.apache.org/collections/api-release/org/apache/commons/collections/FunctorException.html"/>.</p>
036     *
037     * @version $Revision: 1070725 $ $Date: 2011-02-15 02:31:12 +0100 (mar. 15 f??vr. 2011) $
038     */
039    public class MathException extends Exception implements MathThrowable {
040    
041        /** Serializable version identifier. */
042        private static final long serialVersionUID = 7428019509644517071L;
043    
044        /**
045         * Pattern used to build the message.
046         */
047        private final Localizable pattern;
048    
049        /**
050         * Arguments used to build the message.
051         */
052        private final Object[] arguments;
053    
054        /**
055         * Constructs a new <code>MathException</code> with no
056         * detail message.
057         */
058        public MathException() {
059            this.pattern   = LocalizedFormats.SIMPLE_MESSAGE;
060            this.arguments = new Object[] { "" };
061        }
062    
063        /**
064         * Constructs a new <code>MathException</code> with specified
065         * formatted detail message.
066         * Message formatting is delegated to {@link java.text.MessageFormat}.
067         * @param pattern format specifier
068         * @param arguments format arguments
069         * @deprecated as of 2.2 replaced by {@link #MathException(Localizable, Object...)}
070         */
071        @Deprecated
072        public MathException(String pattern, Object ... arguments) {
073          this(new DummyLocalizable(pattern), arguments);
074        }
075    
076        /**
077         * Constructs a new <code>MathException</code> with specified
078         * formatted detail message.
079         * Message formatting is delegated to {@link java.text.MessageFormat}.
080         * @param pattern format specifier
081         * @param arguments format arguments
082         * @since 2.2
083         */
084        public MathException(Localizable pattern, Object ... arguments) {
085          this.pattern   = pattern;
086          this.arguments = (arguments == null) ? new Object[0] : arguments.clone();
087        }
088    
089        /**
090         * Constructs a new <code>MathException</code> with specified
091         * nested <code>Throwable</code> root cause.
092         *
093         * @param rootCause  the exception or error that caused this exception
094         *                   to be thrown.
095         */
096        public MathException(Throwable rootCause) {
097            super(rootCause);
098            this.pattern   = LocalizedFormats.SIMPLE_MESSAGE;
099            this.arguments = new Object[] { (rootCause == null) ? "" : rootCause.getMessage() };
100        }
101    
102        /**
103         * Constructs a new <code>MathException</code> with specified
104         * formatted detail message and nested <code>Throwable</code> root cause.
105         * Message formatting is delegated to {@link java.text.MessageFormat}.
106         * @param rootCause the exception or error that caused this exception
107         * to be thrown.
108         * @param pattern format specifier
109         * @param arguments format arguments
110         * @since 1.2
111         * @deprecated as of 2.2 replaced by {@link #MathException(Throwable, Localizable, Object...)}
112         */
113        @Deprecated
114        public MathException(Throwable rootCause, String pattern, Object ... arguments) {
115            this(rootCause, new DummyLocalizable(pattern), arguments);
116        }
117    
118        /**
119         * Constructs a new <code>MathException</code> with specified
120         * formatted detail message and nested <code>Throwable</code> root cause.
121         * Message formatting is delegated to {@link java.text.MessageFormat}.
122         * @param rootCause the exception or error that caused this exception
123         * to be thrown.
124         * @param pattern format specifier
125         * @param arguments format arguments
126         * @since 2.2
127         */
128        public MathException(Throwable rootCause, Localizable pattern, Object ... arguments) {
129          super(rootCause);
130          this.pattern   = pattern;
131          this.arguments = (arguments == null) ? new Object[0] : arguments.clone();
132        }
133    
134        /** Gets the pattern used to build the message of this throwable.
135         *
136         * @return the pattern used to build the message of this throwable
137         * @since 1.2
138         * @deprecated as of 2.2 replaced by {@link #getSpecificPattern()} and {@link #getGeneralPattern()}
139         */
140        @Deprecated
141        public String getPattern() {
142            return pattern.getSourceString();
143        }
144    
145        /**
146         * {@inheritDoc}
147         *
148         * @since 2.2
149         */
150        public Localizable getSpecificPattern() {
151            return null;
152        }
153    
154        /**
155         * {@inheritDoc}
156         *
157         * @since 2.2
158         */
159        public Localizable getGeneralPattern() {
160            return pattern;
161        }
162    
163        /** {@inheritDoc} */
164        public Object[] getArguments() {
165            return arguments.clone();
166        }
167    
168        /** Gets the message in a specified locale.
169         *
170         * @param locale Locale in which the message should be translated
171         *
172         * @return localized message
173         * @since 1.2
174         */
175        public String getMessage(final Locale locale) {
176            if (pattern != null) {
177                return new MessageFormat(pattern.getLocalizedString(locale), locale).format(arguments);
178            }
179            return "";
180        }
181    
182        /** {@inheritDoc} */
183        @Override
184        public String getMessage() {
185            return getMessage(Locale.US);
186        }
187    
188        /** {@inheritDoc} */
189        @Override
190        public String getLocalizedMessage() {
191            return getMessage(Locale.getDefault());
192        }
193    
194        /**
195         * Prints the stack trace of this exception to the standard error stream.
196         */
197        @Override
198        public void printStackTrace() {
199            printStackTrace(System.err);
200        }
201    
202        /**
203         * Prints the stack trace of this exception to the specified stream.
204         *
205         * @param out  the <code>PrintStream</code> to use for output
206         */
207        @Override
208        public void printStackTrace(PrintStream out) {
209            synchronized (out) {
210                PrintWriter pw = new PrintWriter(out, false);
211                printStackTrace(pw);
212                // Flush the PrintWriter before it's GC'ed.
213                pw.flush();
214            }
215        }
216    
217    }