Source for gnu.javax.naming.giop.GiopNamingServiceURLContext

   1: /* GiopNamingServiceURLContext.java -- handles corbaname: urls
   2:    Copyright (C) 2006 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package gnu.javax.naming.giop;
  40: 
  41: import gnu.CORBA.NamingService.Ext;
  42: import gnu.CORBA.NamingService.NameTransformer;
  43: 
  44: import java.util.Hashtable;
  45: 
  46: import javax.naming.Binding;
  47: import javax.naming.Context;
  48: import javax.naming.ContextNotEmptyException;
  49: import javax.naming.InvalidNameException;
  50: import javax.naming.Name;
  51: import javax.naming.NameAlreadyBoundException;
  52: import javax.naming.NameClassPair;
  53: import javax.naming.NameNotFoundException;
  54: import javax.naming.NameParser;
  55: import javax.naming.NamingEnumeration;
  56: import javax.naming.NamingException;
  57: import javax.naming.OperationNotSupportedException;
  58: import javax.naming.directory.InvalidAttributesException;
  59: 
  60: import org.omg.CORBA.ORB;
  61: import org.omg.CORBA.portable.Delegate;
  62: import org.omg.CORBA.portable.ObjectImpl;
  63: import org.omg.CosNaming.BindingIteratorHolder;
  64: import org.omg.CosNaming.BindingListHolder;
  65: import org.omg.CosNaming.NameComponent;
  66: import org.omg.CosNaming.NamingContext;
  67: import org.omg.CosNaming.NamingContextExt;
  68: import org.omg.CosNaming.NamingContextExtHelper;
  69: import org.omg.CosNaming.NamingContextHelper;
  70: import org.omg.CosNaming._NamingContextExtStub;
  71: import org.omg.CosNaming._NamingContextStub;
  72: import org.omg.CosNaming.NamingContextPackage.AlreadyBound;
  73: import org.omg.CosNaming.NamingContextPackage.CannotProceed;
  74: import org.omg.CosNaming.NamingContextPackage.InvalidName;
  75: import org.omg.CosNaming.NamingContextPackage.NotFound;
  76: 
  77: /**
  78:  * The context to represent the corba naming service. Being the naming service,
  79:  * the returned context supports creating the subcontexts, forwarding this task
  80:  * to the existing naming service. When listing bindings, it uses the
  81:  * {@link Context#BATCHSIZE} property to determine, how many bindings should
  82:  * be returned at once (the process is transparend)
  83:  *
  84:  * @author Audrius Meskauskas (audriusa@Bioinformatics.org)
  85:  */
  86: public class GiopNamingServiceURLContext extends CorbalocParser implements
  87:     Context
  88: {
  89:   /**
  90:    * This number of bindings will be requested from the naming server at once,
  91:    * while the subsequent bindings will be requested via binding iterator one by
  92:    * one. Use {@link Context#BATCHSIZE} to override the value of this constant.
  93:    */
  94:   public int DEFAULT_BATCH_SIZE = 20;
  95: 
  96:   /**
  97:    * The object request broker, used to access the naming service. This field
  98:    * is only initialised when the context is constructed from the URL.
  99:    */
 100:   ORB orb;
 101: 
 102:   /**
 103:    * The properties.
 104:    */
 105:   Hashtable properties;
 106: 
 107:   /**
 108:    * The parent factory.
 109:    */
 110:   GiopNamingServiceFactory factory;
 111: 
 112:   /**
 113:    * The name transformer to obtain the name from its string representation. The
 114:    * to_name method of the naming service is avoided as it may be remote and
 115:    * hence expensive. The conversion rules are standard and cannot be service
 116:    * specific.
 117:    */
 118:   static NameTransformer transformer = new NameTransformer();
 119: 
 120:   /**
 121:    * The batch size for list operations - how many to return at once.
 122:    */
 123:   public final int howMany;
 124: 
 125:   /**
 126:    * Creates a new naming context that uses naming service, represented by the
 127:    * given CORBA object.
 128:    *
 129:    * @param props
 130:    *          the environment table.
 131:    * @param aFactory
 132:    *          parent factory. This reference is used during cleanup.
 133:    * @param anOrb
 134:    *          the associated ORB. This reference is used during cleanup.
 135:    */
 136:   public GiopNamingServiceURLContext(Hashtable props,
 137:                                      GiopNamingServiceFactory aFactory,
 138:                                      ORB anOrb)
 139:   {
 140:     factory = aFactory;
 141:     orb = anOrb;
 142: 
 143:     properties = props;
 144:     howMany = getBatchSize();
 145:   }
 146: 
 147:   public NamingContextExt getService(String address)
 148:   {
 149:     org.omg.CORBA.Object nsObject = orb.string_to_object(address);
 150:     Delegate delegate = ((ObjectImpl) nsObject)._get_delegate();
 151: 
 152:     // If the IOR provides the IDL ID, we can check if our name
 153:     // service is old NamingContext or new NamingContextExt.
 154:     // Not all forms of the URL always provide the IDL id.
 155:     if (!nsObject._is_a(NamingContextExtHelper.id())
 156:         && nsObject._is_a(NamingContextHelper.id()))
 157:       {
 158:         // We are surely working with the old version.
 159:         _NamingContextStub stub = new _NamingContextStub();
 160:         stub._set_delegate(delegate);
 161:         // The Ext object will add the necessary extensions.
 162:         return new Ext(stub);
 163:       }
 164:     else
 165:       {
 166:         // We expecte the service to be the NamingContextExt (this is true
 167:         // for both Sun's and our implementations). There is no easy way
 168:         // to check the version.
 169:         _NamingContextExtStub stub = new _NamingContextExtStub();
 170:         stub._set_delegate(delegate);
 171:         return stub;
 172:       }
 173:   }
 174: 
 175:   /**
 176:    * Split the corbaname name into the address of the naming service (first
 177:    * part) and the name of the object in the naming service (second part)
 178:    */
 179:   public String[] split(String corbaloc) throws InvalidNameException
 180:   {
 181:     if (corbaloc.endsWith("#"))
 182:       corbaloc = corbaloc.substring(0, corbaloc.length() - 1);
 183: 
 184:     // No name part - parse as corbaname.
 185:     if (corbaloc.indexOf('#') < 0)
 186:       {
 187:         if (!corbaloc.regionMatches(true, 0, pxCORBANAME, 0,
 188:                                     pxCORBANAME.length()))
 189:           throw new InvalidNameException(corbaloc + " must start with "
 190:                                          + pxCORBANAME);
 191:         corbaloc = pxCORBALOC + corbaloc.substring(pxCORBANAME.length());
 192:         return new String[] { corbaloc, "" };
 193:       }
 194: 
 195:     return corbaloc(corbaloc, orb);
 196:   }
 197: 
 198:   /**
 199:    * Give the specified name for the specified object. The passed name must not
 200:    * be already bound to some other object. The components of the name are
 201:    * mapped into the components of the CORBA name.
 202:    *
 203:    * @param name
 204:    *          the name that will be given to the object (in the scope of this
 205:    *          context).
 206:    * @param obj
 207:    *          the object being named.
 208:    * @throws NameAlreadyBoundException
 209:    *           if this name is already used to name some object.
 210:    * @throws InvalidAttributesException
 211:    *           if the object does not supply all required attributes.
 212:    * @throws NamingException
 213:    *           if the naming operation has failed due other reasons.
 214:    */
 215:   public void bind(Name name, Object obj) throws NamingException
 216:   {
 217:     bind(name.toString(), obj);
 218:   }
 219: 
 220:   /**
 221:    * Give the specified name for the specified object. The passed name must not
 222:    * be already bound to some other object.
 223:    *
 224:    * @param name
 225:    *          the name that will be given to the object (in the scope of this
 226:    *          context).
 227:    * @param obj
 228:    *          the object being named.
 229:    * @throws NameAlreadyBoundException
 230:    *           if this name is already used to name some object.
 231:    * @throws InvalidAttributesException
 232:    *           if the object does not supply all required attributes.
 233:    * @throws NamingException
 234:    *           if the naming operation has failed due other reasons.
 235:    */
 236:   public void bind(String name, Object obj) throws NamingException
 237:   {
 238:     try
 239:       {
 240:         String[] n = split(name);
 241:         org.omg.CORBA.Object object = (org.omg.CORBA.Object) obj;
 242:         getService(n[0]).bind(transformer.toName(n[1]), object);
 243:       }
 244:     catch (ClassCastException e)
 245:       {
 246:         throw new NamingException(org.omg.CORBA.Object.class + " required ");
 247:       }
 248:     catch (InvalidName e)
 249:       {
 250:         throw new InvalidNameException();
 251:       }
 252:     catch (AlreadyBound e)
 253:       {
 254:         throw new NameAlreadyBoundException();
 255:       }
 256:     catch (Exception e)
 257:       {
 258:         throw new NamingException(e.toString());
 259:       }
 260:   }
 261: 
 262:   /**
 263:    * Releases all resources, associated with this context. The close() method
 264:    * can be called several times, but after it has been once invoked, it is not
 265:    * allowed to call any other method of this context. This method destroys
 266:    * the ORB, if we have one.
 267:    *
 268:    * @throws NamingException
 269:    */
 270:   public void close() throws NamingException
 271:   {
 272:     if (orb != null && factory != null)
 273:       {
 274:         factory.checkIfReferenced(orb);
 275:       }
 276:   }
 277: 
 278:   /**
 279:    * Not supported.
 280:    */
 281:   public Name composeName(Name name, Name prefix) throws NamingException
 282:   {
 283:     throw new OperationNotSupportedException();
 284:   }
 285: 
 286:   /**
 287:    * Not supported
 288:    */
 289:   public String composeName(String name1, String name2) throws NamingException
 290:   {
 291:     throw new OperationNotSupportedException();
 292:   }
 293: 
 294:   /**
 295:    * Creates the new naming subcontext and binds it to the current (this)
 296:    * context. The returned object will wrap around the newly created CORBA
 297:    * subcontext
 298:    *
 299:    * @param subContext
 300:    *          the name of the new context being created
 301:    * @return the newly created context, bound to the instance of the context on
 302:    *         that the method has been called
 303:    * @throws NameAlreadyBoundException
 304:    *           if this name is already bound
 305:    * @throws InvalidAttributesException
 306:    *           if the creation of the new context requires the missing mandatory
 307:    *           attributes
 308:    * @throws NamingException
 309:    */
 310:   public Context createSubcontext(Name subContext) throws NamingException
 311:   {
 312:     return createSubcontext(subContext.toString());
 313:   }
 314: 
 315:   /**
 316:    * Creates the new naming subcontext and binds it to the current (this)
 317:    * context. The returned object will wrap around the newly created CORBA
 318:    * subcontext
 319:    *
 320:    * @param subContext
 321:    *          the name of the new context being created
 322:    * @return the newly created context, bound to the instance of the context on
 323:    *         that the method has been called
 324:    * @throws NameAlreadyBoundException
 325:    *           if this name is already bound
 326:    * @throws InvalidAttributesException
 327:    *           if the creation of the new context requires the missing mandatory
 328:    *           attributes
 329:    * @throws NamingException
 330:    */
 331:   public Context createSubcontext(String subContext) throws NamingException
 332:   {
 333:     try
 334:       {
 335:         String[] n = split(subContext);
 336:         org.omg.CORBA.Object subcontext = getService(n[0]).bind_new_context(
 337:                                             transformer.toName(n[1]));
 338:         Hashtable clonedProps = new Hashtable();
 339:         clonedProps.putAll(properties);
 340: 
 341:         // Nulls are passed both for orb and factory, as the child contexts
 342:         // need not to do any cleanup.
 343:         return new ContextContinuation(subcontext, clonedProps, null, null);
 344:       }
 345:     catch (AlreadyBound e)
 346:       {
 347:         throw new NameAlreadyBoundException(subContext);
 348:       }
 349:     catch (InvalidName e)
 350:       {
 351:         throw new InvalidNameException(subContext);
 352:       }
 353:     catch (Exception ex)
 354:       {
 355:         throw new NamingException(ex.toString());
 356:       }
 357:   }
 358: 
 359:   /**
 360:    * Removes the naming subcontext from this naming context. Returns without
 361:    * action if such subcontext does not exist. The context being destroyed must
 362:    * be empty.
 363:    *
 364:    * @param subContext
 365:    *          the name of the subcontext beig removed.
 366:    * @throws ContextNotEmptyException
 367:    *           if the named context is not empty.
 368:    * @throws NamingException
 369:    */
 370:   public void destroySubcontext(Name subContext) throws NamingException
 371:   {
 372:     unbind(subContext);
 373:   }
 374: 
 375:   /**
 376:    * Removes the naming subcontext from this naming context. Returns without
 377:    * action if such subcontext does not exist. The context being destroyed must
 378:    * be empty.
 379:    *
 380:    * @param subContext
 381:    *          the name of the subcontext beig removed.
 382:    * @throws ContextNotEmptyException
 383:    *           if the named context is not empty.
 384:    * @throws NamingException
 385:    */
 386:   public void destroySubcontext(String subContext) throws NamingException
 387:   {
 388:     unbind(subContext);
 389:   }
 390: 
 391:   /**
 392:    * Returs the empty string.
 393:    */
 394:   public String getNameInNamespace() throws NamingException
 395:   {
 396:     return "";
 397:   }
 398: 
 399:   /**
 400:    * Not supported.
 401:    */
 402:   public NameParser getNameParser(Name name) throws NamingException
 403:   {
 404:     throw new UnsupportedOperationException();
 405:   }
 406: 
 407:   /**
 408:    * Not supported.
 409:    */
 410:   public NameParser getNameParser(String name) throws NamingException
 411:   {
 412:     throw new UnsupportedOperationException();
 413:   }
 414: 
 415:   /**
 416:    * Creates and returns the enumeration over the name bindings that are present
 417:    * the given subcontext. The enumeration elements have the type of
 418:    * {@link NameClassPair}, providing also information about the class of the
 419:    * bound object. The behaviour in the case if the bindings are added or
 420:    * removed later is not defined. The contents of the subcontexts are not
 421:    * included.
 422:    *
 423:    * @param name
 424:    *          the name of the subcontext
 425:    * @return the enumeration over the names, known for the given subcontext.
 426:    * @throws NamingException
 427:    */
 428:   public NamingEnumeration list(Name name) throws NamingException
 429:   {
 430:     return list(name.toString());
 431:   }
 432: 
 433:   /**
 434:    * Creates and returns the enumeration over the name bindings that are present
 435:    * the given subcontext. The enumeration elements have the type of
 436:    * {@link NameClassPair}, providing also information about the class of the
 437:    * bound object. The behaviour in the case if the bindings are added or
 438:    * removed later is not defined. The contents of the subcontexts are not
 439:    * included.
 440:    *
 441:    * @param name
 442:    *          the name of the subcontext
 443:    * @return the enumeration over the names, known for the given subcontext.
 444:    * @throws NamingException
 445:    */
 446:   public NamingEnumeration list(String name) throws NamingException
 447:   {
 448:     BindingIteratorHolder bi = new BindingIteratorHolder();
 449:     BindingListHolder bl = new BindingListHolder();
 450: 
 451:     NamingContext subcontext;
 452: 
 453:     String [] n = split(name);
 454:     NamingContextExt service = getService(n[0]);
 455: 
 456:     if (n[1].length() == 0)
 457:       subcontext = service;
 458:     else
 459:       {
 460:         try
 461:           {
 462:             subcontext = (NamingContextHelper.narrow(service.resolve_str(n[1])));
 463:           }
 464:         catch (Exception e)
 465:           {
 466:             throw new NamingException(e.toString());
 467:           }
 468: 
 469:       }
 470: 
 471:     subcontext.list(howMany, bl, bi);
 472: 
 473:     return new ListEnumeration(bl, bi, howMany);
 474:   }
 475: 
 476:   /**
 477:    * Creates and returns the enumeration over the name - object bindings that
 478:    * are present the given subcontext. The enumeration elements have the type of
 479:    * {@link Binding}, providing also information about the class of the bound
 480:    * object. The behaviour in the case if the bindings are added or removed
 481:    * later is not defined. The contents of the subcontexts are not included.
 482:    *
 483:    * @param name
 484:    *          the name of the subcontext
 485:    * @return the enumeration over the names, known for the given subcontext.
 486:    * @throws NamingException
 487:    */
 488:   public NamingEnumeration listBindings(Name name) throws NamingException
 489:   {
 490:     return listBindings(name.toString());
 491:   }
 492: 
 493:   /**
 494:    * Creates and returns the enumeration over the name - object bindings that
 495:    * are present the given subcontext. The enumeration elements have the type of
 496:    * {@link Binding}, providing also information about the class of the bound
 497:    * object. The behaviour in the case if the bindings are added or removed
 498:    * later is not defined. The contents of the subcontexts are not included.
 499:    *
 500:    * @param name
 501:    *          the name of the subcontext
 502:    * @return the enumeration over the names, known for the given subcontext.
 503:    * @throws NamingException
 504:    */
 505:   public NamingEnumeration listBindings(String name) throws NamingException
 506:   {
 507:     BindingIteratorHolder bi = new BindingIteratorHolder();
 508:     BindingListHolder bl = new BindingListHolder();
 509: 
 510:     NamingContext subcontext;
 511: 
 512:     String [] n = split(name);
 513:     NamingContextExt service = getService(n[0]);
 514: 
 515:     if (n[1].length() == 0)
 516:       subcontext = service;
 517:     else
 518:       {
 519:         try
 520:           {
 521:             subcontext = (NamingContextHelper.narrow(service.resolve_str(n[1])));
 522:           }
 523:         catch (Exception e)
 524:           {
 525:             throw new NamingException(e.toString());
 526:           }
 527: 
 528:       }
 529: 
 530:     subcontext.list(howMany, bl, bi);
 531: 
 532:     return new ListBindingsEnumeration(bl, bi, howMany, subcontext);
 533:   }
 534: 
 535:   /**
 536:    * Gets the previously named object by name. If the passed name is empty, the
 537:    * method should return a cloned instance of this naming context.
 538:    *
 539:    * @param name
 540:    *          the name of the object being searched in this context
 541:    * @return the named object
 542:    * @throws NameNotFoundException
 543:    *           if the name is not found
 544:    */
 545:   public Object lookup(Name name) throws NamingException
 546:   {
 547:     return lookup(name.toString());
 548:   }
 549: 
 550:   /**
 551:    * Gets the previously named object by name. If the passed name is empty, the
 552:    * method should return a cloned instance of this naming context.
 553:    *
 554:    * @param name
 555:    *          the name of the object being searched in this context
 556:    * @return the named object
 557:    * @throws NamingException
 558:    *           if the naming fails.
 559:    */
 560:   public Object lookup(String name) throws NamingException
 561:   {
 562:     try
 563:       {
 564:         String [] n = split(name);
 565:         NamingContextExt service = getService(n[0]);
 566:         return service.resolve_str(n[1]);
 567:       }
 568:     catch (NotFound e)
 569:       {
 570:         throw new NameNotFoundException();
 571:       }
 572:     catch (InvalidName e)
 573:       {
 574:         throw new InvalidNameException();
 575:       }
 576:     catch (Exception e)
 577:       {
 578:         throw new NamingException(e.toString());
 579:       }
 580:   }
 581: 
 582:   /**
 583:    * Not supported.
 584:    */
 585:   public Object lookupLink(Name name) throws NamingException
 586:   {
 587:     throw new OperationNotSupportedException();
 588:   }
 589: 
 590:   /**
 591:    * Not supported.
 592:    */
 593:   public Object lookupLink(String name) throws NamingException
 594:   {
 595:     throw new OperationNotSupportedException();
 596:   }
 597: 
 598:   /**
 599:    * Give the specified name for the specified object. Unlike bind, this method
 600:    * silently replaces the existing binding for this name, if one exists.
 601:    *
 602:    * @param name
 603:    *          the name that will be given to the object (in the scope of this
 604:    *          context).
 605:    * @param obj
 606:    *          the object being named.
 607:    * @throws InvalidAttributesException
 608:    *           if the object does not supply all required attributes.
 609:    * @throws NamingException
 610:    *           if the naming operation has failed due other reasons.
 611:    */
 612:   public void rebind(Name name, Object obj) throws NamingException
 613:   {
 614:     rebind(name.toString(), obj);
 615:   }
 616: 
 617:   /**
 618:    * Give the specified name for the specified object. Unlike bind, this method
 619:    * silently replaces the existing binding for this name, if one exists.
 620:    *
 621:    * @param name
 622:    *          the name that will be given to the object (in the scope of this
 623:    *          context).
 624:    * @param obj
 625:    *          the object being named.
 626:    * @throws InvalidAttributesException
 627:    *           if the object does not supply all required attributes.
 628:    * @throws NamingException
 629:    *           if the naming operation has failed due other reasons.
 630:    */
 631:   public void rebind(String name, Object obj) throws NamingException
 632:   {
 633:     try
 634:       {
 635:         String[] n = split(name);
 636:         NamingContextExt service = getService(n[0]);
 637: 
 638:         org.omg.CORBA.Object object = (org.omg.CORBA.Object) obj;
 639:         service.rebind(transformer.toName(n[1]), object);
 640:       }
 641:     catch (ClassCastException e)
 642:       {
 643:         throw new NamingException(org.omg.CORBA.Object.class + " required ");
 644:       }
 645:     catch (InvalidName e)
 646:       {
 647:         throw new InvalidNameException();
 648:       }
 649:     catch (Exception e)
 650:       {
 651:         throw new NamingException(e.toString());
 652:       }
 653:   }
 654: 
 655:   /**
 656:    * Renames the existing binding, removing the existing and giving the new name
 657:    * for the same object.
 658:    *
 659:    * @param oldName
 660:    *          the existing name of the known object
 661:    * @param newName
 662:    *          the new name of the same object
 663:    * @throws NameNotFoundException
 664:    *           if the oldName is unknown for this context
 665:    * @throws NamingException
 666:    *           if the naming operation has failed due other reasons.
 667:    */
 668:   public void rename(Name oldName, Name newName) throws NamingException
 669:   {
 670:     Object object = lookup(oldName);
 671:     unbind(oldName);
 672:     bind(newName, object);
 673:   }
 674: 
 675:   /**
 676:    * Renames the existing binding, removing the existing and giving the new name
 677:    * for the same object.
 678:    *
 679:    * @param oldName
 680:    *          the existing name of the known object
 681:    * @param newName
 682:    *          the new name of the same object
 683:    * @throws NameNotFoundException
 684:    *           if the oldName is unknown for this context
 685:    * @throws NamingException
 686:    *           if the naming operation has failed due other reasons.
 687:    */
 688:   public void rename(String oldName, String newName) throws NamingException
 689:   {
 690:     Object object = lookup(oldName);
 691:     unbind(oldName);
 692:     bind(newName, object);
 693:   }
 694: 
 695:   /**
 696:    * Removes the name - object mapping from the current context. This method
 697:    * returns without action if the name is not bound to an object in the
 698:    * terminal context, but throws {@link NameNotFoundException} if one of the
 699:    * intermadiate contexts does not exist.
 700:    *
 701:    * @param name
 702:    *          the name to be removed
 703:    * @throws NameNotFoundException
 704:    *           if one of the intermediate naming contexts does not exist. Will
 705:    *           not be thrown if just the terminal binding is missing.
 706:    * @throws NamingException
 707:    *           if the naming operation has failed due other reasons.
 708:    */
 709:   public void unbind(Name name) throws NamingException
 710:   {
 711:     unbind(name.toString());
 712:   }
 713: 
 714:   /**
 715:    * Removes the name - object mapping from the current context. This method
 716:    * returns without action if the name is not bound to an object in the
 717:    * terminal context, but throws {@link NameNotFoundException} if one of the
 718:    * intermadiate contexts does not exist.
 719:    *
 720:    * @param name
 721:    *          the name to be removed
 722:    * @throws NameNotFoundException
 723:    *           if one of the intermediate naming contexts does not exist. Will
 724:    *           not be thrown if just the terminal binding is missing.
 725:    * @throws NamingException
 726:    *           if the naming operation has failed due other reasons.
 727:    */
 728:   public void unbind(String name) throws NamingException
 729:   {
 730:     try
 731:       {
 732:         String[] n = split(name);
 733:         NamingContextExt service = getService(n[0]);
 734: 
 735:         service.unbind(transformer.toName(n[1]));
 736:       }
 737:     catch (NotFound e)
 738:       {
 739:         throw new NameNotFoundException(name);
 740:       }
 741:     catch (CannotProceed e)
 742:       {
 743:         throw new ContextNotEmptyException(name);
 744:       }
 745:     catch (InvalidName e)
 746:       {
 747:         throw new InvalidNameException(name);
 748:       }
 749:   }
 750: 
 751:   /**
 752:    * Add new environment property to the environment of this context. Both name
 753:    * and value of the new property must not be null. If the property is already
 754:    * defined, is current value is replaced by the propVal.
 755:    *
 756:    * @param key
 757:    *          the name of the new property
 758:    * @param value
 759:    *          the value of the new property
 760:    * @return the previous value of this property or null if the property has not
 761:    *         been previously defined
 762:    * @throws NamingException
 763:    */
 764:   public Object addToEnvironment(String key, Object value)
 765:       throws NamingException
 766:   {
 767:     if (key == null || value == null)
 768:       throw new NullPointerException();
 769:     return properties.put(key, value);
 770:   }
 771: 
 772:   /**
 773:    * Returns the environment, associated with this naming context. The returned
 774:    * table should never be modified by the caller. Use {@link #addToEnvironment}
 775:    * and {@link #removeFromEnvironment} to modify the environement, if needed.
 776:    *
 777:    * @return the table, representing the environment of this context
 778:    * @throws NamingException
 779:    */
 780:   public Hashtable getEnvironment() throws NamingException
 781:   {
 782:     return properties;
 783:   }
 784: 
 785:   /**
 786:    * Removes the property with the given name from the environment. Returns
 787:    * without action if this property is not defined.
 788:    *
 789:    * @param propName
 790:    *          the name of the property being removed.
 791:    * @return the value of the property that has been removed or null if the
 792:    *         property was not defined.
 793:    * @throws NamingException
 794:    */
 795:   public Object removeFromEnvironment(String propName) throws NamingException
 796:   {
 797:     return properties.remove(propName);
 798:   }
 799: 
 800:   /**
 801:    * Convert the {@link Name} into array of the name components, required to the
 802:    * CORBA naming service. First the string representation is obtained, then
 803:    * it is converted using parsing rules of the CORBA name.
 804:    *
 805:    * @param name
 806:    *          then name to convert
 807:    * @return the converted array of components.
 808:    */
 809:   public NameComponent[] toGiop(Name name) throws InvalidName
 810:   {
 811:     return transformer.toName(name.toString());
 812:   }
 813: 
 814:   /**
 815:    * Get the batch size from the environment properties. The batch size is used
 816:    * for listing operations.
 817:    *
 818:    * @return the batch size, or some default value if not specified.
 819:    */
 820:   public int getBatchSize()
 821:   {
 822:     int batchSize = DEFAULT_BATCH_SIZE;
 823:     Object bs = properties.get(Context.BATCHSIZE);
 824:     if (bs != null)
 825:       {
 826:         try
 827:           {
 828:             int b = Integer.parseInt(bs.toString());
 829:             if (b >= 0)
 830:               batchSize = b;
 831:           }
 832:         catch (NumberFormatException e)
 833:           {
 834:             // OK, use default value.
 835:           }
 836:       }
 837:     return batchSize;
 838:   }
 839: 
 840: }