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 */ InitialContext(Hashtable<?,?> environment)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 */ InitialContext(boolean lazy)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 */ InitialContext()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 */ init(Hashtable<?, ?> environment)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 */ merge(Hashtable<Object, Object> primary, Hashtable<Object, Object> additional)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 */ getDefaultInitCtx()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 */ getURLOrDefaultInitCtx(Name name)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 */ getURLOrDefaultInitCtx(String name)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 */ bind(Name name, Object obj)352 public void bind (Name name, Object obj) throws NamingException 353 { 354 getURLOrDefaultInitCtx (name).bind (name, obj); 355 } 356 357 /** @inheritDoc */ bind(String name, Object obj)358 public void bind (String name, Object obj) throws NamingException 359 { 360 getURLOrDefaultInitCtx (name).bind (name, obj); 361 } 362 363 /** @inheritDoc */ lookup(Name name)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 */ lookup(String name)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 */ rebind(Name name, Object obj)392 public void rebind (Name name, Object obj) throws NamingException 393 { 394 getURLOrDefaultInitCtx (name).rebind (name, obj); 395 } 396 397 /** @inheritDoc */ rebind(String name, Object obj)398 public void rebind (String name, Object obj) throws NamingException 399 { 400 getURLOrDefaultInitCtx (name).rebind (name, obj); 401 } 402 403 /** @inheritDoc */ unbind(Name name)404 public void unbind (Name name) throws NamingException 405 { 406 getURLOrDefaultInitCtx (name).unbind (name); 407 } 408 409 /** @inheritDoc */ unbind(String name)410 public void unbind (String name) throws NamingException 411 { 412 getURLOrDefaultInitCtx (name).unbind (name); 413 } 414 415 /** @inheritDoc */ rename(Name oldName, Name newName)416 public void rename (Name oldName, Name newName) throws NamingException 417 { 418 getURLOrDefaultInitCtx (oldName).rename (oldName, newName); 419 } 420 421 /** @inheritDoc */ rename(String oldName, String newName)422 public void rename (String oldName, String newName) throws NamingException 423 { 424 getURLOrDefaultInitCtx (oldName).rename (oldName, newName); 425 } 426 427 /** @inheritDoc */ list(Name name)428 public NamingEnumeration<NameClassPair> list (Name name) throws NamingException 429 { 430 return getURLOrDefaultInitCtx (name).list (name); 431 } 432 433 /** @inheritDoc */ list(String name)434 public NamingEnumeration<NameClassPair> list (String name) throws NamingException 435 { 436 return getURLOrDefaultInitCtx (name).list (name); 437 } 438 439 /** @inheritDoc */ listBindings(Name name)440 public NamingEnumeration<Binding> listBindings (Name name) throws NamingException 441 { 442 return getURLOrDefaultInitCtx (name).listBindings (name); 443 } 444 445 /** @inheritDoc */ listBindings(String name)446 public NamingEnumeration<Binding> listBindings (String name) throws NamingException 447 { 448 return getURLOrDefaultInitCtx (name).listBindings (name); 449 } 450 451 /** @inheritDoc */ destroySubcontext(Name name)452 public void destroySubcontext (Name name) throws NamingException 453 { 454 getURLOrDefaultInitCtx (name).destroySubcontext (name); 455 } 456 457 /** @inheritDoc */ destroySubcontext(String name)458 public void destroySubcontext (String name) throws NamingException 459 { 460 getURLOrDefaultInitCtx (name).destroySubcontext (name); 461 } 462 463 /** @inheritDoc */ createSubcontext(Name name)464 public Context createSubcontext (Name name) throws NamingException 465 { 466 return getURLOrDefaultInitCtx (name).createSubcontext (name); 467 } 468 469 /** @inheritDoc */ createSubcontext(String name)470 public Context createSubcontext (String name) throws NamingException 471 { 472 return getURLOrDefaultInitCtx (name).createSubcontext (name); 473 } 474 475 /** @inheritDoc */ lookupLink(Name name)476 public Object lookupLink (Name name) throws NamingException 477 { 478 return getURLOrDefaultInitCtx (name).lookupLink (name); 479 } 480 481 /** @inheritDoc */ lookupLink(String name)482 public Object lookupLink (String name) throws NamingException 483 { 484 return getURLOrDefaultInitCtx (name).lookupLink (name); 485 } 486 487 /** @inheritDoc */ getNameParser(Name name)488 public NameParser getNameParser (Name name) throws NamingException 489 { 490 return getURLOrDefaultInitCtx (name).getNameParser (name); 491 } 492 493 /** @inheritDoc */ getNameParser(String name)494 public NameParser getNameParser (String name) throws NamingException 495 { 496 return getURLOrDefaultInitCtx (name).getNameParser (name); 497 } 498 499 /** @inheritDoc */ composeName(Name name, Name prefix)500 public Name composeName (Name name, Name prefix) throws NamingException 501 { 502 return getURLOrDefaultInitCtx (name).composeName (name, prefix); 503 } 504 505 /** @inheritDoc */ composeName(String name, String prefix)506 public String composeName (String name, 507 String prefix) throws NamingException 508 { 509 return getURLOrDefaultInitCtx (name).composeName (name, prefix); 510 } 511 512 /** @inheritDoc */ addToEnvironment(String propName, Object propVal)513 public Object addToEnvironment (String propName, 514 Object propVal) throws NamingException 515 { 516 return myProps.put (propName, propVal); 517 } 518 519 /** @inheritDoc */ removeFromEnvironment(String propName)520 public Object removeFromEnvironment (String propName) throws NamingException 521 { 522 return myProps.remove (propName); 523 } 524 525 /** @inheritDoc */ getEnvironment()526 public Hashtable<?,?> getEnvironment () throws NamingException 527 { 528 return myProps; 529 } 530 531 /** @inheritDoc */ close()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 */ getNameInNamespace()544 public String getNameInNamespace () throws NamingException 545 { 546 throw new OperationNotSupportedException (); 547 } 548 } 549