InitialContext.java 16 KB

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