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