OSDN Git Service

Merged gcj-eclipse branch to trunk.
[pf3gnuchains/gcc-fork.git] / libjava / classpath / javax / naming / InitialContext.java
1 /* InitialContext.java -- Initial naming context.
2    Copyright (C) 2000, 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38
39 package javax.naming;
40
41 import java.applet.Applet;
42 import java.io.IOException;
43 import java.io.InputStream;
44 import java.net.URL;
45 import java.util.Enumeration;
46 import java.util.HashSet;
47 import java.util.Hashtable;
48 import java.util.Properties;
49
50 import javax.naming.spi.NamingManager;
51
52 /**
53  * The starting context for performing naming operations. All naming operations
54  * are performed in the scope of some context. The initial context is the
55  * starting point for the name resolution.
56  */
57 public class InitialContext implements Context
58 {
59   /**
60    * Contains the default initial context. This value is returned by
61    * {@link NamingManager#getInitialContext}. It is set by this method
62    * when calling it first time. The subsequent calls return the value of
63    * this field.
64    */
65   protected Context defaultInitCtx;
66   
67   /**
68    * Indicates if the initial context was obtained by calling
69    * {@link NamingManager#getInitialContext}. 
70    */
71   protected boolean gotDefault = false;
72   
73   /**
74    * The environment, associated with this initial context.
75    */
76   protected Hashtable<Object,Object> myProps;
77   
78   /**
79    * The list of the properties, to that the second alternative value must
80    * be appended after the colon to the first possible value. Used in
81    * {@link #merge(Hashtable, Hashtable)}
82    */
83   static final HashSet colon_list;
84   static
85     {
86       colon_list = new HashSet();
87       colon_list.add(Context.OBJECT_FACTORIES);
88       colon_list.add(Context.URL_PKG_PREFIXES);
89       colon_list.add(Context.STATE_FACTORIES);
90     };  
91     
92    /**
93     * The properties that are searched in the agreed places in the
94     * {@link #init(Hashtable)} method.
95     */
96     static final String[] use_properties = 
97       {
98         Context.DNS_URL,
99         Context.INITIAL_CONTEXT_FACTORY,
100         Context.OBJECT_FACTORIES,
101         Context.PROVIDER_URL,
102         Context.STATE_FACTORIES,
103         Context.URL_PKG_PREFIXES,
104       };
105     
106   
107   /**
108    * Creates the new initial context with the given properties.
109    * 
110    * @param environment the properties, used by the initial context being
111    *          created.
112    * @throws NamingException
113    */
114   public InitialContext(Hashtable<?,?> environment) throws NamingException
115   {
116     init(environment);
117   }
118   
119   /**
120    * Creates the initial context with the possibility to delay its
121    * initialisation.
122    * 
123    * @param lazy specified if the initialization should not be performed by this
124    *          constructor (true). If the valueis false, it works the same way as
125    *          the parameterless constructor.
126    * @throws NamingException
127    */
128   protected InitialContext(boolean lazy) throws NamingException
129   {
130     if (! lazy)
131       init(null);
132   }
133   
134   /**
135    * Creates teh new initial context with no properties. Same as
136    * InitialContext(null).
137    * 
138    * @throws NamingException
139    */
140   public InitialContext() throws NamingException
141   {
142     init(null);
143   }
144  
145   /**
146    * <p>
147    * Initialises the context, using the properties, specified in the passed
148    * table.
149    * </p>
150    * The missing properties are additionally obtained (in order) from the
151    * following locations:
152    * <ul>
153    * <li>If the passed parameter contains the key Context.APPLET, its value
154    * must be the instance of the {@link Applet}. Then the properties are
155    * requested via {@link Applet#getParameter(String)}.</li>
156    * <li>The value of the system property is used.</li>
157    * <li>The resource "jndi.properties" is requested from the context class
158    * loader of the current thread</li>
159    * <li>The property file "jndi.properties" is read from the location,
160    * specified by the system property "gnu.classpath.home.url".
161    * </ul>
162    * </p>
163    * 
164    * @param environment the table of the properties, may be null. The method
165    *          modifies the table and stores the reference to it. The caller must
166    *          not later reuse this structure for other purposes.
167    * @since 1.3
168    */
169   protected void init(Hashtable<?, ?> environment) throws NamingException
170   {
171     // If is documented that the caller should not modify the environment.
172     if (environment != null)
173       myProps = (Hashtable<Object, Object>) environment;
174     else
175       myProps = new Hashtable<Object, Object>();
176
177     Applet napplet = (Applet) myProps.get(Context.APPLET);
178
179     Properties pApplet = null;
180     if (napplet != null)
181       pApplet = new Properties();
182     Properties pSystem = new Properties();
183     Object value;
184
185     for (int i = use_properties.length - 1; i >= 0; i--)
186       {
187         String key = use_properties[i];
188         if (napplet != null)
189           {
190             value = napplet.getParameter(key);
191             if (value != null)
192               pApplet.put(key, value);
193           }
194         
195         value = System.getProperty(key);
196         if (value != null)
197           pSystem.put(key, value);
198       }
199     
200     merge(myProps, pSystem);
201     if (pApplet != null)
202       merge(myProps, pApplet);
203
204     try
205       {
206         Enumeration ep = Thread.currentThread().
207           getContextClassLoader().getResources("jndi.properties");
208         while (ep.hasMoreElements())
209           {
210             URL url = (URL) ep.nextElement();
211             Properties p = new Properties();
212
213             try
214               {
215                 InputStream is = url.openStream();
216                 p.load(is);
217                 is.close();
218               }
219             catch (IOException e)
220               {
221                 // Ignore.
222               }
223
224             merge(myProps, p);
225           }
226       }
227     catch (IOException e)
228       {
229         // Ignore.
230       }
231
232     String home = System.getProperty("gnu.classpath.home.url");
233     if (home != null)
234       {
235         String url = home + "/jndi.properties";
236         Properties p = new Properties();
237
238         try
239           {
240             InputStream is = new URL(url).openStream();
241             p.load(is);
242             is.close();
243           }
244         catch (IOException e)
245           {
246             // Ignore.
247           }
248
249         merge(myProps, p);
250       }
251   }
252   
253   /**
254    * Merge the content of the two tables. If the second table contains the key
255    * that is missing in the first table, this key - value pair is copied to the
256    * first table. If both first and second tables contain the same key AND the
257    * {@link #colon_list} set also contains this key, the value from the second
258    * table is appended to the value from the first table after semicolon, and
259    * the resulted value replaces the value in the first table.
260    * 
261    * @param primary the first table to merge. The merged result is also stored
262    *          in this table.
263    * @param additional the second table, from where additional values are taken
264    */  
265   static void merge (Hashtable primary, Hashtable additional)
266   {
267     Enumeration en = additional.keys();
268     
269     while (en.hasMoreElements())
270       {
271         String key2 = (String) en.nextElement();
272         Object value1 = primary.get(key2);
273         if (value1 == null)
274           primary.put(key2, additional.get(key2));
275         else if (colon_list.contains(key2))
276           {
277             String value2 = (String) additional.get(key2);
278             primary.put(key2, (String) value1 + ":" + value2);
279           }
280       }
281   }
282   
283   /**
284    * Get the default initial context. If {@link #gotDefault} == false, this
285    * method obtains the initial context from the naming manager and sets
286    * gotDefault to true. Otherwise the cached value ({@link #defaultInitCtx} is
287    * returned.
288    * 
289    * @return the default initial context
290    * @throws NamingException
291    */
292   protected Context getDefaultInitCtx() throws NamingException
293   {
294     if (! gotDefault)
295       {
296         defaultInitCtx = NamingManager.getInitialContext(myProps);
297         gotDefault = true;
298       }
299     return defaultInitCtx;
300   }
301
302   /**
303    * Obtains the context for resolving the given name. If the first component of
304    * the name is the URL string, this method tries to find the corressponding
305    * URL naming context. If it is not an URL string, or the URL context is not
306    * found, the default initial context is returned.
307    * 
308    * @param name the name, for that it is required to obtain the context.
309    * @return the context for resolving the name.
310    * @throws NamingException
311    */
312   protected Context getURLOrDefaultInitCtx(Name name) throws NamingException
313   {
314     if (name.size() > 0)
315       return getURLOrDefaultInitCtx(name.get(0));
316     else
317       return getDefaultInitCtx();
318   }
319
320   /**
321    * Obtains the context for resolving the given name. If the first component of
322    * the name is the URL string, this method tries to find the corressponding
323    * URL naming context. If it is not an URL string, or the URL context is not
324    * found, the default initial context is returned.
325    * 
326    * @param name the name, for that it is required to obtain the context.
327    * @return the context for resolving the name.
328    * @throws NamingException
329    */
330   protected Context getURLOrDefaultInitCtx(String name) throws NamingException
331   {
332     String scheme = null;
333
334     if (NamingManager.hasInitialContextFactoryBuilder())
335       return getDefaultInitCtx();
336     int colon = name.indexOf(':');
337     int slash = name.indexOf('/');
338     if (colon > 0 && (slash == - 1 || colon < slash))
339       scheme = name.substring(0, colon);
340     if (scheme != null)
341       {
342         Context context = NamingManager.getURLContext(scheme, myProps);
343         if (context != null)
344           return context;
345       }
346
347     return getDefaultInitCtx();
348   }
349
350   /** @inheritDoc */  
351   public void bind (Name name, Object obj) throws NamingException
352   {
353     getURLOrDefaultInitCtx (name).bind (name, obj);
354   }
355
356   /** @inheritDoc */  
357   public void bind (String name, Object obj) throws NamingException
358   {
359     getURLOrDefaultInitCtx (name).bind (name, obj);
360   }
361
362   /** @inheritDoc */  
363   public Object lookup (Name name) throws NamingException
364   {
365     try
366       {
367         return getURLOrDefaultInitCtx (name).lookup (name);
368       }
369     catch (CannotProceedException cpe)
370       {
371         Context ctx = NamingManager.getContinuationContext (cpe);
372         return ctx.lookup (cpe.getRemainingName());
373       }
374   }
375
376   /** @inheritDoc */  
377   public Object lookup (String name) throws NamingException
378   {
379       try
380         {
381           return getURLOrDefaultInitCtx (name).lookup (name);
382         }
383       catch (CannotProceedException cpe)
384         {
385           Context ctx = NamingManager.getContinuationContext (cpe);
386           return ctx.lookup (cpe.getRemainingName());
387         }
388   }
389
390   /** @inheritDoc */  
391   public void rebind (Name name, Object obj) throws NamingException
392   {
393     getURLOrDefaultInitCtx (name).rebind (name, obj);
394   }
395   
396   /** @inheritDoc */
397   public void rebind (String name, Object obj) throws NamingException
398   {
399     getURLOrDefaultInitCtx (name).rebind (name, obj);
400   }
401
402   /** @inheritDoc */  
403   public void unbind (Name name) throws NamingException
404   {
405     getURLOrDefaultInitCtx (name).unbind (name);
406   }
407
408   /** @inheritDoc */  
409   public void unbind (String name) throws NamingException
410   {
411     getURLOrDefaultInitCtx (name).unbind (name);
412   }
413
414   /** @inheritDoc */  
415   public void rename (Name oldName, Name newName) throws NamingException
416   {
417     getURLOrDefaultInitCtx (oldName).rename (oldName, newName);
418   }
419
420   /** @inheritDoc */  
421   public void rename (String oldName, String newName) throws NamingException
422   {
423     getURLOrDefaultInitCtx (oldName).rename (oldName, newName);
424   }
425
426   /** @inheritDoc */  
427   public NamingEnumeration<NameClassPair> list (Name name) throws NamingException
428   {
429     return getURLOrDefaultInitCtx (name).list (name);
430   }
431
432   /** @inheritDoc */  
433   public NamingEnumeration<NameClassPair> list (String name) throws NamingException
434   {
435     return getURLOrDefaultInitCtx (name).list (name);
436   }
437
438   /** @inheritDoc */  
439   public NamingEnumeration<Binding> listBindings (Name name) throws NamingException
440   {
441     return getURLOrDefaultInitCtx (name).listBindings (name);
442   }
443
444   /** @inheritDoc */  
445   public NamingEnumeration<Binding> listBindings (String name) throws NamingException
446   {
447     return getURLOrDefaultInitCtx (name).listBindings (name);
448   }
449
450   /** @inheritDoc */  
451   public void destroySubcontext (Name name) throws NamingException
452   {
453     getURLOrDefaultInitCtx (name).destroySubcontext (name);
454   }
455
456   /** @inheritDoc */  
457   public void destroySubcontext (String name) throws NamingException
458   {
459     getURLOrDefaultInitCtx (name).destroySubcontext (name);
460   }
461
462   /** @inheritDoc */  
463   public Context createSubcontext (Name name) throws NamingException
464   {
465     return getURLOrDefaultInitCtx (name).createSubcontext (name);
466   }
467
468   /** @inheritDoc */  
469   public Context createSubcontext (String name) throws NamingException
470   {
471     return getURLOrDefaultInitCtx (name).createSubcontext (name);
472   }
473
474   /** @inheritDoc */  
475   public Object lookupLink (Name name) throws NamingException
476   {
477     return getURLOrDefaultInitCtx (name).lookupLink (name);
478   }
479
480   /** @inheritDoc */  
481   public Object lookupLink (String name) throws NamingException
482   {
483     return getURLOrDefaultInitCtx (name).lookupLink (name);
484   }
485
486   /** @inheritDoc */  
487   public NameParser getNameParser (Name name) throws NamingException
488   {
489     return getURLOrDefaultInitCtx (name).getNameParser (name);
490   }
491
492   /** @inheritDoc */  
493   public NameParser getNameParser (String name) throws NamingException
494   {
495     return getURLOrDefaultInitCtx (name).getNameParser (name);
496   }
497
498   /** @inheritDoc */  
499   public Name composeName (Name name, Name prefix) throws NamingException
500   {
501     return getURLOrDefaultInitCtx (name).composeName (name, prefix);
502   }
503
504   /** @inheritDoc */  
505   public String composeName (String name, 
506                              String prefix) throws NamingException
507   {
508     return getURLOrDefaultInitCtx (name).composeName (name, prefix);
509   }
510   
511   /** @inheritDoc */
512   public Object addToEnvironment (String propName, 
513                                   Object propVal) throws NamingException
514   {
515     return myProps.put (propName, propVal);
516   }
517
518   /** @inheritDoc */  
519   public Object removeFromEnvironment (String propName) throws NamingException
520   {
521     return myProps.remove (propName);
522   }
523
524   /** @inheritDoc */  
525   public Hashtable<?,?> getEnvironment () throws NamingException
526   {
527     return myProps;
528   }
529
530   /** @inheritDoc */  
531   public void close () throws NamingException
532   {
533     myProps = null;
534     defaultInitCtx = null;
535   }
536
537   /**
538    * This operation is not supported for the initial naming context.
539    * 
540    * @throws OperationNotSupportedException always, unless the method is
541    *           overridden in the derived class.
542    */
543   public String getNameInNamespace () throws NamingException
544   {
545     throw new OperationNotSupportedException ();
546   }
547 }