1 /*
2  * Copyright (c) 1999, 2003, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package javax.naming;
27 
28 /**
29   * This is the superclass of all exceptions thrown by
30   * operations in the Context and DirContext interfaces.
31   * The nature of the failure is described by the name of the subclass.
32   * This exception captures the information pinpointing where the operation
33   * failed, such as where resolution last proceeded to.
34   * <ul>
35   * <li> Resolved Name. Portion of name that has been resolved.
36   * <li> Resolved Object. Object to which resolution of name proceeded.
37   * <li> Remaining Name. Portion of name that has not been resolved.
38   * <li> Explanation. Detail explaining why name resolution failed.
39   * <li> Root Exception. The exception that caused this naming exception
40   *                     to be thrown.
41   *</ul>
42   * null is an acceptable value for any of these fields. When null,
43   * it means that no such information has been recorded for that field.
44   *<p>
45   * A NamingException instance is not synchronized against concurrent
46   * multithreaded access. Multiple threads trying to access and modify
47   * a single NamingException instance should lock the object.
48   *<p>
49   * This exception has been retrofitted to conform to
50   * the general purpose exception-chaining mechanism.  The
51   * <i>root exception</i> (or <i>root cause</i>) is the same object as the
52   * <i>cause</i> returned by the {@link Throwable#getCause()} method.
53   *
54   * @author Rosanna Lee
55   * @author Scott Seligman
56   * @since 1.3
57   */
58 
59 
60 public class NamingException extends Exception {
61     /**
62      * Contains the part of the name that has been successfully resolved.
63      * It is a composite name and can be null.
64      * This field is initialized by the constructors.
65      * You should access and manipulate this field
66      * through its get and set methods.
67      * @serial
68      * @see #getResolvedName
69      * @see #setResolvedName
70      */
71     protected Name resolvedName;
72     /**
73       * Contains the object to which resolution of the part of the name was
74       * successful. Can be null.
75       * This field is initialized by the constructors.
76       * You should access and manipulate this field
77       * through its get and set methods.
78       * @serial
79       * @see #getResolvedObj
80       * @see #setResolvedObj
81       */
82     protected Object resolvedObj;
83     /**
84      * Contains the remaining name that has not been resolved yet.
85      * It is a composite name and can be null.
86      * This field is initialized by the constructors.
87      * You should access and manipulate this field
88      * through its get, set, "append" methods.
89      * @serial
90      * @see #getRemainingName
91      * @see #setRemainingName
92      * @see #appendRemainingName
93      * @see #appendRemainingComponent
94      */
95     protected Name remainingName;
96 
97     /**
98      * Contains the original exception that caused this NamingException to
99      * be thrown. This field is set if there is additional
100      * information that could be obtained from the original
101      * exception, or if the original exception could not be
102      * mapped to a subclass of NamingException.
103      * Can be null.
104      *<p>
105      * This field predates the general-purpose exception chaining facility.
106      * The {@link #initCause(Throwable)} and {@link #getCause()} methods
107      * are now the preferred means of accessing this information.
108      *
109      * @serial
110      * @see #getRootCause
111      * @see #setRootCause(Throwable)
112      * @see #initCause(Throwable)
113      * @see #getCause
114      */
115     protected Throwable rootException = null;
116 
117     /**
118      * Constructs a new NamingException with an explanation.
119      * All unspecified fields are set to null.
120      *
121      * @param   explanation     A possibly null string containing
122      *                          additional detail about this exception.
123      * @see java.lang.Throwable#getMessage
124      */
NamingException(String explanation)125     public NamingException(String explanation) {
126         super(explanation);
127         resolvedName = remainingName = null;
128         resolvedObj = null;
129     }
130 
131     /**
132       * Constructs a new NamingException.
133       * All fields are set to null.
134       */
NamingException()135     public NamingException() {
136         super();
137         resolvedName = remainingName = null;
138         resolvedObj = null;
139     }
140 
141     /**
142      * Retrieves the leading portion of the name that was resolved
143      * successfully.
144      *
145      * @return The part of the name that was resolved successfully.
146      *          It is a composite name. It can be null, which means
147      *          the resolved name field has not been set.
148      * @see #getResolvedObj
149      * @see #setResolvedName
150      */
getResolvedName()151     public Name getResolvedName() {
152         return resolvedName;
153     }
154 
155     /**
156      * Retrieves the remaining unresolved portion of the name.
157      * @return The part of the name that has not been resolved.
158      *          It is a composite name. It can be null, which means
159      *          the remaining name field has not been set.
160      * @see #setRemainingName
161      * @see #appendRemainingName
162      * @see #appendRemainingComponent
163      */
getRemainingName()164     public Name getRemainingName() {
165         return remainingName;
166     }
167 
168     /**
169      * Retrieves the object to which resolution was successful.
170      * This is the object to which the resolved name is bound.
171      *
172      * @return The possibly null object that was resolved so far.
173      *  null means that the resolved object field has not been set.
174      * @see #getResolvedName
175      * @see #setResolvedObj
176      */
getResolvedObj()177     public Object getResolvedObj() {
178         return resolvedObj;
179     }
180 
181     /**
182       * Retrieves the explanation associated with this exception.
183       *
184       * @return The possibly null detail string explaining more
185       *         about this exception. If null, it means there is no
186       *         detail message for this exception.
187       *
188       * @see java.lang.Throwable#getMessage
189       */
getExplanation()190     public String getExplanation() {
191         return getMessage();
192     }
193 
194     /**
195      * Sets the resolved name field of this exception.
196      *<p>
197      * {@code name} is a composite name. If the intent is to set
198      * this field using a compound name or string, you must
199      * "stringify" the compound name, and create a composite
200      * name with a single component using the string. You can then
201      * invoke this method using the resulting composite name.
202      *<p>
203      * A copy of {@code name} is made and stored.
204      * Subsequent changes to {@code name} do not
205      * affect the copy in this NamingException and vice versa.
206      *
207      * @param name The possibly null name to set resolved name to.
208      *          If null, it sets the resolved name field to null.
209      * @see #getResolvedName
210      */
setResolvedName(Name name)211     public void setResolvedName(Name name) {
212         if (name != null)
213             resolvedName = (Name)(name.clone());
214         else
215             resolvedName = null;
216     }
217 
218     /**
219      * Sets the remaining name field of this exception.
220      *<p>
221      * {@code name} is a composite name. If the intent is to set
222      * this field using a compound name or string, you must
223      * "stringify" the compound name, and create a composite
224      * name with a single component using the string. You can then
225      * invoke this method using the resulting composite name.
226      *<p>
227      * A copy of {@code name} is made and stored.
228      * Subsequent changes to {@code name} do not
229      * affect the copy in this NamingException and vice versa.
230      * @param name The possibly null name to set remaining name to.
231      *          If null, it sets the remaining name field to null.
232      * @see #getRemainingName
233      * @see #appendRemainingName
234      * @see #appendRemainingComponent
235      */
setRemainingName(Name name)236     public void setRemainingName(Name name) {
237         if (name != null)
238             remainingName = (Name)(name.clone());
239         else
240             remainingName = null;
241     }
242 
243     /**
244      * Sets the resolved object field of this exception.
245      * @param obj The possibly null object to set resolved object to.
246      *            If null, the resolved object field is set to null.
247      * @see #getResolvedObj
248      */
setResolvedObj(Object obj)249     public void setResolvedObj(Object obj) {
250         resolvedObj = obj;
251     }
252 
253     /**
254       * Add name as the last component in remaining name.
255       * @param name The component to add.
256       *         If name is null, this method does not do anything.
257       * @see #setRemainingName
258       * @see #getRemainingName
259       * @see #appendRemainingName
260       */
appendRemainingComponent(String name)261     public void appendRemainingComponent(String name) {
262         if (name != null) {
263             try {
264                 if (remainingName == null) {
265                     remainingName = new CompositeName();
266                 }
267                 remainingName.add(name);
268             } catch (NamingException e) {
269                 throw new IllegalArgumentException(e.toString());
270             }
271         }
272     }
273 
274     /**
275       * Add components from 'name' as the last components in
276       * remaining name.
277       *<p>
278       * {@code name} is a composite name. If the intent is to append
279       * a compound name, you should "stringify" the compound name
280       * then invoke the overloaded form that accepts a String parameter.
281       *<p>
282       * Subsequent changes to {@code name} do not
283       * affect the remaining name field in this NamingException and vice versa.
284       * @param name The possibly null name containing ordered components to add.
285       *                 If name is null, this method does not do anything.
286       * @see #setRemainingName
287       * @see #getRemainingName
288       * @see #appendRemainingComponent
289       */
appendRemainingName(Name name)290     public void appendRemainingName(Name name) {
291         if (name == null) {
292             return;
293         }
294         if (remainingName != null) {
295             try {
296                 remainingName.addAll(name);
297             } catch (NamingException e) {
298                 throw new IllegalArgumentException(e.toString());
299             }
300         } else {
301             remainingName = (Name)(name.clone());
302         }
303     }
304 
305     /**
306       * Retrieves the root cause of this NamingException, if any.
307       * The root cause of a naming exception is used when the service provider
308       * wants to indicate to the caller a non-naming related exception
309       * but at the same time wants to use the NamingException structure
310       * to indicate how far the naming operation proceeded.
311       *<p>
312       * This method predates the general-purpose exception chaining facility.
313       * The {@link #getCause()} method is now the preferred means of obtaining
314       * this information.
315       *
316       * @return The possibly null exception that caused this naming
317       *    exception. If null, it means no root cause has been
318       *    set for this naming exception.
319       * @see #setRootCause
320       * @see #rootException
321       * @see #getCause
322       */
getRootCause()323     public Throwable getRootCause() {
324         return rootException;
325     }
326 
327     /**
328       * Records the root cause of this NamingException.
329       * If {@code e} is {@code this}, this method does not do anything.
330       *<p>
331       * This method predates the general-purpose exception chaining facility.
332       * The {@link #initCause(Throwable)} method is now the preferred means
333       * of recording this information.
334       *
335       * @param e The possibly null exception that caused the naming
336       *          operation to fail. If null, it means this naming
337       *          exception has no root cause.
338       * @see #getRootCause
339       * @see #rootException
340       * @see #initCause
341       */
setRootCause(Throwable e)342     public void setRootCause(Throwable e) {
343         if (e != this) {
344             rootException = e;
345         }
346     }
347 
348     /**
349       * Returns the cause of this exception.  The cause is the
350       * throwable that caused this naming exception to be thrown.
351       * Returns {@code null} if the cause is nonexistent or
352       * unknown.
353       *
354       * @return  the cause of this exception, or {@code null} if the
355       *          cause is nonexistent or unknown.
356       * @see #initCause(Throwable)
357       * @since 1.4
358       */
getCause()359     public Throwable getCause() {
360         return getRootCause();
361     }
362 
363     /**
364       * Initializes the cause of this exception to the specified value.
365       * The cause is the throwable that caused this naming exception to be
366       * thrown.
367       *<p>
368       * This method may be called at most once.
369       *
370       * @param  cause   the cause, which is saved for later retrieval by
371       *         the {@link #getCause()} method.  A {@code null} value
372       *         indicates that the cause is nonexistent or unknown.
373       * @return a reference to this {@code NamingException} instance.
374       * @throws IllegalArgumentException if {@code cause} is this
375       *         exception.  (A throwable cannot be its own cause.)
376       * @throws IllegalStateException if this method has already
377       *         been called on this exception.
378       * @see #getCause
379       * @since 1.4
380       */
initCause(Throwable cause)381     public Throwable initCause(Throwable cause) {
382         super.initCause(cause);
383         setRootCause(cause);
384         return this;
385     }
386 
387     /**
388      * Generates the string representation of this exception.
389      * The string representation consists of this exception's class name,
390      * its detailed message, and if it has a root cause, the string
391      * representation of the root cause exception, followed by
392      * the remaining name (if it is not null).
393      * This string is used for debugging and not meant to be interpreted
394      * programmatically.
395      *
396      * @return The non-null string containing the string representation
397      * of this exception.
398      */
toString()399     public String toString() {
400         String answer = super.toString();
401 
402         if (rootException != null) {
403             answer += " [Root exception is " + rootException + "]";
404         }
405         if (remainingName != null) {
406             answer += "; remaining name '" + remainingName + "'";
407         }
408         return answer;
409     }
410 
411     /**
412       * Generates the string representation in more detail.
413       * This string representation consists of the information returned
414       * by the toString() that takes no parameters, plus the string
415       * representation of the resolved object (if it is not null).
416       * This string is used for debugging and not meant to be interpreted
417       * programmatically.
418       *
419       * @param detail If true, include details about the resolved object
420       *                 in addition to the other information.
421       * @return The non-null string containing the string representation.
422       */
toString(boolean detail)423     public String toString(boolean detail) {
424         if (!detail || resolvedObj == null) {
425             return toString();
426         } else {
427             return (toString() + "; resolved object " + resolvedObj);
428         }
429     }
430 
431     /**
432      * Use serialVersionUID from JNDI 1.1.1 for interoperability
433      */
434     private static final long serialVersionUID = -1299181962103167177L;
435 };
436