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
26package 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
60public 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     */
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      */
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     */
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     */
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     */
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      */
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     */
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     */
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     */
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      */
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      */
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      */
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      */
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      */
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      */
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     */
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      */
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