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