Source for javax.naming.InitialContext

   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 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 = environment;
 174:     else
 175:       myProps = new Hashtable();
 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 list (Name name) throws NamingException
 428:   {
 429:     return getURLOrDefaultInitCtx (name).list (name);
 430:   }
 431: 
 432:   /** @inheritDoc */  
 433:   public NamingEnumeration list (String name) throws NamingException
 434:   {
 435:     return getURLOrDefaultInitCtx (name).list (name);
 436:   }
 437: 
 438:   /** @inheritDoc */  
 439:   public NamingEnumeration listBindings (Name name) throws NamingException
 440:   {
 441:     return getURLOrDefaultInitCtx (name).listBindings (name);
 442:   }
 443: 
 444:   /** @inheritDoc */  
 445:   public NamingEnumeration 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: }