blob: 0e105d0f8401005b2670bfbe62a32ece1ffcaf78 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1999-2005 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package javax.naming;
27
28import java.util.Hashtable;
29import javax.naming.spi.NamingManager;
30import com.sun.naming.internal.ResourceManager;
31
32/**
33 * This class is the starting context for performing naming operations.
34 *<p>
35 * All naming operations are relative to a context.
36 * The initial context implements the Context interface and
37 * provides the starting point for resolution of names.
38 *<p>
39 * <a name=ENVIRONMENT></a>
40 * When the initial context is constructed, its environment
41 * is initialized with properties defined in the environment parameter
42 * passed to the constructor, and in any
43 * <a href=Context.html#RESOURCEFILES>application resource files</a>.
44 * In addition, a small number of standard JNDI properties may
45 * be specified as system properties or as applet parameters
46 * (through the use of {@link Context#APPLET}).
47 * These special properties are listed in the field detail sections of the
48 * <a href=Context.html#field_detail><tt>Context</tt></a> and
49 * <a href=ldap/LdapContext.html#field_detail><tt>LdapContext</tt></a>
50 * interface documentation.
51 *<p>
52 * JNDI determines each property's value by merging
53 * the values from the following two sources, in order:
54 * <ol>
55 * <li>
56 * The first occurrence of the property from the constructor's
57 * environment parameter and (for appropriate properties) the applet
58 * parameters and system properties.
59 * <li>
60 * The application resource files (<tt>jndi.properties</tt>).
61 * </ol>
62 * For each property found in both of these two sources, or in
63 * more than one application resource file, the property's value
64 * is determined as follows. If the property is
65 * one of the standard JNDI properties that specify a list of JNDI
66 * factories (see <a href=Context.html#LISTPROPS><tt>Context</tt></a>),
67 * all of the values are
68 * concatenated into a single colon-separated list. For other
69 * properties, only the first value found is used.
70 *
71 *<p>
72 * The initial context implementation is determined at runtime.
73 * The default policy uses the environment property
74 * "{@link Context#INITIAL_CONTEXT_FACTORY java.naming.factory.initial}",
75 * which contains the class name of the initial context factory.
76 * An exception to this policy is made when resolving URL strings, as described
77 * below.
78 *<p>
79 * When a URL string (a <tt>String</tt> of the form
80 * <em>scheme_id:rest_of_name</em>) is passed as a name parameter to
81 * any method, a URL context factory for handling that scheme is
82 * located and used to resolve the URL. If no such factory is found,
83 * the initial context specified by
84 * <tt>"java.naming.factory.initial"</tt> is used. Similarly, when a
85 * <tt>CompositeName</tt> object whose first component is a URL string is
86 * passed as a name parameter to any method, a URL context factory is
87 * located and used to resolve the first name component.
88 * See {@link NamingManager#getURLContext
89 * <tt>NamingManager.getURLContext()</tt>} for a description of how URL
90 * context factories are located.
91 *<p>
92 * This default policy of locating the initial context and URL context
93 * factories may be overridden
94 * by calling
95 * <tt>NamingManager.setInitialContextFactoryBuilder()</tt>.
96 *<p>
97 * NoInitialContextException is thrown when an initial context cannot
98 * be instantiated. This exception can be thrown during any interaction
99 * with the InitialContext, not only when the InitialContext is constructed.
100 * For example, the implementation of the initial context might lazily
101 * retrieve the context only when actual methods are invoked on it.
102 * The application should not have any dependency on when the existence
103 * of an initial context is determined.
104 *<p>
105 * When the environment property "java.naming.factory.initial" is
106 * non-null, the InitialContext constructor will attempt to create the
107 * initial context specified therein. At that time, the initial context factory
108 * involved might throw an exception if a problem is encountered. However,
109 * it is provider implementation-dependent when it verifies and indicates
110 * to the users of the initial context any environment property- or
111 * connection- related problems. It can do so lazily--delaying until
112 * an operation is performed on the context, or eagerly, at the time
113 * the context is constructed.
114 *<p>
115 * An InitialContext instance is not synchronized against concurrent
116 * access by multiple threads. Multiple threads each manipulating a
117 * different InitialContext instance need not synchronize.
118 * Threads that need to access a single InitialContext instance
119 * concurrently should synchronize amongst themselves and provide the
120 * necessary locking.
121 *
122 * @author Rosanna Lee
123 * @author Scott Seligman
124 *
125 * @see Context
126 * @see NamingManager#setInitialContextFactoryBuilder
127 * NamingManager.setInitialContextFactoryBuilder
128 * @since JNDI 1.1 / Java 2 Platform, Standard Edition, v 1.3
129 */
130
131public class InitialContext implements Context {
132
133 /**
134 * The environment associated with this InitialContext.
135 * It is initialized to null and is updated by the constructor
136 * that accepts an environment or by the <tt>init()</tt> method.
137 * @see #addToEnvironment
138 * @see #removeFromEnvironment
139 * @see #getEnvironment
140 */
141 protected Hashtable<Object,Object> myProps = null;
142
143 /**
144 * Field holding the result of calling NamingManager.getInitialContext().
145 * It is set by getDefaultInitCtx() the first time getDefaultInitCtx()
146 * is called. Subsequent invocations of getDefaultInitCtx() return
147 * the value of defaultInitCtx.
148 * @see #getDefaultInitCtx
149 */
150 protected Context defaultInitCtx = null;
151
152 /**
153 * Field indicating whether the initial context has been obtained
154 * by calling NamingManager.getInitialContext().
155 * If true, its result is in <code>defaultInitCtx</code>.
156 */
157 protected boolean gotDefault = false;
158
159 /**
160 * Constructs an initial context with the option of not
161 * initializing it. This may be used by a constructor in
162 * a subclass when the value of the environment parameter
163 * is not yet known at the time the <tt>InitialContext</tt>
164 * constructor is called. The subclass's constructor will
165 * call this constructor, compute the value of the environment,
166 * and then call <tt>init()</tt> before returning.
167 *
168 * @param lazy
169 * true means do not initialize the initial context; false
170 * is equivalent to calling <tt>new InitialContext()</tt>
171 * @throws NamingException if a naming exception is encountered
172 *
173 * @see #init(Hashtable)
174 * @since 1.3
175 */
176 protected InitialContext(boolean lazy) throws NamingException {
177 if (!lazy) {
178 init(null);
179 }
180 }
181
182 /**
183 * Constructs an initial context.
184 * No environment properties are supplied.
185 * Equivalent to <tt>new InitialContext(null)</tt>.
186 *
187 * @throws NamingException if a naming exception is encountered
188 *
189 * @see #InitialContext(Hashtable)
190 */
191 public InitialContext() throws NamingException {
192 init(null);
193 }
194
195 /**
196 * Constructs an initial context using the supplied environment.
197 * Environment properties are discussed in the class description.
198 *
199 * <p> This constructor will not modify <tt>environment</tt>
200 * or save a reference to it, but may save a clone.
201 *
202 * @param environment
203 * environment used to create the initial context.
204 * Null indicates an empty environment.
205 *
206 * @throws NamingException if a naming exception is encountered
207 */
208 public InitialContext(Hashtable<?,?> environment)
209 throws NamingException
210 {
211 if (environment != null) {
212 environment = (Hashtable)environment.clone();
213 }
214 init(environment);
215 }
216
217 /**
218 * Initializes the initial context using the supplied environment.
219 * Environment properties are discussed in the class description.
220 *
221 * <p> This method will modify <tt>environment</tt> and save
222 * a reference to it. The caller may no longer modify it.
223 *
224 * @param environment
225 * environment used to create the initial context.
226 * Null indicates an empty environment.
227 *
228 * @throws NamingException if a naming exception is encountered
229 *
230 * @see #InitialContext(boolean)
231 * @since 1.3
232 */
233 protected void init(Hashtable<?,?> environment)
234 throws NamingException
235 {
236 myProps = ResourceManager.getInitialEnvironment(environment);
237
238 if (myProps.get(Context.INITIAL_CONTEXT_FACTORY) != null) {
239 // user has specified initial context factory; try to get it
240 getDefaultInitCtx();
241 }
242 }
243
244 /**
245 * A static method to retrieve the named object.
246 * This is a shortcut method equivalent to invoking:
247 * <p>
248 * <code>
249 * InitialContext ic = new InitialContext();
250 * Object obj = ic.lookup();
251 * </code>
252 * <p> If <tt>name</tt> is empty, returns a new instance of this context
253 * (which represents the same naming context as this context, but its
254 * environment may be modified independently and it may be accessed
255 * concurrently).
256 *
257 * @param name
258 * the name of the object to look up
259 * @return the object bound to <tt>name</tt>
260 * @throws NamingException if a naming exception is encountered
261 *
262 * @see #doLookup(String)
263 * @see #lookup(Name)
264 * @since 1.6
265 */
266 public static <T> T doLookup(Name name)
267 throws NamingException {
268 return (T) (new InitialContext()).lookup(name);
269 }
270
271 /**
272 * A static method to retrieve the named object.
273 * See {@link #doLookup(Name)} for details.
274 * @param name
275 * the name of the object to look up
276 * @return the object bound to <tt>name</tt>
277 * @throws NamingException if a naming exception is encountered
278 * @since 1.6
279 */
280 public static <T> T doLookup(String name)
281 throws NamingException {
282 return (T) (new InitialContext()).lookup(name);
283 }
284
285 private static String getURLScheme(String str) {
286 int colon_posn = str.indexOf(':');
287 int slash_posn = str.indexOf('/');
288
289 if (colon_posn > 0 && (slash_posn == -1 || colon_posn < slash_posn))
290 return str.substring(0, colon_posn);
291 return null;
292 }
293
294 /**
295 * Retrieves the initial context by calling
296 * <code>NamingManager.getInitialContext()</code>
297 * and cache it in defaultInitCtx.
298 * Set <code>gotDefault</code> so that we know we've tried this before.
299 * @return The non-null cached initial context.
300 * @exception NoInitialContextException If cannot find an initial context.
301 * @exception NamingException If a naming exception was encountered.
302 */
303 protected Context getDefaultInitCtx() throws NamingException{
304 if (!gotDefault) {
305 defaultInitCtx = NamingManager.getInitialContext(myProps);
306 gotDefault = true;
307 }
308 if (defaultInitCtx == null)
309 throw new NoInitialContextException();
310
311 return defaultInitCtx;
312 }
313
314 /**
315 * Retrieves a context for resolving the string name <code>name</code>.
316 * If <code>name</code> name is a URL string, then attempt
317 * to find a URL context for it. If none is found, or if
318 * <code>name</code> is not a URL string, then return
319 * <code>getDefaultInitCtx()</code>.
320 *<p>
321 * See getURLOrDefaultInitCtx(Name) for description
322 * of how a subclass should use this method.
323 * @param name The non-null name for which to get the context.
324 * @return A URL context for <code>name</code> or the cached
325 * initial context. The result cannot be null.
326 * @exception NoInitialContextException If cannot find an initial context.
327 * @exception NamingException In a naming exception is encountered.
328 * @see javax.naming.spi.NamingManager#getURLContext
329 */
330 protected Context getURLOrDefaultInitCtx(String name)
331 throws NamingException {
332 if (NamingManager.hasInitialContextFactoryBuilder()) {
333 return getDefaultInitCtx();
334 }
335 String scheme = getURLScheme(name);
336 if (scheme != null) {
337 Context ctx = NamingManager.getURLContext(scheme, myProps);
338 if (ctx != null) {
339 return ctx;
340 }
341 }
342 return getDefaultInitCtx();
343 }
344
345 /**
346 * Retrieves a context for resolving <code>name</code>.
347 * If the first component of <code>name</code> name is a URL string,
348 * then attempt to find a URL context for it. If none is found, or if
349 * the first component of <code>name</code> is not a URL string,
350 * then return <code>getDefaultInitCtx()</code>.
351 *<p>
352 * When creating a subclass of InitialContext, use this method as
353 * follows.
354 * Define a new method that uses this method to get an initial
355 * context of the desired subclass.
356 * <p><blockquote><pre>
357 * protected XXXContext getURLOrDefaultInitXXXCtx(Name name)
358 * throws NamingException {
359 * Context answer = getURLOrDefaultInitCtx(name);
360 * if (!(answer instanceof XXXContext)) {
361 * if (answer == null) {
362 * throw new NoInitialContextException();
363 * } else {
364 * throw new NotContextException("Not an XXXContext");
365 * }
366 * }
367 * return (XXXContext)answer;
368 * }
369 * </pre></blockquote>
370 * When providing implementations for the new methods in the subclass,
371 * use this newly defined method to get the initial context.
372 * <p><blockquote><pre>
373 * public Object XXXMethod1(Name name, ...) {
374 * throws NamingException {
375 * return getURLOrDefaultInitXXXCtx(name).XXXMethod1(name, ...);
376 * }
377 * </pre></blockquote>
378 *
379 * @param name The non-null name for which to get the context.
380 * @return A URL context for <code>name</code> or the cached
381 * initial context. The result cannot be null.
382 * @exception NoInitialContextException If cannot find an initial context.
383 * @exception NamingException In a naming exception is encountered.
384 *
385 * @see javax.naming.spi.NamingManager#getURLContext
386 */
387 protected Context getURLOrDefaultInitCtx(Name name)
388 throws NamingException {
389 if (NamingManager.hasInitialContextFactoryBuilder()) {
390 return getDefaultInitCtx();
391 }
392 if (name.size() > 0) {
393 String first = name.get(0);
394 String scheme = getURLScheme(first);
395 if (scheme != null) {
396 Context ctx = NamingManager.getURLContext(scheme, myProps);
397 if (ctx != null) {
398 return ctx;
399 }
400 }
401 }
402 return getDefaultInitCtx();
403 }
404
405// Context methods
406// Most Javadoc is deferred to the Context interface.
407
408 public Object lookup(String name) throws NamingException {
409 return getURLOrDefaultInitCtx(name).lookup(name);
410 }
411
412 public Object lookup(Name name) throws NamingException {
413 return getURLOrDefaultInitCtx(name).lookup(name);
414 }
415
416 public void bind(String name, Object obj) throws NamingException {
417 getURLOrDefaultInitCtx(name).bind(name, obj);
418 }
419
420 public void bind(Name name, Object obj) throws NamingException {
421 getURLOrDefaultInitCtx(name).bind(name, obj);
422 }
423
424 public void rebind(String name, Object obj) throws NamingException {
425 getURLOrDefaultInitCtx(name).rebind(name, obj);
426 }
427
428 public void rebind(Name name, Object obj) throws NamingException {
429 getURLOrDefaultInitCtx(name).rebind(name, obj);
430 }
431
432 public void unbind(String name) throws NamingException {
433 getURLOrDefaultInitCtx(name).unbind(name);
434 }
435
436 public void unbind(Name name) throws NamingException {
437 getURLOrDefaultInitCtx(name).unbind(name);
438 }
439
440 public void rename(String oldName, String newName) throws NamingException {
441 getURLOrDefaultInitCtx(oldName).rename(oldName, newName);
442 }
443
444 public void rename(Name oldName, Name newName)
445 throws NamingException
446 {
447 getURLOrDefaultInitCtx(oldName).rename(oldName, newName);
448 }
449
450 public NamingEnumeration<NameClassPair> list(String name)
451 throws NamingException
452 {
453 return (getURLOrDefaultInitCtx(name).list(name));
454 }
455
456 public NamingEnumeration<NameClassPair> list(Name name)
457 throws NamingException
458 {
459 return (getURLOrDefaultInitCtx(name).list(name));
460 }
461
462 public NamingEnumeration<Binding> listBindings(String name)
463 throws NamingException {
464 return getURLOrDefaultInitCtx(name).listBindings(name);
465 }
466
467 public NamingEnumeration<Binding> listBindings(Name name)
468 throws NamingException {
469 return getURLOrDefaultInitCtx(name).listBindings(name);
470 }
471
472 public void destroySubcontext(String name) throws NamingException {
473 getURLOrDefaultInitCtx(name).destroySubcontext(name);
474 }
475
476 public void destroySubcontext(Name name) throws NamingException {
477 getURLOrDefaultInitCtx(name).destroySubcontext(name);
478 }
479
480 public Context createSubcontext(String name) throws NamingException {
481 return getURLOrDefaultInitCtx(name).createSubcontext(name);
482 }
483
484 public Context createSubcontext(Name name) throws NamingException {
485 return getURLOrDefaultInitCtx(name).createSubcontext(name);
486 }
487
488 public Object lookupLink(String name) throws NamingException {
489 return getURLOrDefaultInitCtx(name).lookupLink(name);
490 }
491
492 public Object lookupLink(Name name) throws NamingException {
493 return getURLOrDefaultInitCtx(name).lookupLink(name);
494 }
495
496 public NameParser getNameParser(String name) throws NamingException {
497 return getURLOrDefaultInitCtx(name).getNameParser(name);
498 }
499
500 public NameParser getNameParser(Name name) throws NamingException {
501 return getURLOrDefaultInitCtx(name).getNameParser(name);
502 }
503
504 /**
505 * Composes the name of this context with a name relative to
506 * this context.
507 * Since an initial context may never be named relative
508 * to any context other than itself, the value of the
509 * <tt>prefix</tt> parameter must be an empty name (<tt>""</tt>).
510 */
511 public String composeName(String name, String prefix)
512 throws NamingException {
513 return name;
514 }
515
516 /**
517 * Composes the name of this context with a name relative to
518 * this context.
519 * Since an initial context may never be named relative
520 * to any context other than itself, the value of the
521 * <tt>prefix</tt> parameter must be an empty name.
522 */
523 public Name composeName(Name name, Name prefix)
524 throws NamingException
525 {
526 return (Name)name.clone();
527 }
528
529 public Object addToEnvironment(String propName, Object propVal)
530 throws NamingException {
531 myProps.put(propName, propVal);
532 return getDefaultInitCtx().addToEnvironment(propName, propVal);
533 }
534
535 public Object removeFromEnvironment(String propName)
536 throws NamingException {
537 myProps.remove(propName);
538 return getDefaultInitCtx().removeFromEnvironment(propName);
539 }
540
541 public Hashtable<?,?> getEnvironment() throws NamingException {
542 return getDefaultInitCtx().getEnvironment();
543 }
544
545 public void close() throws NamingException {
546 myProps = null;
547 if (defaultInitCtx != null) {
548 defaultInitCtx.close();
549 defaultInitCtx = null;
550 }
551 gotDefault = false;
552 }
553
554 public String getNameInNamespace() throws NamingException {
555 return getDefaultInitCtx().getNameInNamespace();
556 }
557};