1 /* Copyright 2002-2026 CS GROUP
2 * Licensed to CS GROUP (CS) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * CS licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.orekit.errors;
18
19 import java.io.Serial;
20 import java.text.MessageFormat;
21 import java.util.Locale;
22
23 import org.hipparchus.exception.Localizable;
24 import org.hipparchus.exception.MathRuntimeException;
25
26 /** This class is the base class for all specific exceptions thrown by
27 * the Orekit classes.
28
29 * <p>When the Orekit classes throw exceptions that are specific to
30 * the package, these exceptions are always subclasses of
31 * OrekitException. When exceptions that are already covered by the
32 * standard java API should be thrown, like
33 * ArrayIndexOutOfBoundsException or InvalidParameterException, these
34 * standard exceptions are thrown rather than the Hipparchus specific
35 * ones.</p>
36 * <p>This class also provides utility methods to throw some standard
37 * java exceptions with localized messages.</p>
38 *
39 * @author Luc Maisonobe
40
41 */
42
43 public class OrekitException extends RuntimeException implements LocalizedException {
44
45 /** Serializable UID. */
46 @Serial
47 private static final long serialVersionUID = 20150611L;
48
49 /** Format specifier (to be translated). */
50 private final Localizable specifier;
51
52 /** Parts to insert in the format (no translation). */
53 private final Object[] parts;
54
55 /** Simple constructor.
56 * Build an exception with a translated and formatted message
57 * @param specifier format specifier (to be translated)
58 * @param parts parts to insert in the format (no translation)
59 */
60 public OrekitException(final Localizable specifier, final Object... parts) {
61 this.specifier = specifier;
62 this.parts = (parts == null) ? new Object[0] : parts.clone();
63 }
64
65 /** Copy constructor.
66 * @param exception exception to copy from
67 * @since 5.1
68 */
69 public OrekitException(final OrekitException exception) {
70 super(exception);
71 this.specifier = exception.specifier;
72 this.parts = exception.parts.clone();
73 }
74
75 /** Simple constructor.
76 * Build an exception from a cause and with a specified message
77 * @param message descriptive message
78 * @param cause underlying cause
79 */
80 public OrekitException(final Localizable message, final Throwable cause) {
81 super(cause);
82 this.specifier = message;
83 this.parts = new Object[0];
84 }
85
86 /** Simple constructor.
87 * Build an exception from a cause and with a translated and formatted message
88 * @param cause underlying cause
89 * @param specifier format specifier (to be translated)
90 * @param parts parts to insert in the format (no translation)
91 */
92 public OrekitException(final Throwable cause, final Localizable specifier,
93 final Object... parts) {
94 super(cause);
95 this.specifier = specifier;
96 this.parts = (parts == null) ? new Object[0] : parts.clone();
97 }
98
99 /** Simple constructor.
100 * Build an exception from an Hipparchus exception
101 * @param exception underlying Hipparchus exception
102 * @since 6.0
103 */
104 public OrekitException(final MathRuntimeException exception) {
105 super(exception);
106 this.specifier = exception.getSpecifier();
107 this.parts = exception.getParts();
108 }
109
110 /** {@inheritDoc} */
111 @Override
112 public String getMessage(final Locale locale) {
113 return buildMessage(locale);
114 }
115
116 /** {@inheritDoc} */
117 @Override
118 public String getMessage() {
119 return getMessage(Locale.US);
120 }
121
122 /** {@inheritDoc} */
123 @Override
124 public String getLocalizedMessage() {
125 return getMessage(Locale.getDefault());
126 }
127
128 /** {@inheritDoc} */
129 @Override
130 public Localizable getSpecifier() {
131 return specifier;
132 }
133
134 /** {@inheritDoc} */
135 @Override
136 public Object[] getParts() {
137 return parts.clone();
138 }
139
140 /** Recover a OrekitException, possibly embedded in a {@link MathRuntimeException}.
141 * <p>
142 * If the {@code MathRuntimeException} does not embed a OrekitException, a
143 * new one will be created.
144 * </p>
145 * @param exception MathRuntimeException to analyze
146 * @return a (possibly embedded) OrekitException
147 */
148 public static OrekitException unwrap(final MathRuntimeException exception) {
149
150 for (Throwable t = exception; t != null; t = t.getCause()) {
151 if (t instanceof OrekitException orekitException) {
152 return orekitException;
153 }
154 }
155
156 return new OrekitException(exception);
157
158 }
159
160 /**
161 * Builds a message string by from a pattern and its arguments.
162 * @param locale Locale in which the message should be translated
163 * @return a message string
164 */
165 private String buildMessage(final Locale locale) {
166 if (specifier == null) {
167 return "";
168 } else {
169 try {
170 final String localizedString = specifier.getLocalizedString(locale);
171 if (localizedString == null) {
172 return "";
173 } else {
174 return new MessageFormat(localizedString, locale).format(parts);
175 }
176 //CHECKSTYLE: stop IllegalCatch check
177 } catch (Throwable t) {
178 //CHECKSTYLE: resume IllegalCatch check
179 // Message formatting or localization failed
180 // Catch all exceptions to prevent the stack trace from being lost
181 // Add the exception as suppressed so the user can fix that bug too
182 this.addSuppressed(t);
183 // just use the source string as the message
184 return specifier.getSourceString();
185 }
186 }
187 }
188
189 }