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<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<String> colon_list;
  84:   static
  85:     {
  86:       colon_list = new HashSet<String>();
  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<Object, Object> primary,
 266:                      Hashtable<Object, Object> additional)
 267:   {
 268:     Enumeration en = additional.keys();
 269:     
 270:     while (en.hasMoreElements())
 271:       {
 272:         String key2 = (String) en.nextElement();
 273:         Object value1 = primary.get(key2);
 274:         if (value1 == null)
 275:           primary.put(key2, additional.get(key2));
 276:         else if (colon_list.contains(key2))
 277:           {
 278:             String value2 = (String) additional.get(key2);
 279:             primary.put(key2, (String) value1 + ":" + value2);
 280:           }
 281:       }
 282:   }
 283:   
 284:   /**
 285:    * Get the default initial context. If {@link #gotDefault} == false, this
 286:    * method obtains the initial context from the naming manager and sets
 287:    * gotDefault to true. Otherwise the cached value ({@link #defaultInitCtx} is
 288:    * returned.
 289:    * 
 290:    * @return the default initial context
 291:    * @throws NamingException
 292:    */
 293:   protected Context getDefaultInitCtx() throws NamingException
 294:   {
 295:     if (! gotDefault)
 296:       {
 297:         defaultInitCtx = NamingManager.getInitialContext(myProps);
 298:         gotDefault = true;
 299:       }
 300:     return defaultInitCtx;
 301:   }
 302: 
 303:   /**
 304:    * Obtains the context for resolving the given name. If the first component of
 305:    * the name is the URL string, this method tries to find the corressponding
 306:    * URL naming context. If it is not an URL string, or the URL context is not
 307:    * found, the default initial context is returned.
 308:    * 
 309:    * @param name the name, for that it is required to obtain the context.
 310:    * @return the context for resolving the name.
 311:    * @throws NamingException
 312:    */
 313:   protected Context getURLOrDefaultInitCtx(Name name) throws NamingException
 314:   {
 315:     if (name.size() > 0)
 316:       return getURLOrDefaultInitCtx(name.get(0));
 317:     else
 318:       return getDefaultInitCtx();
 319:   }
 320: 
 321:   /**
 322:    * Obtains the context for resolving the given name. If the first component of
 323:    * the name is the URL string, this method tries to find the corressponding
 324:    * URL naming context. If it is not an URL string, or the URL context is not
 325:    * found, the default initial context is returned.
 326:    * 
 327:    * @param name the name, for that it is required to obtain the context.
 328:    * @return the context for resolving the name.
 329:    * @throws NamingException
 330:    */
 331:   protected Context getURLOrDefaultInitCtx(String name) throws NamingException
 332:   {
 333:     String scheme = null;
 334: 
 335:     if (NamingManager.hasInitialContextFactoryBuilder())
 336:       return getDefaultInitCtx();
 337:     int colon = name.indexOf(':');
 338:     int slash = name.indexOf('/');
 339:     if (colon > 0 && (slash == - 1 || colon < slash))
 340:       scheme = name.substring(0, colon);
 341:     if (scheme != null)
 342:       {
 343:         Context context = NamingManager.getURLContext(scheme, myProps);
 344:         if (context != null)
 345:           return context;
 346:       }
 347: 
 348:     return getDefaultInitCtx();
 349:   }
 350: 
 351:   /** @inheritDoc */  
 352:   public void bind (Name name, Object obj) throws NamingException
 353:   {
 354:     getURLOrDefaultInitCtx (name).bind (name, obj);
 355:   }
 356: 
 357:   /** @inheritDoc */  
 358:   public void bind (String name, Object obj) throws NamingException
 359:   {
 360:     getURLOrDefaultInitCtx (name).bind (name, obj);
 361:   }
 362: 
 363:   /** @inheritDoc */  
 364:   public Object lookup (Name name) throws NamingException
 365:   {
 366:     try
 367:       {
 368:         return getURLOrDefaultInitCtx (name).lookup (name);
 369:       }
 370:     catch (CannotProceedException cpe)
 371:       {
 372:         Context ctx = NamingManager.getContinuationContext (cpe);
 373:         return ctx.lookup (cpe.getRemainingName());
 374:       }
 375:   }
 376: 
 377:   /** @inheritDoc */  
 378:   public Object lookup (String name) throws NamingException
 379:   {
 380:       try
 381:         {
 382:           return getURLOrDefaultInitCtx (name).lookup (name);
 383:         }
 384:       catch (CannotProceedException cpe)
 385:         {
 386:           Context ctx = NamingManager.getContinuationContext (cpe);
 387:           return ctx.lookup (cpe.getRemainingName());
 388:         }
 389:   }
 390: 
 391:   /** @inheritDoc */  
 392:   public void rebind (Name name, Object obj) throws NamingException
 393:   {
 394:     getURLOrDefaultInitCtx (name).rebind (name, obj);
 395:   }
 396:   
 397:   /** @inheritDoc */
 398:   public void rebind (String name, Object obj) throws NamingException
 399:   {
 400:     getURLOrDefaultInitCtx (name).rebind (name, obj);
 401:   }
 402: 
 403:   /** @inheritDoc */  
 404:   public void unbind (Name name) throws NamingException
 405:   {
 406:     getURLOrDefaultInitCtx (name).unbind (name);
 407:   }
 408: 
 409:   /** @inheritDoc */  
 410:   public void unbind (String name) throws NamingException
 411:   {
 412:     getURLOrDefaultInitCtx (name).unbind (name);
 413:   }
 414: 
 415:   /** @inheritDoc */  
 416:   public void rename (Name oldName, Name newName) throws NamingException
 417:   {
 418:     getURLOrDefaultInitCtx (oldName).rename (oldName, newName);
 419:   }
 420: 
 421:   /** @inheritDoc */  
 422:   public void rename (String oldName, String newName) throws NamingException
 423:   {
 424:     getURLOrDefaultInitCtx (oldName).rename (oldName, newName);
 425:   }
 426: 
 427:   /** @inheritDoc */  
 428:   public NamingEnumeration<NameClassPair> list (Name name) throws NamingException
 429:   {
 430:     return getURLOrDefaultInitCtx (name).list (name);
 431:   }
 432: 
 433:   /** @inheritDoc */  
 434:   public NamingEnumeration<NameClassPair> list (String name) throws NamingException
 435:   {
 436:     return getURLOrDefaultInitCtx (name).list (name);
 437:   }
 438: 
 439:   /** @inheritDoc */  
 440:   public NamingEnumeration<Binding> listBindings (Name name) throws NamingException
 441:   {
 442:     return getURLOrDefaultInitCtx (name).listBindings (name);
 443:   }
 444: 
 445:   /** @inheritDoc */  
 446:   public NamingEnumeration<Binding> listBindings (String name) throws NamingException
 447:   {
 448:     return getURLOrDefaultInitCtx (name).listBindings (name);
 449:   }
 450: 
 451:   /** @inheritDoc */  
 452:   public void destroySubcontext (Name name) throws NamingException
 453:   {
 454:     getURLOrDefaultInitCtx (name).destroySubcontext (name);
 455:   }
 456: 
 457:   /** @inheritDoc */  
 458:   public void destroySubcontext (String name) throws NamingException
 459:   {
 460:     getURLOrDefaultInitCtx (name).destroySubcontext (name);
 461:   }
 462: 
 463:   /** @inheritDoc */  
 464:   public Context createSubcontext (Name name) throws NamingException
 465:   {
 466:     return getURLOrDefaultInitCtx (name).createSubcontext (name);
 467:   }
 468: 
 469:   /** @inheritDoc */  
 470:   public Context createSubcontext (String name) throws NamingException
 471:   {
 472:     return getURLOrDefaultInitCtx (name).createSubcontext (name);
 473:   }
 474: 
 475:   /** @inheritDoc */  
 476:   public Object lookupLink (Name name) throws NamingException
 477:   {
 478:     return getURLOrDefaultInitCtx (name).lookupLink (name);
 479:   }
 480: 
 481:   /** @inheritDoc */  
 482:   public Object lookupLink (String name) throws NamingException
 483:   {
 484:     return getURLOrDefaultInitCtx (name).lookupLink (name);
 485:   }
 486: 
 487:   /** @inheritDoc */  
 488:   public NameParser getNameParser (Name name) throws NamingException
 489:   {
 490:     return getURLOrDefaultInitCtx (name).getNameParser (name);
 491:   }
 492: 
 493:   /** @inheritDoc */  
 494:   public NameParser getNameParser (String name) throws NamingException
 495:   {
 496:     return getURLOrDefaultInitCtx (name).getNameParser (name);
 497:   }
 498: 
 499:   /** @inheritDoc */  
 500:   public Name composeName (Name name, Name prefix) throws NamingException
 501:   {
 502:     return getURLOrDefaultInitCtx (name).composeName (name, prefix);
 503:   }
 504: 
 505:   /** @inheritDoc */  
 506:   public String composeName (String name, 
 507:                              String prefix) throws NamingException
 508:   {
 509:     return getURLOrDefaultInitCtx (name).composeName (name, prefix);
 510:   }
 511:   
 512:   /** @inheritDoc */
 513:   public Object addToEnvironment (String propName, 
 514:                                   Object propVal) throws NamingException
 515:   {
 516:     return myProps.put (propName, propVal);
 517:   }
 518: 
 519:   /** @inheritDoc */  
 520:   public Object removeFromEnvironment (String propName) throws NamingException
 521:   {
 522:     return myProps.remove (propName);
 523:   }
 524: 
 525:   /** @inheritDoc */  
 526:   public Hashtable<?,?> getEnvironment () throws NamingException
 527:   {
 528:     return myProps;
 529:   }
 530: 
 531:   /** @inheritDoc */  
 532:   public void close () throws NamingException
 533:   {
 534:     myProps = null;
 535:     defaultInitCtx = null;
 536:   }
 537: 
 538:   /**
 539:    * This operation is not supported for the initial naming context.
 540:    * 
 541:    * @throws OperationNotSupportedException always, unless the method is
 542:    *           overridden in the derived class.
 543:    */
 544:   public String getNameInNamespace () throws NamingException
 545:   {
 546:     throw new OperationNotSupportedException ();
 547:   }
 548: }