blob: 734d4ce0384d19beffadc06f5496091919d11bf1 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1999-2005 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package com.sun.jndi.cosnaming;
27
28import javax.naming.*;
29import javax.naming.spi.NamingManager;
30import javax.naming.spi.ResolveResult;
31
32import java.util.Hashtable;
33import java.util.Vector;
34import java.net.MalformedURLException;
35import java.net.URL;
36import java.io.InputStream;
37import java.io.InputStreamReader;
38import java.io.BufferedReader;
39import java.io.IOException;
40
41import org.omg.CosNaming.*;
42import org.omg.CosNaming.NamingContextPackage.*;
43import org.omg.CORBA.*;
44
45import com.sun.jndi.toolkit.corba.CorbaUtils;
46
47// Needed for creating default ORB
48import java.applet.Applet;
49
50/**
51 * Provides a bridge to the CosNaming server provided by
52 * JavaIDL. This class provides the InitialContext from CosNaming.
53 *
54 * @author Raj Krishnamurthy
55 * @author Rosanna Lee
56 */
57
58public class CNCtx implements javax.naming.Context {
59
60 private final static boolean debug = false;
61
62 ORB _orb; // used by ExceptionMapper and RMI/IIOP factory
63 public NamingContext _nc; // public for accessing underlying NamingContext
64 private NameComponent[] _name = null;
65
66 Hashtable _env; // used by ExceptionMapper
67 static final CNNameParser parser = new CNNameParser();
68
69 private static final String FED_PROP = "com.sun.jndi.cosnaming.federation";
70 boolean federation = false;
71
72 // Reference counter for tracking _orb references
73 OrbReuseTracker orbTracker = null;
74 int enumCount;
75 boolean isCloseCalled = false;
76
77 /**
78 * Create a CNCtx object. Gets the initial naming
79 * reference for the COS Naming Service from the ORB.
80 * The ORB can be passed in via the java.naming.corba.orb property
81 * or be created using properties in the environment properties.
82 * @param env Environment properties for initializing name service.
83 * @exception NamingException Cannot initialize ORB or naming context.
84 */
85 CNCtx(Hashtable env) throws NamingException {
86 if (env != null) {
87 env = (Hashtable) env.clone();
88 }
89 _env = env;
90 federation = "true".equals(env != null ? env.get(FED_PROP) : null);
91 initOrbAndRootContext(env);
92 }
93
94 private CNCtx() {
95 }
96
97 /**
98 * This method is used by the iiop and iiopname URL Context factories.
99 */
100 public static ResolveResult createUsingURL(String url, Hashtable env)
101 throws NamingException {
102 CNCtx ctx = new CNCtx();
103 if (env != null) {
104 env = (Hashtable) env.clone();
105 }
106 ctx._env = env;
107 String rest = ctx.initUsingUrl(
108 env != null ?
109 (org.omg.CORBA.ORB) env.get("java.naming.corba.orb")
110 : null,
111 url, env);
112
113 // rest is the INS name
114 // Return the parsed form to prevent subsequent lookup
115 // from parsing the string as a composite name
116 // The caller should be aware that a toString() of the name
117 // will yield its INS syntax, rather than a composite syntax
118 return new ResolveResult(ctx, parser.parse(rest));
119 }
120
121 /**
122 * Creates a CNCtx object which supports the javax.naming
123 * apis given a COS Naming Context object.
124 * @param orb The ORB used by this context
125 * @param tracker The ORB reuse tracker for tracking references to the
126 * orb object
127 * @param nctx The COS NamingContext object associated with this context
128 * @param name The name of this context relative to the root
129 */
130
131 CNCtx(ORB orb, OrbReuseTracker tracker, NamingContext nctx, Hashtable env,
132 NameComponent[]name)
133 throws NamingException {
134 if (orb == null || nctx == null)
135 throw new ConfigurationException(
136 "Must supply ORB or NamingContext");
137 _orb = orb;
138 orbTracker = tracker;
139 if (orbTracker != null) {
140 orbTracker.incRefCount();
141 }
142 _nc = nctx;
143 _env = env;
144 _name = name;
145 federation = "true".equals(env != null ? env.get(FED_PROP) : null);
146 }
147
148 NameComponent[] makeFullName(NameComponent[] child) {
149 if (_name == null || _name.length == 0) {
150 return child;
151 }
152 NameComponent[] answer = new NameComponent[_name.length+child.length];
153
154 // parent
155 System.arraycopy(_name, 0, answer, 0, _name.length);
156
157 // child
158 System.arraycopy(child, 0, answer, _name.length, child.length);
159 return answer;
160 }
161
162
163 public String getNameInNamespace() throws NamingException {
164 if (_name == null || _name.length == 0) {
165 return "";
166 }
167 return CNNameParser.cosNameToInsString(_name);
168 }
169
170 /**
171 * These are the URL schemes that need to be processed.
172 * IOR and corbaloc URLs can be passed directly to ORB.string_to_object()
173 */
174 private static boolean isCorbaUrl(String url) {
175 return url.startsWith("iiop://")
176 || url.startsWith("iiopname://")
177 || url.startsWith("corbaname:")
178 ;
179 }
180
181 /**
182 * Initializes the COS Naming Service.
183 * This method initializes the three instance fields:
184 * _nc : The root naming context.
185 * _orb: The ORB to use for connecting RMI/IIOP stubs and for
186 * getting the naming context (_nc) if one was not specified
187 * explicitly via PROVIDER_URL.
188 * _name: The name of the root naming context.
189 *<p>
190 * _orb is obtained from java.naming.corba.orb if it has been set.
191 * Otherwise, _orb is created using the host/port from PROVIDER_URL
192 * (if it contains an "iiop" or "iiopname" URL), or from initialization
193 * properties specified in env.
194 *<p>
195 * _nc is obtained from the IOR stored in PROVIDER_URL if it has been
196 * set and does not contain an "iiop" or "iiopname" URL. It can be
197 * a stringified IOR, "corbaloc" URL, "corbaname" URL,
198 * or a URL (such as file/http/ftp) to a location
199 * containing a stringified IOR. If PROVIDER_URL has not been
200 * set in this way, it is obtained from the result of
201 * ORB.resolve_initial_reference("NameService");
202 *<p>
203 * _name is obtained from the "iiop", "iiopname", or "corbaname" URL.
204 * It is the empty name by default.
205 *
206 * @param env Environment The possibly null environment.
207 * @exception NamingException When an error occurs while initializing the
208 * ORB or the naming context.
209 */
210 private void initOrbAndRootContext(Hashtable env) throws NamingException {
211 org.omg.CORBA.ORB inOrb = null;
212 String ncIor = null;
213
214 if (env != null) {
215 inOrb = (org.omg.CORBA.ORB) env.get("java.naming.corba.orb");
216 }
217
218 // Extract PROVIDER_URL from environment
219 String provUrl = null;
220 if (env != null) {
221 provUrl = (String)env.get(javax.naming.Context.PROVIDER_URL);
222 }
223
224 if (provUrl != null && !isCorbaUrl(provUrl)) {
225 // Initialize the root naming context by using the IOR supplied
226 // in the PROVIDER_URL
227 ncIor = getStringifiedIor(provUrl);
228
229 if (inOrb == null) {
230
231 // no ORB instance specified; create one using env and defaults
232 inOrb = CorbaUtils.getOrb(null, -1, env);
233 orbTracker = new OrbReuseTracker(inOrb);
234 }
235 setOrbAndRootContext(inOrb, ncIor);
236 } else if (provUrl != null) {
237 // Initialize the root naming context by using the URL supplied
238 // in the PROVIDER_URL
239 String insName = initUsingUrl(inOrb, provUrl, env);
240
241 // If name supplied in URL, resolve it to a NamingContext
242 if (insName.length() > 0) {
243 _name = parser.nameToCosName(parser.parse(insName));
244 try {
245 org.omg.CORBA.Object obj = _nc.resolve(_name);
246 _nc = NamingContextHelper.narrow(obj);
247 if (_nc == null) {
248 throw new ConfigurationException(insName +
249 " does not name a NamingContext");
250 }
251 } catch (org.omg.CORBA.BAD_PARAM e) {
252 throw new ConfigurationException(insName +
253 " does not name a NamingContext");
254 } catch (Exception e) {
255 throw ExceptionMapper.mapException(e, this, _name);
256 }
257 }
258 } else {
259 // No PROVIDER_URL supplied; initialize using defaults
260 if (inOrb == null) {
261
262 // No ORB instance specified; create one using env and defaults
263 inOrb = CorbaUtils.getOrb(null, -1, env);
264 orbTracker = new OrbReuseTracker(inOrb);
265 if (debug) {
266 System.err.println("Getting default ORB: " + inOrb + env);
267 }
268 }
269 setOrbAndRootContext(inOrb, (String)null);
270 }
271 }
272
273
274 private String initUsingUrl(ORB orb, String url, Hashtable env)
275 throws NamingException {
276 if (url.startsWith("iiop://") || url.startsWith("iiopname://")) {
277 return initUsingIiopUrl(orb, url, env);
278 } else {
279 return initUsingCorbanameUrl(orb, url, env);
280 }
281 }
282
283 /**
284 * Handles "iiop" and "iiopname" URLs (INS 98-10-11)
285 */
286 private String initUsingIiopUrl(ORB defOrb, String url, Hashtable env)
287 throws NamingException {
288 try {
289 IiopUrl parsedUrl = new IiopUrl(url);
290
291 Vector addrs = parsedUrl.getAddresses();
292 IiopUrl.Address addr;
293 NamingException savedException = null;
294
295 for (int i = 0; i < addrs.size(); i++) {
296 addr = (IiopUrl.Address)addrs.elementAt(i);
297
298 try {
299 if (defOrb != null) {
300 try {
301 String tmpUrl = "corbaloc:iiop:" + addr.host
302 + ":" + addr.port + "/NameService";
303 if (debug) {
304 System.err.println("Using url: " + tmpUrl);
305 }
306 org.omg.CORBA.Object rootCtx =
307 defOrb.string_to_object(tmpUrl);
308 setOrbAndRootContext(defOrb, rootCtx);
309 return parsedUrl.getStringName();
310 } catch (Exception e) {} // keep going
311 }
312
313 // Get ORB
314 if (debug) {
315 System.err.println("Getting ORB for " + addr.host
316 + " and port " + addr.port);
317 }
318
319 // Get ORB
320 ORB orb = CorbaUtils.getOrb(addr.host, addr.port, env);
321 orbTracker = new OrbReuseTracker(orb);
322
323 // Assign to fields
324 setOrbAndRootContext(orb, (String)null);
325 return parsedUrl.getStringName();
326
327 } catch (NamingException ne) {
328 savedException = ne;
329 }
330 }
331 if (savedException != null) {
332 throw savedException;
333 } else {
334 throw new ConfigurationException("Problem with URL: " + url);
335 }
336 } catch (MalformedURLException e) {
337 throw new ConfigurationException(e.getMessage());
338 }
339 }
340
341 /**
342 * Initializes using "corbaname" URL (INS 99-12-03)
343 */
344 private String initUsingCorbanameUrl(ORB orb, String url, Hashtable env)
345 throws NamingException {
346 try {
347 CorbanameUrl parsedUrl = new CorbanameUrl(url);
348
349 String corbaloc = parsedUrl.getLocation();
350 String cosName = parsedUrl.getStringName();
351
352 if (orb == null) {
353
354 // No ORB instance specified; create one using env and defaults
355 orb = CorbaUtils.getOrb(null, -1, env);
356 orbTracker = new OrbReuseTracker(orb);
357 }
358 setOrbAndRootContext(orb, corbaloc);
359
360 return parsedUrl.getStringName();
361 } catch (MalformedURLException e) {
362 throw new ConfigurationException(e.getMessage());
363 }
364 }
365
366 private void setOrbAndRootContext(ORB orb, String ncIor)
367 throws NamingException {
368 _orb = orb;
369 try {
370 org.omg.CORBA.Object ncRef;
371 if (ncIor != null) {
372 if (debug) {
373 System.err.println("Passing to string_to_object: " + ncIor);
374 }
375 ncRef = _orb.string_to_object(ncIor);
376 } else {
377 ncRef = _orb.resolve_initial_references("NameService");
378 }
379 if (debug) {
380 System.err.println("Naming Context Ref: " + ncRef);
381 }
382 _nc = NamingContextHelper.narrow(ncRef);
383 if (_nc == null) {
384 if (ncIor != null) {
385 throw new ConfigurationException(
386 "Cannot convert IOR to a NamingContext: " + ncIor);
387 } else {
388 throw new ConfigurationException(
389"ORB.resolve_initial_references(\"NameService\") does not return a NamingContext");
390 }
391 }
392 } catch (org.omg.CORBA.ORBPackage.InvalidName in) {
393 NamingException ne =
394 new ConfigurationException(
395"COS Name Service not registered with ORB under the name 'NameService'");
396 ne.setRootCause(in);
397 throw ne;
398 } catch (org.omg.CORBA.COMM_FAILURE e) {
399 NamingException ne =
400 new CommunicationException("Cannot connect to ORB");
401 ne.setRootCause(e);
402 throw ne;
403 } catch (org.omg.CORBA.BAD_PARAM e) {
404 NamingException ne = new ConfigurationException(
405 "Invalid URL or IOR: " + ncIor);
406 ne.setRootCause(e);
407 throw ne;
408 } catch (org.omg.CORBA.INV_OBJREF e) {
409 NamingException ne = new ConfigurationException(
410 "Invalid object reference: " + ncIor);
411 ne.setRootCause(e);
412 throw ne;
413 }
414 }
415
416 private void setOrbAndRootContext(ORB orb, org.omg.CORBA.Object ncRef)
417 throws NamingException {
418 _orb = orb;
419 try {
420 _nc = NamingContextHelper.narrow(ncRef);
421 if (_nc == null) {
422 throw new ConfigurationException(
423 "Cannot convert object reference to NamingContext: " + ncRef);
424 }
425 } catch (org.omg.CORBA.COMM_FAILURE e) {
426 NamingException ne =
427 new CommunicationException("Cannot connect to ORB");
428 ne.setRootCause(e);
429 throw ne;
430 }
431 }
432
433 private String getStringifiedIor(String url) throws NamingException {
434 if (url.startsWith("IOR:") || url.startsWith("corbaloc:")) {
435 return url;
436 } else {
437 InputStream in = null;
438 try {
439 URL u = new URL(url);
440 in = u.openStream();
441 if (in != null) {
442 BufferedReader bufin =
443 new BufferedReader(new InputStreamReader(in, "8859_1"));
444 String str;
445 while ((str = bufin.readLine()) != null) {
446 if (str.startsWith("IOR:")) {
447 return str;
448 }
449 }
450 }
451 } catch (IOException e) {
452 NamingException ne =
453 new ConfigurationException("Invalid URL: " + url);
454 ne.setRootCause(e);
455 throw ne;
456 } finally {
457 try {
458 if (in != null) {
459 in.close();
460 }
461 } catch (IOException e) {
462 NamingException ne =
463 new ConfigurationException("Invalid URL: " + url);
464 ne.setRootCause(e);
465 throw ne;
466 }
467 }
468 throw new ConfigurationException(url + " does not contain an IOR");
469 }
470 }
471
472
473 /**
474 * Does the job of calling the COS Naming API,
475 * resolve, and performs the exception mapping. If the resolved
476 * object is a COS Naming Context (sub-context), then this function
477 * returns a new JNDI naming context object.
478 * @param path the NameComponent[] object.
479 * @exception NotFound No objects under the name.
480 * @exception CannotProceed Unable to obtain a continuation context
481 * @exception InvalidName Name not understood.
482 * @return Resolved object returned by the COS Name Server.
483 */
484 java.lang.Object callResolve(NameComponent[] path)
485 throws NamingException {
486 try {
487 org.omg.CORBA.Object obj = _nc.resolve(path);
488 try {
489 NamingContext nc =
490 NamingContextHelper.narrow(obj);
491 if (nc != null) {
492 return new CNCtx(_orb, orbTracker, nc, _env,
493 makeFullName(path));
494 } else {
495 return obj;
496 }
497 } catch (org.omg.CORBA.SystemException e) {
498 return obj;
499 }
500 } catch (Exception e) {
501 throw ExceptionMapper.mapException(e, this, path);
502 }
503 }
504
505 /**
506 * Converts the "String" name into a CompositeName
507 * returns the object resolved by the COS Naming api,
508 * resolve. Returns the current context if the name is empty.
509 * Returns either an org.omg.CORBA.Object or javax.naming.Context object.
510 * @param name string used to resolve the object.
511 * @exception NamingException See callResolve.
512 * @return the resolved object
513 */
514 public java.lang.Object lookup(String name) throws NamingException {
515 if (debug) {
516 System.out.println("Looking up: " + name);
517 }
518 return lookup(new CompositeName(name));
519 }
520
521 /**
522 * Converts the "Name" name into a NameComponent[] object and
523 * returns the object resolved by the COS Naming api,
524 * resolve. Returns the current context if the name is empty.
525 * Returns either an org.omg.CORBA.Object or javax.naming.Context object.
526 * @param name JNDI Name used to resolve the object.
527 * @exception NamingException See callResolve.
528 * @return the resolved object
529 */
530 public java.lang.Object lookup(Name name)
531 throws NamingException {
532 if (_nc == null)
533 throw new ConfigurationException(
534 "Context does not have a corresponding NamingContext");
535 if (name.size() == 0 )
536 return this; // %%% should clone() so that env can be changed
537 NameComponent[] path = CNNameParser.nameToCosName(name);
538
539 try {
540 java.lang.Object answer = callResolve(path);
541
542 try {
543 return NamingManager.getObjectInstance(answer, name, this, _env);
544 } catch (NamingException e) {
545 throw e;
546 } catch (Exception e) {
547 NamingException ne = new NamingException(
548 "problem generating object using object factory");
549 ne.setRootCause(e);
550 throw ne;
551 }
552 } catch (CannotProceedException cpe) {
553 javax.naming.Context cctx = getContinuationContext(cpe);
554 return cctx.lookup(cpe.getRemainingName());
555 }
556 }
557
558 /**
559 * Performs bind or rebind in the context depending on whether the
560 * flag rebind is set. The only objects allowed to be bound are of
561 * types org.omg.CORBA.Object, org.omg.CosNaming.NamingContext.
562 * You can use a state factory to turn other objects (such as
563 * Remote) into these acceptable forms.
564 *
565 * Uses the COS Naming apis bind/rebind or
566 * bind_context/rebind_context.
567 * @param pth NameComponent[] object
568 * @param obj Object to be bound.
569 * @param rebind perform rebind ? if true performs a rebind.
570 * @exception NotFound No objects under the name.
571 * @exception CannotProceed Unable to obtain a continuation context
572 * @exception AlreadyBound An object is already bound to this name.
573 */
574 private void callBindOrRebind(NameComponent[] pth, Name name,
575 java.lang.Object obj, boolean rebind) throws NamingException {
576 if (_nc == null)
577 throw new ConfigurationException(
578 "Context does not have a corresponding NamingContext");
579 try {
580 // Call state factories to convert
581 obj = NamingManager.getStateToBind(obj, name, this, _env);
582
583 if (obj instanceof CNCtx) {
584 // Use naming context object reference
585 obj = ((CNCtx)obj)._nc;
586 }
587
588 if ( obj instanceof org.omg.CosNaming.NamingContext) {
589 NamingContext nobj =
590 NamingContextHelper.narrow((org.omg.CORBA.Object)obj);
591 if (rebind)
592 _nc.rebind_context(pth,nobj);
593 else
594 _nc.bind_context(pth,nobj);
595
596 } else if (obj instanceof org.omg.CORBA.Object) {
597 if (rebind)
598 _nc.rebind(pth,(org.omg.CORBA.Object)obj);
599 else
600 _nc.bind(pth,(org.omg.CORBA.Object)obj);
601 }
602 else
603 throw new IllegalArgumentException(
604 "Only instances of org.omg.CORBA.Object can be bound");
605 } catch (BAD_PARAM e) {
606 // probably narrow() failed?
607 NamingException ne = new NotContextException(name.toString());
608 ne.setRootCause(e);
609 throw ne;
610 } catch (Exception e) {
611 throw ExceptionMapper.mapException(e, this, pth);
612 }
613 }
614
615 /**
616 * Converts the "Name" name into a NameComponent[] object and
617 * performs the bind operation. Uses callBindOrRebind. Throws an
618 * invalid name exception if the name is empty. We need a name to
619 * bind the object even when we work within the current context.
620 * @param name JNDI Name object
621 * @param obj Object to be bound.
622 * @exception NamingException See callBindOrRebind
623 */
624 public void bind(Name name, java.lang.Object obj)
625 throws NamingException {
626 if (name.size() == 0 ) {
627 throw new InvalidNameException("Name is empty");
628 }
629
630 if (debug) {
631 System.out.println("Bind: " + name);
632 }
633 NameComponent[] path = CNNameParser.nameToCosName(name);
634
635 try {
636 callBindOrRebind(path, name, obj, false);
637 } catch (CannotProceedException e) {
638 javax.naming.Context cctx = getContinuationContext(e);
639 cctx.bind(e.getRemainingName(), obj);
640 }
641 }
642
643 static private javax.naming.Context
644 getContinuationContext(CannotProceedException cpe)
645 throws NamingException {
646 try {
647 return NamingManager.getContinuationContext(cpe);
648 } catch (CannotProceedException e) {
649 java.lang.Object resObj = e.getResolvedObj();
650 if (resObj instanceof Reference) {
651 Reference ref = (Reference)resObj;
652 RefAddr addr = ref.get("nns");
653 if (addr.getContent() instanceof javax.naming.Context) {
654 NamingException ne = new NameNotFoundException(
655 "No object reference bound for specified name");
656 ne.setRootCause(cpe.getRootCause());
657 ne.setRemainingName(cpe.getRemainingName());
658 throw ne;
659 }
660 }
661 throw e;
662 }
663 }
664
665 /**
666 * Converts the "String" name into a CompositeName object and
667 * performs the bind operation. Uses callBindOrRebind. Throws an
668 * invalid name exception if the name is empty.
669 * @param name string
670 * @param obj Object to be bound.
671 * @exception NamingException See callBindOrRebind
672 */
673 public void bind(String name, java.lang.Object obj) throws NamingException {
674 bind(new CompositeName(name), obj);
675 }
676
677 /**
678 * Converts the "Name" name into a NameComponent[] object and
679 * performs the rebind operation. Uses callBindOrRebind. Throws an
680 * invalid name exception if the name is empty. We must have a name
681 * to rebind the object to even if we are working within the current
682 * context.
683 * @param name string
684 * @param obj Object to be bound.
685 * @exception NamingException See callBindOrRebind
686 */
687 public void rebind(Name name, java.lang.Object obj)
688 throws NamingException {
689 if (name.size() == 0 ) {
690 throw new InvalidNameException("Name is empty");
691 }
692 NameComponent[] path = CNNameParser.nameToCosName(name);
693 try {
694 callBindOrRebind(path, name, obj, true);
695 } catch (CannotProceedException e) {
696 javax.naming.Context cctx = getContinuationContext(e);
697 cctx.rebind(e.getRemainingName(), obj);
698 }
699 }
700
701 /**
702 * Converts the "String" name into a CompositeName object and
703 * performs the rebind operation. Uses callBindOrRebind. Throws an
704 * invalid name exception if the name is an empty string.
705 * @param name string
706 * @param obj Object to be bound.
707 * @exception NamingException See callBindOrRebind
708 */
709 public void rebind(String name, java.lang.Object obj)
710 throws NamingException {
711 rebind(new CompositeName(name), obj);
712 }
713
714 /**
715 * Calls the unbind api of COS Naming and uses the exception mapper
716 * class to map the exceptions
717 * @param path NameComponent[] object
718 * @exception NotFound No objects under the name. If leaf
719 * is not found, that's OK according to the JNDI spec
720 * @exception CannotProceed Unable to obtain a continuation context
721 * @exception InvalidName Name not understood.
722 */
723 private void callUnbind(NameComponent[] path) throws NamingException {
724 if (_nc == null)
725 throw new ConfigurationException(
726 "Context does not have a corresponding NamingContext");
727 try {
728 _nc.unbind(path);
729 } catch (NotFound e) {
730 // If leaf is the one missing, return success
731 // as per JNDI spec
732
733 if (leafNotFound(e, path[path.length-1])) {
734 ; // do nothing
735 } else {
736 throw ExceptionMapper.mapException(e, this, path);
737 }
738 } catch (Exception e) {
739 throw ExceptionMapper.mapException(e, this, path);
740 }
741 }
742
743 private boolean leafNotFound(NotFound e, NameComponent leaf) {
744
745 // This test is not foolproof because some name servers
746 // always just return one component in rest_of_name
747 // so you might not be able to tell whether that is
748 // the leaf (e.g. aa/aa/aa, which one is missing?)
749
750 NameComponent rest;
751 return e.why.value() == NotFoundReason._missing_node &&
752 e.rest_of_name.length == 1 &&
753 (rest=e.rest_of_name[0]).id.equals(leaf.id) &&
754 (rest.kind == leaf.kind ||
755 (rest.kind != null && rest.kind.equals(leaf.kind)));
756 }
757
758 /**
759 * Converts the "String" name into a CompositeName object and
760 * performs the unbind operation. Uses callUnbind. If the name is
761 * empty, throws an invalid name exception. Do we unbind the
762 * current context (JNDI spec says work with the current context if
763 * the name is empty) ?
764 * @param name string
765 * @exception NamingException See callUnbind
766 */
767 public void unbind(String name) throws NamingException {
768 unbind(new CompositeName(name));
769 }
770
771 /**
772 * Converts the "Name" name into a NameComponent[] object and
773 * performs the unbind operation. Uses callUnbind. Throws an
774 * invalid name exception if the name is empty.
775 * @param name string
776 * @exception NamingException See callUnbind
777 */
778 public void unbind(Name name)
779 throws NamingException {
780 if (name.size() == 0 )
781 throw new InvalidNameException("Name is empty");
782 NameComponent[] path = CNNameParser.nameToCosName(name);
783 try {
784 callUnbind(path);
785 } catch (CannotProceedException e) {
786 javax.naming.Context cctx = getContinuationContext(e);
787 cctx.unbind(e.getRemainingName());
788 }
789 }
790
791 /**
792 * Renames an object. Since COS Naming does not support a rename
793 * api, this method unbinds the object with the "oldName" and
794 * creates a new binding.
795 * @param oldName string, existing name for the binding.
796 * @param newName string, name used to replace.
797 * @exception NamingException See bind
798 */
799 public void rename(String oldName,String newName)
800 throws NamingException {
801 rename(new CompositeName(oldName), new CompositeName(newName));
802 }
803
804 /**
805 * Renames an object. Since COS Naming does not support a rename
806 * api, this method unbinds the object with the "oldName" and
807 * creates a new binding.
808 * @param oldName JNDI Name, existing name for the binding.
809 * @param newName JNDI Name, name used to replace.
810 * @exception NamingException See bind
811 */
812 public void rename(Name oldName,Name newName)
813 throws NamingException {
814 if (_nc == null)
815 throw new ConfigurationException(
816 "Context does not have a corresponding NamingContext");
817 if (oldName.size() == 0 || newName.size() == 0)
818 throw new InvalidNameException("One or both names empty");
819 java.lang.Object obj = lookup(oldName);
820 bind(newName,obj);
821 unbind(oldName);
822 }
823
824 /**
825 * Returns a NameClassEnumeration object which has a list of name
826 * class pairs. Lists the current context if the name is empty.
827 * @param name string
828 * @exception NamingException All exceptions thrown by lookup
829 * with a non-null argument
830 * @return a list of name-class objects as a NameClassEnumeration.
831 */
832 public NamingEnumeration list(String name) throws NamingException {
833 return list(new CompositeName(name));
834 }
835
836 /**
837 * Returns a NameClassEnumeration object which has a list of name
838 * class pairs. Lists the current context if the name is empty.
839 * @param name JNDI Name
840 * @exception NamingException All exceptions thrown by lookup
841 * @return a list of name-class objects as a NameClassEnumeration.
842 */
843 public NamingEnumeration list(Name name)
844 throws NamingException {
845 return listBindings(name);
846 }
847
848 /**
849 * Returns a BindingEnumeration object which has a list of name
850 * object pairs. Lists the current context if the name is empty.
851 * @param name string
852 * @exception NamingException all exceptions returned by lookup
853 * @return a list of bindings as a BindingEnumeration.
854 */
855 public NamingEnumeration listBindings(String name)
856 throws NamingException {
857 return listBindings(new CompositeName(name));
858 }
859
860 /**
861 * Returns a BindingEnumeration object which has a list of name
862 * class pairs. Lists the current context if the name is empty.
863 * @param name JNDI Name
864 * @exception NamingException all exceptions returned by lookup.
865 * @return a list of bindings as a BindingEnumeration.
866 */
867 public NamingEnumeration listBindings(Name name)
868 throws NamingException {
869 if (_nc == null)
870 throw new ConfigurationException(
871 "Context does not have a corresponding NamingContext");
872 if (name.size() > 0) {
873 try {
874 java.lang.Object obj = lookup(name);
875 if (obj instanceof CNCtx) {
876 return new CNBindingEnumeration(
877 (CNCtx) obj, true, _env);
878 } else {
879 throw new NotContextException(name.toString());
880 }
881 } catch (NamingException ne) {
882 throw ne;
883 } catch (BAD_PARAM e) {
884 NamingException ne =
885 new NotContextException(name.toString());
886 ne.setRootCause(e);
887 throw ne;
888 }
889 }
890 return new CNBindingEnumeration(this, false, _env);
891 }
892
893 /**
894 * Calls the destroy on the COS Naming Server
895 * @param nc The NamingContext object to use.
896 * @exception NotEmpty when the context is not empty and cannot be destroyed.
897 */
898 private void callDestroy(NamingContext nc)
899 throws NamingException {
900 if (_nc == null)
901 throw new ConfigurationException(
902 "Context does not have a corresponding NamingContext");
903 try {
904 nc.destroy();
905 } catch (Exception e) {
906 throw ExceptionMapper.mapException(e, this, null);
907 }
908 }
909
910 /**
911 * Uses the callDestroy function to destroy the context. If name is
912 * empty destroys the current context.
913 * @param name string
914 * @exception OperationNotSupportedException when list is invoked
915 * with a non-null argument
916 */
917 public void destroySubcontext(String name) throws NamingException {
918 destroySubcontext(new CompositeName(name));
919 }
920
921 /**
922 * Uses the callDestroy function to destroy the context. Destroys
923 * the current context if name is empty.
924 * @param name JNDI Name
925 * @exception OperationNotSupportedException when list is invoked
926 * with a non-null argument
927 */
928 public void destroySubcontext(Name name)
929 throws NamingException {
930 if (_nc == null)
931 throw new ConfigurationException(
932 "Context does not have a corresponding NamingContext");
933 NamingContext the_nc = _nc;
934 NameComponent[] path = CNNameParser.nameToCosName(name);
935 if ( name.size() > 0) {
936 try {
937 javax.naming.Context ctx =
938 (javax.naming.Context) callResolve(path);
939 CNCtx cnc = (CNCtx)ctx;
940 the_nc = cnc._nc;
941 cnc.close(); //remove the reference to the context
942 } catch (ClassCastException e) {
943 throw new NotContextException(name.toString());
944 } catch (CannotProceedException e) {
945 javax.naming.Context cctx = getContinuationContext(e);
946 cctx.destroySubcontext(e.getRemainingName());
947 return;
948 } catch (NameNotFoundException e) {
949 // If leaf is the one missing, return success
950 // as per JNDI spec
951
952 if (e.getRootCause() instanceof NotFound &&
953 leafNotFound((NotFound)e.getRootCause(),
954 path[path.length-1])) {
955 return; // leaf missing OK
956 }
957 throw e;
958 } catch (NamingException e) {
959 throw e;
960 }
961 }
962 callDestroy(the_nc);
963 callUnbind(path);
964 }
965
966 /**
967 * Calls the bind_new_context COS naming api to create a new subcontext.
968 * @param path NameComponent[] object
969 * @exception NotFound No objects under the name.
970 * @exception CannotProceed Unable to obtain a continuation context
971 * @exception InvalidName Name not understood.
972 * @exception AlreadyBound An object is already bound to this name.
973 * @return the new context object.
974 */
975 private javax.naming.Context callBindNewContext(NameComponent[] path)
976 throws NamingException {
977 if (_nc == null)
978 throw new ConfigurationException(
979 "Context does not have a corresponding NamingContext");
980 try {
981 NamingContext nctx = _nc.bind_new_context(path);
982 return new CNCtx(_orb, orbTracker, nctx, _env,
983 makeFullName(path));
984 } catch (Exception e) {
985 throw ExceptionMapper.mapException(e, this, path);
986 }
987 }
988
989 /**
990 * Uses the callBindNewContext convenience function to create a new
991 * context. Throws an invalid name exception if the name is empty.
992 * @param name string
993 * @exception NamingException See callBindNewContext
994 * @return the new context object.
995 */
996 public javax.naming.Context createSubcontext(String name)
997 throws NamingException {
998 return createSubcontext(new CompositeName(name));
999 }
1000
1001 /**
1002 * Uses the callBindNewContext convenience function to create a new
1003 * context. Throws an invalid name exception if the name is empty.
1004 * @param name string
1005 * @exception NamingException See callBindNewContext
1006 * @return the new context object.
1007 */
1008 public javax.naming.Context createSubcontext(Name name)
1009 throws NamingException {
1010 if (name.size() == 0 )
1011 throw new InvalidNameException("Name is empty");
1012 NameComponent[] path = CNNameParser.nameToCosName(name);
1013 try {
1014 return callBindNewContext(path);
1015 } catch (CannotProceedException e) {
1016 javax.naming.Context cctx = getContinuationContext(e);
1017 return cctx.createSubcontext(e.getRemainingName());
1018 }
1019 }
1020
1021 /**
1022 * Is mapped to resolve in the COS Naming api.
1023 * @param name string
1024 * @exception NamingException See lookup.
1025 * @return the resolved object.
1026 */
1027 public java.lang.Object lookupLink(String name) throws NamingException {
1028 return lookupLink(new CompositeName(name));
1029 }
1030
1031 /**
1032 * Is mapped to resolve in the COS Naming api.
1033 * @param name string
1034 * @exception NamingException See lookup.
1035 * @return the resolved object.
1036 */
1037 public java.lang.Object lookupLink(Name name) throws NamingException {
1038 return lookup(name);
1039 }
1040
1041 /**
1042 * Allow access to the name parser object.
1043 * @param String JNDI name, is ignored since there is only one Name
1044 * Parser object.
1045 * @exception NamingException --
1046 * @return NameParser object
1047 */
1048 public NameParser getNameParser(String name) throws NamingException {
1049 return parser;
1050 }
1051
1052 /**
1053 * Allow access to the name parser object.
1054 * @param Name JNDI name, is ignored since there is only one Name
1055 * Parser object.
1056 * @exception NamingException --
1057 * @return NameParser object
1058 */
1059 public NameParser getNameParser(Name name) throws NamingException {
1060 return parser;
1061 }
1062
1063 /**
1064 * Returns the current environment.
1065 * @return Environment.
1066 */
1067 public Hashtable getEnvironment() throws NamingException {
1068 if (_env == null) {
1069 return new Hashtable(5, 0.75f);
1070 } else {
1071 return (Hashtable)_env.clone();
1072 }
1073 }
1074
1075 public String composeName(String name, String prefix) throws NamingException {
1076 return composeName(new CompositeName(name),
1077 new CompositeName(prefix)).toString();
1078 }
1079
1080 public Name composeName(Name name, Name prefix) throws NamingException {
1081 Name result = (Name)prefix.clone();
1082 return result.addAll(name);
1083 }
1084
1085 /**
1086 * Adds to the environment for the current context.
1087 * Record change but do not reinitialize ORB.
1088 *
1089 * @param propName The property name.
1090 * @param propVal The ORB.
1091 * @return the previous value of this property if any.
1092 */
1093 public java.lang.Object addToEnvironment(String propName,
1094 java.lang.Object propValue)
1095 throws NamingException {
1096 if (_env == null) {
1097 _env = new Hashtable(7, 0.75f);
1098 } else {
1099 // copy-on-write
1100 _env = (Hashtable)_env.clone();
1101 }
1102
1103 return _env.put(propName, propValue);
1104 }
1105
1106 // Record change but do not reinitialize ORB
1107 public java.lang.Object removeFromEnvironment(String propName)
1108 throws NamingException {
1109 if (_env != null && _env.get(propName) != null) {
1110 // copy-on-write
1111 _env = (Hashtable)_env.clone();
1112 return _env.remove(propName);
1113 }
1114 return null;
1115 }
1116
1117 synchronized public void incEnumCount() {
1118 if (orbTracker == null) {
1119 return;
1120 }
1121 enumCount++;
1122 if (debug) {
1123 System.out.println("incEnumCount, new count:" + enumCount);
1124 }
1125 }
1126
1127 synchronized public void decEnumCount()
1128 throws NamingException {
1129 if (orbTracker == null) {
1130 return;
1131 }
1132 enumCount--;
1133 if (debug) {
1134 System.out.println("decEnumCount, new count:" + enumCount +
1135 " isCloseCalled:" + isCloseCalled);
1136 }
1137 if ((enumCount == 0) && isCloseCalled) {
1138 close();
1139 }
1140 }
1141
1142 synchronized public void close() throws NamingException {
1143 if (orbTracker == null) {
1144 return;
1145 }
1146 if (enumCount > 0) {
1147 isCloseCalled = true;
1148 return;
1149 }
1150 orbTracker.decRefCount();
1151 }
1152
1153 protected void finalize() {
1154 try {
1155 close();
1156 } catch (NamingException e) {
1157 // ignore failures
1158 }
1159 }
1160}