1 /* 2 * Copyright (c) 1999, 2012, 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 /* 62 * Implement one shared ORB among all CNCtx. However, there is a public constructor 63 * accepting an ORB, so we need the option of using a given ORB. 64 */ 65 private static ORB _defaultOrb; 66 ORB _orb; // used by ExceptionMapper and RMI/IIOP factory 67 public NamingContext _nc; // public for accessing underlying NamingContext 68 69 private synchronized static ORB getDefaultOrb() { 70 if (_defaultOrb == null) { 71 _defaultOrb = CorbaUtils.getOrb(null, -1, 72 new Hashtable<String, java.lang.Object>()); 73 } 74 return _defaultOrb; 75 } 76 77 private NameComponent[] _name = null; 78 79 Hashtable<String, java.lang.Object> _env; // used by ExceptionMapper 80 static final CNNameParser parser = new CNNameParser(); 81 82 private static final String FED_PROP = "com.sun.jndi.cosnaming.federation"; 83 boolean federation = false; 84 85 // Reference counter for tracking _orb references 86 OrbReuseTracker orbTracker = null; 87 int enumCount; 88 boolean isCloseCalled = false; 89 90 /** 91 * Create a CNCtx object. Gets the initial naming 92 * reference for the COS Naming Service from the ORB. 93 * The ORB can be passed in via the java.naming.corba.orb property 94 * or be created using properties in the environment properties. 95 * @param env Environment properties for initializing name service. 96 * @exception NamingException Cannot initialize ORB or naming context. 97 */ 98 @SuppressWarnings("unchecked") 99 CNCtx(Hashtable<?,?> env) throws NamingException { 100 if (env != null) { 101 env = (Hashtable<?,?>)env.clone(); 102 } 103 _env = (Hashtable<String, java.lang.Object>)env; 104 federation = "true".equals(env != null ? env.get(FED_PROP) : null); 105 initOrbAndRootContext(env); 106 } 107 108 private CNCtx() { 109 } 110 111 /** 112 * This method is used by the iiop and iiopname URL Context factories. 113 */ 114 @SuppressWarnings("unchecked") 115 public static ResolveResult createUsingURL(String url, Hashtable<?,?> env) 116 throws NamingException { 117 CNCtx ctx = new CNCtx(); 118 if (env != null) { 119 env = (Hashtable<?,?>) env.clone(); 120 } 121 ctx._env = (Hashtable<String, java.lang.Object>)env; 122 String rest = ctx.initUsingUrl( 123 env != null ? 124 (org.omg.CORBA.ORB) env.get("java.naming.corba.orb") 125 : null, 126 url, env); 127 128 // rest is the INS name 129 // Return the parsed form to prevent subsequent lookup 130 // from parsing the string as a composite name 131 // The caller should be aware that a toString() of the name, 132 // which came from the environment will yield its INS syntax, 133 // rather than a composite syntax 134 return new ResolveResult(ctx, parser.parse(rest)); 135 } 136 137 /** 138 * Creates a CNCtx object which supports the javax.naming 139 * apis given a COS Naming Context object. 140 * @param orb The ORB used by this context 141 * @param tracker The ORB reuse tracker for tracking references to the 142 * orb object 143 * @param nctx The COS NamingContext object associated with this context 144 * @param name The name of this context relative to the root 145 */ 146 147 CNCtx(ORB orb, OrbReuseTracker tracker, NamingContext nctx, 148 Hashtable<String, java.lang.Object> env, NameComponent[]name) 149 throws NamingException { 150 if (orb == null || nctx == null) 151 throw new ConfigurationException( 152 "Must supply ORB or NamingContext"); 153 if (orb != null) { 154 _orb = orb; 155 } else { 156 _orb = getDefaultOrb(); 157 } 158 _nc = nctx; 159 _env = env; 160 _name = name; 161 federation = "true".equals(env != null ? env.get(FED_PROP) : null); 162 } 163 164 NameComponent[] makeFullName(NameComponent[] child) { 165 if (_name == null || _name.length == 0) { 166 return child; 167 } 168 NameComponent[] answer = new NameComponent[_name.length+child.length]; 169 170 // parent 171 System.arraycopy(_name, 0, answer, 0, _name.length); 172 173 // child 174 System.arraycopy(child, 0, answer, _name.length, child.length); 175 return answer; 176 } 177 178 179 public String getNameInNamespace() throws NamingException { 180 if (_name == null || _name.length == 0) { 181 return ""; 182 } 183 return CNNameParser.cosNameToInsString(_name); 184 } 185 186 /** 187 * These are the URL schemes that need to be processed. 188 * IOR and corbaloc URLs can be passed directly to ORB.string_to_object() 189 */ 190 private static boolean isCorbaUrl(String url) { 191 return url.startsWith("iiop://") 192 || url.startsWith("iiopname://") 193 || url.startsWith("corbaname:") 194 ; 195 } 196 197 /** 198 * Initializes the COS Naming Service. 199 * This method initializes the three instance fields: 200 * _nc : The root naming context. 201 * _orb: The ORB to use for connecting RMI/IIOP stubs and for 202 * getting the naming context (_nc) if one was not specified 203 * explicitly via PROVIDER_URL. 204 * _name: The name of the root naming context. 205 *<p> 206 * _orb is obtained from java.naming.corba.orb if it has been set. 207 * Otherwise, _orb is created using the host/port from PROVIDER_URL 208 * (if it contains an "iiop" or "iiopname" URL), or from initialization 209 * properties specified in env. 210 *<p> 211 * _nc is obtained from the IOR stored in PROVIDER_URL if it has been 212 * set and does not contain an "iiop" or "iiopname" URL. It can be 213 * a stringified IOR, "corbaloc" URL, "corbaname" URL, 214 * or a URL (such as file/http/ftp) to a location 215 * containing a stringified IOR. If PROVIDER_URL has not been 216 * set in this way, it is obtained from the result of 217 * ORB.resolve_initial_reference("NameService"); 218 *<p> 219 * _name is obtained from the "iiop", "iiopname", or "corbaname" URL. 220 * It is the empty name by default. 221 * 222 * @param env Environment The possibly null environment. 223 * @exception NamingException When an error occurs while initializing the 224 * ORB or the naming context. 225 */ 226 private void initOrbAndRootContext(Hashtable<?,?> env) throws NamingException { 227 org.omg.CORBA.ORB inOrb = null; 228 String ncIor = null; 229 230 if (inOrb == null && env != null) { 231 inOrb = (org.omg.CORBA.ORB) env.get("java.naming.corba.orb"); 232 } 233 234 if (inOrb == null) 235 inOrb = getDefaultOrb(); // will create a default ORB if none exists 236 237 // Extract PROVIDER_URL from environment 238 String provUrl = null; 239 if (env != null) { 240 provUrl = (String)env.get(javax.naming.Context.PROVIDER_URL); 241 } 242 243 if (provUrl != null && !isCorbaUrl(provUrl)) { 244 // Initialize the root naming context by using the IOR supplied 245 // in the PROVIDER_URL 246 ncIor = getStringifiedIor(provUrl); 247 setOrbAndRootContext(inOrb, ncIor); 248 } else if (provUrl != null) { 249 // Initialize the root naming context by using the URL supplied 250 // in the PROVIDER_URL 251 String insName = initUsingUrl(inOrb, provUrl, env); 252 253 // If name supplied in URL, resolve it to a NamingContext 254 if (insName.length() > 0) { 255 _name = CNNameParser.nameToCosName(parser.parse(insName)); 256 try { 257 org.omg.CORBA.Object obj = _nc.resolve(_name); 258 _nc = NamingContextHelper.narrow(obj); 259 if (_nc == null) { 260 throw new ConfigurationException(insName + 261 " does not name a NamingContext"); 262 } 263 } catch (org.omg.CORBA.BAD_PARAM e) { 264 throw new ConfigurationException(insName + 265 " does not name a NamingContext"); 266 } catch (Exception e) { 267 throw ExceptionMapper.mapException(e, this, _name); 268 } 269 } 270 } else { 271 // No PROVIDER_URL supplied; initialize using defaults 272 if (debug) { 273 System.err.println("Getting default ORB: " + inOrb + env); 274 } 275 setOrbAndRootContext(inOrb, (String)null); 276 } 277 } 278 279 280 private String initUsingUrl(ORB orb, String url, Hashtable<?,?> env) 281 throws NamingException { 282 if (url.startsWith("iiop://") || url.startsWith("iiopname://")) { 283 return initUsingIiopUrl(orb, url, env); 284 } else { 285 return initUsingCorbanameUrl(orb, url, env); 286 } 287 } 288 289 /** 290 * Handles "iiop" and "iiopname" URLs (INS 98-10-11) 291 */ 292 private String initUsingIiopUrl(ORB defOrb, String url, Hashtable<?,?> env) 293 throws NamingException { 294 295 if (defOrb == null) 296 defOrb = getDefaultOrb(); 297 298 try { 299 IiopUrl parsedUrl = new IiopUrl(url); 300 301 NamingException savedException = null; 302 303 for (IiopUrl.Address addr : parsedUrl.getAddresses()) { 304 305 try { 306 try { 307 String tmpUrl = "corbaloc:iiop:" + addr.host 308 + ":" + addr.port + "/NameService"; 309 if (debug) { 310 System.err.println("Using url: " + tmpUrl); 311 } 312 org.omg.CORBA.Object rootCtx = 313 defOrb.string_to_object(tmpUrl); 314 setOrbAndRootContext(defOrb, rootCtx); 315 return parsedUrl.getStringName(); 316 } catch (Exception e) {} // keep going 317 318 // Get ORB 319 if (debug) { 320 System.err.println("Getting ORB for " + addr.host 321 + " and port " + addr.port); 322 } 323 324 // Assign to fields 325 setOrbAndRootContext(defOrb, (String)null); 326 return parsedUrl.getStringName(); 327 328 } catch (NamingException ne) { 329 savedException = ne; 330 } 331 } 332 if (savedException != null) { 333 throw savedException; 334 } else { 335 throw new ConfigurationException("Problem with URL: " + url); 336 } 337 } catch (MalformedURLException e) { 338 throw new ConfigurationException(e.getMessage()); 339 } 340 } 341 342 /** 343 * Initializes using "corbaname" URL (INS 99-12-03) 344 */ 345 private String initUsingCorbanameUrl(ORB orb, String url, Hashtable<?,?> env) 346 throws NamingException { 347 348 if (orb == null) 349 orb = getDefaultOrb(); 350 351 try { 352 CorbanameUrl parsedUrl = new CorbanameUrl(url); 353 354 String corbaloc = parsedUrl.getLocation(); 355 String cosName = parsedUrl.getStringName(); 356 357 setOrbAndRootContext(orb, corbaloc); 358 359 return parsedUrl.getStringName(); 360 } catch (MalformedURLException e) { 361 throw new ConfigurationException(e.getMessage()); 362 } 363 } 364 365 private void setOrbAndRootContext(ORB orb, String ncIor) 366 throws NamingException { 367 _orb = orb; 368 try { 369 org.omg.CORBA.Object ncRef; 370 if (ncIor != null) { 371 if (debug) { 372 System.err.println("Passing to string_to_object: " + ncIor); 373 } 374 ncRef = _orb.string_to_object(ncIor); 375 } else { 376 ncRef = _orb.resolve_initial_references("NameService"); 377 } 378 if (debug) { 379 System.err.println("Naming Context Ref: " + ncRef); 380 } 381 _nc = NamingContextHelper.narrow(ncRef); 382 if (_nc == null) { 383 if (ncIor != null) { 384 throw new ConfigurationException( 385 "Cannot convert IOR to a NamingContext: " + ncIor); 386 } else { 387 throw new ConfigurationException( 388 "ORB.resolve_initial_references(\"NameService\") does not return a NamingContext"); 389 } 390 } 391 } catch (org.omg.CORBA.ORBPackage.InvalidName in) { 392 NamingException ne = 393 new ConfigurationException( 394 "COS Name Service not registered with ORB under the name 'NameService'"); 395 ne.setRootCause(in); 396 throw ne; 397 } catch (org.omg.CORBA.COMM_FAILURE e) { 398 NamingException ne = 399 new CommunicationException("Cannot connect to ORB"); 400 ne.setRootCause(e); 401 throw ne; 402 } catch (org.omg.CORBA.BAD_PARAM e) { 403 NamingException ne = new ConfigurationException( 404 "Invalid URL or IOR: " + ncIor); 405 ne.setRootCause(e); 406 throw ne; 407 } catch (org.omg.CORBA.INV_OBJREF e) { 408 NamingException ne = new ConfigurationException( 409 "Invalid object reference: " + ncIor); 410 ne.setRootCause(e); 411 throw ne; 412 } 413 } 414 415 private void setOrbAndRootContext(ORB orb, org.omg.CORBA.Object ncRef) 416 throws NamingException { 417 _orb = orb; 418 try { 419 _nc = NamingContextHelper.narrow(ncRef); 420 if (_nc == null) { 421 throw new ConfigurationException( 422 "Cannot convert object reference to NamingContext: " + ncRef); 423 } 424 } catch (org.omg.CORBA.COMM_FAILURE e) { 425 NamingException ne = 426 new CommunicationException("Cannot connect to ORB"); 427 ne.setRootCause(e); 428 throw ne; 429 } 430 } 431 432 private String getStringifiedIor(String url) throws NamingException { 433 if (url.startsWith("IOR:") || url.startsWith("corbaloc:")) { 434 return url; 435 } else { 436 InputStream in = null; 437 try { 438 URL u = new URL(url); 439 in = u.openStream(); 440 if (in != null) { 441 BufferedReader bufin = 442 new BufferedReader(new InputStreamReader(in, "8859_1")); 443 String str; 444 while ((str = bufin.readLine()) != null) { 445 if (str.startsWith("IOR:")) { 446 return str; 447 } 448 } 449 } 450 } catch (IOException e) { 451 NamingException ne = 452 new ConfigurationException("Invalid URL: " + url); 453 ne.setRootCause(e); 454 throw ne; 455 } finally { 456 try { 457 if (in != null) { 458 in.close(); 459 } 460 } catch (IOException e) { 461 NamingException ne = 462 new ConfigurationException("Invalid URL: " + url); 463 ne.setRootCause(e); 464 throw ne; 465 } 466 } 467 throw new ConfigurationException(url + " does not contain an IOR"); 468 } 469 } 470 471 472 /** 473 * Does the job of calling the COS Naming API, 474 * resolve, and performs the exception mapping. If the resolved 475 * object is a COS Naming Context (sub-context), then this function 476 * returns a new JNDI naming context object. 477 * @param path the NameComponent[] object. 478 * @exception NotFound No objects under the name. 479 * @exception CannotProceed Unable to obtain a continuation context 480 * @exception InvalidName Name not understood. 481 * @return Resolved object returned by the COS Name Server. 482 */ 483 java.lang.Object callResolve(NameComponent[] path) 484 throws NamingException { 485 try { 486 org.omg.CORBA.Object obj = _nc.resolve(path); 487 try { 488 NamingContext nc = 489 NamingContextHelper.narrow(obj); 490 if (nc != null) { 491 return new CNCtx(_orb, orbTracker, nc, _env, 492 makeFullName(path)); 493 } else { 494 return obj; 495 } 496 } catch (org.omg.CORBA.SystemException e) { 497 return obj; 498 } 499 } catch (Exception e) { 500 throw ExceptionMapper.mapException(e, this, path); 501 } 502 } 503 504 /** 505 * Converts the "String" name into a CompositeName 506 * returns the object resolved by the COS Naming api, 507 * resolve. Returns the current context if the name is empty. 508 * Returns either an org.omg.CORBA.Object or javax.naming.Context object. 509 * @param name string used to resolve the object. 510 * @exception NamingException See callResolve. 511 * @return the resolved object 512 */ 513 public java.lang.Object lookup(String name) throws NamingException { 514 if (debug) { 515 System.out.println("Looking up: " + name); 516 } 517 return lookup(new CompositeName(name)); 518 } 519 520 /** 521 * Converts the "Name" name into a NameComponent[] object and 522 * returns the object resolved by the COS Naming api, 523 * resolve. Returns the current context if the name is empty. 524 * Returns either an org.omg.CORBA.Object or javax.naming.Context object. 525 * @param name JNDI Name used to resolve the object. 526 * @exception NamingException See callResolve. 527 * @return the resolved object 528 */ 529 public java.lang.Object lookup(Name name) 530 throws NamingException { 531 if (_nc == null) 532 throw new ConfigurationException( 533 "Context does not have a corresponding NamingContext"); 534 if (name.size() == 0 ) 535 return this; // %%% should clone() so that env can be changed 536 NameComponent[] path = CNNameParser.nameToCosName(name); 537 538 try { 539 java.lang.Object answer = callResolve(path); 540 541 try { 542 return NamingManager.getObjectInstance(answer, name, this, _env); 543 } catch (NamingException e) { 544 throw e; 545 } catch (Exception e) { 546 NamingException ne = new NamingException( 547 "problem generating object using object factory"); 548 ne.setRootCause(e); 549 throw ne; 550 } 551 } catch (CannotProceedException cpe) { 552 javax.naming.Context cctx = getContinuationContext(cpe); 553 return cctx.lookup(cpe.getRemainingName()); 554 } 555 } 556 557 /** 558 * Performs bind or rebind in the context depending on whether the 559 * flag rebind is set. The only objects allowed to be bound are of 560 * types org.omg.CORBA.Object, org.omg.CosNaming.NamingContext. 561 * You can use a state factory to turn other objects (such as 562 * Remote) into these acceptable forms. 563 * 564 * Uses the COS Naming apis bind/rebind or 565 * bind_context/rebind_context. 566 * @param pth NameComponent[] object 567 * @param obj Object to be bound. 568 * @param rebind perform rebind ? if true performs a rebind. 569 * @exception NotFound No objects under the name. 570 * @exception CannotProceed Unable to obtain a continuation context 571 * @exception AlreadyBound An object is already bound to this name. 572 */ 573 private void callBindOrRebind(NameComponent[] pth, Name name, 574 java.lang.Object obj, boolean rebind) throws NamingException { 575 if (_nc == null) 576 throw new ConfigurationException( 577 "Context does not have a corresponding NamingContext"); 578 try { 579 // Call state factories to convert 580 obj = NamingManager.getStateToBind(obj, name, this, _env); 581 582 if (obj instanceof CNCtx) { 583 // Use naming context object reference 584 obj = ((CNCtx)obj)._nc; 585 } 586 587 if ( obj instanceof org.omg.CosNaming.NamingContext) { 588 NamingContext nobj = 589 NamingContextHelper.narrow((org.omg.CORBA.Object)obj); 590 if (rebind) 591 _nc.rebind_context(pth,nobj); 592 else 593 _nc.bind_context(pth,nobj); 594 595 } else if (obj instanceof org.omg.CORBA.Object) { 596 if (rebind) 597 _nc.rebind(pth,(org.omg.CORBA.Object)obj); 598 else 599 _nc.bind(pth,(org.omg.CORBA.Object)obj); 600 } 601 else 602 throw new IllegalArgumentException( 603 "Only instances of org.omg.CORBA.Object can be bound"); 604 } catch (BAD_PARAM e) { 605 // probably narrow() failed? 606 NamingException ne = new NotContextException(name.toString()); 607 ne.setRootCause(e); 608 throw ne; 609 } catch (Exception e) { 610 throw ExceptionMapper.mapException(e, this, pth); 611 } 612 } 613 614 /** 615 * Converts the "Name" name into a NameComponent[] object and 616 * performs the bind operation. Uses callBindOrRebind. Throws an 617 * invalid name exception if the name is empty. We need a name to 618 * bind the object even when we work within the current context. 619 * @param name JNDI Name object 620 * @param obj Object to be bound. 621 * @exception NamingException See callBindOrRebind 622 */ 623 public void bind(Name name, java.lang.Object obj) 624 throws NamingException { 625 if (name.size() == 0 ) { 626 throw new InvalidNameException("Name is empty"); 627 } 628 629 if (debug) { 630 System.out.println("Bind: " + name); 631 } 632 NameComponent[] path = CNNameParser.nameToCosName(name); 633 634 try { 635 callBindOrRebind(path, name, obj, false); 636 } catch (CannotProceedException e) { 637 javax.naming.Context cctx = getContinuationContext(e); 638 cctx.bind(e.getRemainingName(), obj); 639 } 640 } 641 642 static private javax.naming.Context 643 getContinuationContext(CannotProceedException cpe) 644 throws NamingException { 645 try { 646 return NamingManager.getContinuationContext(cpe); 647 } catch (CannotProceedException e) { 648 java.lang.Object resObj = e.getResolvedObj(); 649 if (resObj instanceof Reference) { 650 Reference ref = (Reference)resObj; 651 RefAddr addr = ref.get("nns"); 652 if (addr.getContent() instanceof javax.naming.Context) { 653 NamingException ne = new NameNotFoundException( 654 "No object reference bound for specified name"); 655 ne.setRootCause(cpe.getRootCause()); 656 ne.setRemainingName(cpe.getRemainingName()); 657 throw ne; 658 } 659 } 660 throw e; 661 } 662 } 663 664 /** 665 * Converts the "String" name into a CompositeName object and 666 * performs the bind operation. Uses callBindOrRebind. Throws an 667 * invalid name exception if the name is empty. 668 * @param name string 669 * @param obj Object to be bound. 670 * @exception NamingException See callBindOrRebind 671 */ 672 public void bind(String name, java.lang.Object obj) throws NamingException { 673 bind(new CompositeName(name), obj); 674 } 675 676 /** 677 * Converts the "Name" name into a NameComponent[] object and 678 * performs the rebind operation. Uses callBindOrRebind. Throws an 679 * invalid name exception if the name is empty. We must have a name 680 * to rebind the object to even if we are working within the current 681 * context. 682 * @param name string 683 * @param obj Object to be bound. 684 * @exception NamingException See callBindOrRebind 685 */ 686 public void rebind(Name name, java.lang.Object obj) 687 throws NamingException { 688 if (name.size() == 0 ) { 689 throw new InvalidNameException("Name is empty"); 690 } 691 NameComponent[] path = CNNameParser.nameToCosName(name); 692 try { 693 callBindOrRebind(path, name, obj, true); 694 } catch (CannotProceedException e) { 695 javax.naming.Context cctx = getContinuationContext(e); 696 cctx.rebind(e.getRemainingName(), obj); 697 } 698 } 699 700 /** 701 * Converts the "String" name into a CompositeName object and 702 * performs the rebind operation. Uses callBindOrRebind. Throws an 703 * invalid name exception if the name is an empty string. 704 * @param name string 705 * @param obj Object to be bound. 706 * @exception NamingException See callBindOrRebind 707 */ 708 public void rebind(String name, java.lang.Object obj) 709 throws NamingException { 710 rebind(new CompositeName(name), obj); 711 } 712 713 /** 714 * Calls the unbind api of COS Naming and uses the exception mapper 715 * class to map the exceptions 716 * @param path NameComponent[] object 717 * @exception NotFound No objects under the name. If leaf 718 * is not found, that's OK according to the JNDI spec 719 * @exception CannotProceed Unable to obtain a continuation context 720 * @exception InvalidName Name not understood. 721 */ 722 private void callUnbind(NameComponent[] path) throws NamingException { 723 if (_nc == null) 724 throw new ConfigurationException( 725 "Context does not have a corresponding NamingContext"); 726 try { 727 _nc.unbind(path); 728 } catch (NotFound e) { 729 // If leaf is the one missing, return success 730 // as per JNDI spec 731 732 if (leafNotFound(e, path[path.length-1])) { 733 // do nothing 734 } else { 735 throw ExceptionMapper.mapException(e, this, path); 736 } 737 } catch (Exception e) { 738 throw ExceptionMapper.mapException(e, this, path); 739 } 740 } 741 742 private boolean leafNotFound(NotFound e, NameComponent leaf) { 743 744 // This test is not foolproof because some name servers 745 // always just return one component in rest_of_name 746 // so you might not be able to tell whether that is 747 // the leaf (e.g. aa/aa/aa, which one is missing?) 748 749 NameComponent rest; 750 return e.why.value() == NotFoundReason._missing_node && 751 e.rest_of_name.length == 1 && 752 (rest=e.rest_of_name[0]).id.equals(leaf.id) && 753 (rest.kind == leaf.kind || 754 (rest.kind != null && rest.kind.equals(leaf.kind))); 755 } 756 757 /** 758 * Converts the "String" name into a CompositeName object and 759 * performs the unbind operation. Uses callUnbind. If the name is 760 * empty, throws an invalid name exception. Do we unbind the 761 * current context (JNDI spec says work with the current context if 762 * the name is empty) ? 763 * @param name string 764 * @exception NamingException See callUnbind 765 */ 766 public void unbind(String name) throws NamingException { 767 unbind(new CompositeName(name)); 768 } 769 770 /** 771 * Converts the "Name" name into a NameComponent[] object and 772 * performs the unbind operation. Uses callUnbind. Throws an 773 * invalid name exception if the name is empty. 774 * @param name string 775 * @exception NamingException See callUnbind 776 */ 777 public void unbind(Name name) 778 throws NamingException { 779 if (name.size() == 0 ) 780 throw new InvalidNameException("Name is empty"); 781 NameComponent[] path = CNNameParser.nameToCosName(name); 782 try { 783 callUnbind(path); 784 } catch (CannotProceedException e) { 785 javax.naming.Context cctx = getContinuationContext(e); 786 cctx.unbind(e.getRemainingName()); 787 } 788 } 789 790 /** 791 * Renames an object. Since COS Naming does not support a rename 792 * api, this method unbinds the object with the "oldName" and 793 * creates a new binding. 794 * @param oldName string, existing name for the binding. 795 * @param newName string, name used to replace. 796 * @exception NamingException See bind 797 */ 798 public void rename(String oldName,String newName) 799 throws NamingException { 800 rename(new CompositeName(oldName), new CompositeName(newName)); 801 } 802 803 /** 804 * Renames an object. Since COS Naming does not support a rename 805 * api, this method unbinds the object with the "oldName" and 806 * creates a new binding. 807 * @param oldName JNDI Name, existing name for the binding. 808 * @param newName JNDI Name, name used to replace. 809 * @exception NamingException See bind 810 */ 811 public void rename(Name oldName,Name newName) 812 throws NamingException { 813 if (_nc == null) 814 throw new ConfigurationException( 815 "Context does not have a corresponding NamingContext"); 816 if (oldName.size() == 0 || newName.size() == 0) 817 throw new InvalidNameException("One or both names empty"); 818 java.lang.Object obj = lookup(oldName); 819 bind(newName,obj); 820 unbind(oldName); 821 } 822 823 /** 824 * Returns a NameClassEnumeration object which has a list of name 825 * class pairs. Lists the current context if the name is empty. 826 * @param name string 827 * @exception NamingException All exceptions thrown by lookup 828 * with a non-null argument 829 * @return a list of name-class objects as a NameClassEnumeration. 830 */ 831 public NamingEnumeration<NameClassPair> list(String name) throws NamingException { 832 return list(new CompositeName(name)); 833 } 834 835 /** 836 * Returns a NameClassEnumeration object which has a list of name 837 * class pairs. Lists the current context if the name is empty. 838 * @param name JNDI Name 839 * @exception NamingException All exceptions thrown by lookup 840 * @return a list of name-class objects as a NameClassEnumeration. 841 */ 842 @SuppressWarnings("unchecked") 843 public NamingEnumeration<NameClassPair> list(Name name) 844 throws NamingException { 845 return (NamingEnumeration)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<javax.naming.Binding> 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<javax.naming.Binding> 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 name 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 @SuppressWarnings("unchecked") 1068 public Hashtable<String, java.lang.Object> getEnvironment() throws NamingException { 1069 if (_env == null) { 1070 return new Hashtable<>(5, 0.75f); 1071 } else { 1072 return (Hashtable<String, java.lang.Object>)_env.clone(); 1073 } 1074 } 1075 1076 public String composeName(String name, String prefix) throws NamingException { 1077 return composeName(new CompositeName(name), 1078 new CompositeName(prefix)).toString(); 1079 } 1080 1081 public Name composeName(Name name, Name prefix) throws NamingException { 1082 Name result = (Name)prefix.clone(); 1083 return result.addAll(name); 1084 } 1085 1086 /** 1087 * Adds to the environment for the current context. 1088 * Record change but do not reinitialize ORB. 1089 * 1090 * @param propName The property name. 1091 * @param propValue The ORB. 1092 * @return the previous value of this property if any. 1093 */ 1094 @SuppressWarnings("unchecked") 1095 public java.lang.Object addToEnvironment(String propName, 1096 java.lang.Object propValue) 1097 throws NamingException { 1098 if (_env == null) { 1099 _env = new Hashtable<>(7, 0.75f); 1100 } else { 1101 // copy-on-write 1102 _env = (Hashtable<String, java.lang.Object>)_env.clone(); 1103 } 1104 1105 return _env.put(propName, propValue); 1106 } 1107 1108 // Record change but do not reinitialize ORB 1109 @SuppressWarnings("unchecked") 1110 public java.lang.Object removeFromEnvironment(String propName) 1111 throws NamingException { 1112 if (_env != null && _env.get(propName) != null) { 1113 // copy-on-write 1114 _env = (Hashtable<String, java.lang.Object>)_env.clone(); 1115 return _env.remove(propName); 1116 } 1117 return null; 1118 } 1119 1120 synchronized public void incEnumCount() { 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 enumCount--; 1130 if (debug) { 1131 System.out.println("decEnumCount, new count:" + enumCount + 1132 " isCloseCalled:" + isCloseCalled); 1133 } 1134 if ((enumCount == 0) && isCloseCalled) { 1135 close(); 1136 } 1137 } 1138 1139 synchronized public void close() throws NamingException { 1140 1141 if (enumCount > 0) { 1142 isCloseCalled = true; 1143 return; 1144 } 1145 1146 // Never destroy an orb in CNCtx. 1147 // The orb we have is either the shared/default orb, or one passed in to a constructor 1148 // from elsewhere, so that orb is somebody else's responsibility. 1149 } 1150 1151 protected void finalize() { 1152 try { 1153 close(); 1154 } catch (NamingException e) { 1155 // ignore failures 1156 } 1157 } 1158 }