OSDN Git Service

libjava/
[pf3gnuchains/gcc-fork.git] / libjava / classpath / gnu / javax / naming / giop / ContextContinuation.java
1 /* ContextContinuation.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 package gnu.javax.naming.giop;
39
40 import gnu.CORBA.NamingService.Ext;
41 import gnu.CORBA.NamingService.NameTransformer;
42
43 import java.util.Hashtable;
44
45 import javax.naming.Binding;
46 import javax.naming.Context;
47 import javax.naming.ContextNotEmptyException;
48 import javax.naming.InvalidNameException;
49 import javax.naming.Name;
50 import javax.naming.NameAlreadyBoundException;
51 import javax.naming.NameClassPair;
52 import javax.naming.NameNotFoundException;
53 import javax.naming.NameParser;
54 import javax.naming.NamingEnumeration;
55 import javax.naming.NamingException;
56 import javax.naming.OperationNotSupportedException;
57 import javax.naming.directory.InvalidAttributesException;
58
59 import org.omg.CORBA.ORB;
60 import org.omg.CORBA.portable.Delegate;
61 import org.omg.CORBA.portable.ObjectImpl;
62 import org.omg.CosNaming.BindingIteratorHolder;
63 import org.omg.CosNaming.BindingListHolder;
64 import org.omg.CosNaming.NameComponent;
65 import org.omg.CosNaming.NamingContext;
66 import org.omg.CosNaming.NamingContextExt;
67 import org.omg.CosNaming.NamingContextExtHelper;
68 import org.omg.CosNaming.NamingContextHelper;
69 import org.omg.CosNaming._NamingContextExtStub;
70 import org.omg.CosNaming._NamingContextStub;
71 import org.omg.CosNaming.NamingContextPackage.AlreadyBound;
72 import org.omg.CosNaming.NamingContextPackage.CannotProceed;
73 import org.omg.CosNaming.NamingContextPackage.InvalidName;
74 import org.omg.CosNaming.NamingContextPackage.NotFound;
75
76 /**
77  * The context to represent the corba naming service. Being the naming service,
78  * the returned context supports creating the subcontexts, forwarding this task
79  * to the existing naming service. When listing bindings, it uses the
80  * {@link Context#BATCHSIZE} property to determine, how many bindings should
81  * be returned at once (the process is transparend)
82  * 
83  * @author Audrius Meskauskas (audriusa@Bioinformatics.org)
84  */
85 public class ContextContinuation implements Context
86 {
87   /**
88    * This number of bindings will be requested from the naming server at once,
89    * while the subsequent bindings will be requested via binding iterator one by
90    * one. Use {@link Context#BATCHSIZE} to override the value of this constant.
91    */
92   public int DEFAULT_BATCH_SIZE = 20;
93   
94   /**
95    * The actual CORBA naming service.
96    */
97   NamingContextExt service;
98   
99   /**
100    * The object request broker, used to access the naming service. This field
101    * is only initialised when the context is constructed from the URL. 
102    */
103   ORB orb;
104   
105   /**
106    * The properties.
107    */
108   Hashtable properties;
109   
110   /**
111    * The parent factory.
112    */
113   GiopNamingServiceFactory factory;
114   
115   /**
116    * The name transformer to obtain the name from its string representation. The
117    * to_name method of the naming service is avoided as it may be remote and
118    * hence expensive. The conversion rules are standard and cannot be service
119    * specific.
120    */
121   static NameTransformer transformer = new NameTransformer();
122   
123   /**
124    * The batch size for list operations - how many to return at once.
125    */
126   public final int howMany;
127   
128   /**
129    * Creates a new naming context that uses naming service, represented by the
130    * given CORBA object.
131    * 
132    * @param nsObject
133    *          the naming service object. It must be possible to narrow it into
134    *          the NamingContextExt.
135    * @param props
136    *          the environment table.
137    * @param anOrb
138    *          the associated ORB. This reference is used during cleanup.
139    * @param aFactory
140    *          parent factory. This reference is used during cleanup.
141    */
142   public ContextContinuation(org.omg.CORBA.Object nsObject,
143                                      Hashtable props, ORB anOrb,
144                                      GiopNamingServiceFactory aFactory)
145   {
146     factory = aFactory;
147     orb = anOrb;
148
149     Delegate delegate = ((ObjectImpl) nsObject)._get_delegate();
150
151     // If the IOR provides the IDL ID, we can check if our name
152     // service is old NamingContext or new NamingContextExt.
153     // Not all forms of the URL always provide the IDL id.
154     if (!nsObject._is_a(NamingContextExtHelper.id())
155         && nsObject._is_a(NamingContextHelper.id()))
156       {
157         // We are surely working with the old version.
158         _NamingContextStub stub = new _NamingContextStub();
159         stub._set_delegate(delegate);
160         // The Ext object will add the necessary extensions.
161         service = new Ext(stub);
162       }
163     else
164       {
165         // We expecte the service to be the NamingContextExt (this is true
166         // for both Sun's and our implementations). There is no easy way
167         // to check the version.
168         _NamingContextExtStub stub = new _NamingContextExtStub();
169         stub._set_delegate(delegate);
170         service = stub;
171       }
172     properties = props;
173     howMany = getBatchSize();
174   }
175
176   /**
177    * Give the specified name for the specified object. The passed name must not
178    * be already bound to some other object. The components of the name are
179    * mapped into the components of the CORBA name.
180    * 
181    * @param name
182    *          the name that will be given to the object (in the scope of this
183    *          context).
184    * @param obj
185    *          the object being named.
186    * @throws NameAlreadyBoundException
187    *           if this name is already used to name some object.
188    * @throws InvalidAttributesException
189    *           if the object does not supply all required attributes.
190    * @throws NamingException
191    *           if the naming operation has failed due other reasons.
192    */
193   public void bind(Name name, Object obj) throws NamingException
194   {
195     try
196       {
197         org.omg.CORBA.Object object = (org.omg.CORBA.Object) obj;
198         service.bind(toGiop(name), object);
199       }
200     catch (ClassCastException e)
201       {
202         throw new NamingException(org.omg.CORBA.Object.class + " required ");
203       }
204     catch (InvalidName e)
205       {
206         throw new InvalidNameException();
207       }
208     catch (AlreadyBound e)
209       {
210         throw new NameAlreadyBoundException();
211       }
212     catch (Exception e)
213       {
214         throw new NamingException(e.toString());
215       }
216   }
217
218   /**
219    * Give the specified name for the specified object. The passed name must not
220    * be already bound to some other object.
221    * 
222    * @param name
223    *          the name that will be given to the object (in the scope of this
224    *          context).
225    * @param obj
226    *          the object being named.
227    * @throws NameAlreadyBoundException
228    *           if this name is already used to name some object.
229    * @throws InvalidAttributesException
230    *           if the object does not supply all required attributes.
231    * @throws NamingException
232    *           if the naming operation has failed due other reasons.
233    */
234   public void bind(String name, Object obj) throws NamingException
235   {
236     try
237       {
238         org.omg.CORBA.Object object = (org.omg.CORBA.Object) obj;
239         service.bind(transformer.toName(name), object);
240       }
241     catch (ClassCastException e)
242       {
243         throw new NamingException(org.omg.CORBA.Object.class + " required ");
244       }
245     catch (InvalidName e)
246       {
247         throw new InvalidNameException();
248       }
249     catch (AlreadyBound e)
250       {
251         throw new NameAlreadyBoundException();
252       }
253     catch (Exception e)
254       {
255         throw new NamingException(e.toString());
256       }
257   }
258
259   /**
260    * Releases all resources, associated with this context. The close() method
261    * can be called several times, but after it has been once invoked, it is not
262    * allowed to call any other method of this context. This method destroys
263    * the ORB, if we have one.
264    * 
265    * @throws NamingException
266    */
267   public void close() throws NamingException
268   {
269     if (orb != null && factory !=null)
270       {
271         factory.checkIfReferenced(orb);
272       }
273   }
274
275   /**
276    * Not supported.
277    */
278   public Name composeName(Name name, Name prefix) throws NamingException
279   {
280     throw new OperationNotSupportedException();
281   }
282
283   /**
284    * Not supported
285    */
286   public String composeName(String name1, String name2) throws NamingException
287   {
288     throw new OperationNotSupportedException();
289   }
290
291   /**
292    * Creates the new naming subcontext and binds it to the current (this)
293    * context. The returned object will wrap around the newly created CORBA
294    * subcontext
295    * 
296    * @param subContext
297    *          the name of the new context being created
298    * @return the newly created context, bound to the instance of the context on
299    *         that the method has been called
300    * @throws NameAlreadyBoundException
301    *           if this name is already bound
302    * @throws InvalidAttributesException
303    *           if the creation of the new context requires the missing mandatory
304    *           attributes
305    * @throws NamingException
306    */
307   public Context createSubcontext(Name subContext) throws NamingException
308   {
309     try
310       {
311         org.omg.CORBA.Object subcontext = service.bind_new_context(
312           toGiop(subContext));
313         Hashtable clonedProps = new Hashtable();
314         clonedProps.putAll(properties);
315         
316         // Nulls are passed both for orb and factory, as the child contexts
317         // need not to do any cleanup.
318         return new ContextContinuation(subcontext, clonedProps, null, null);
319       }
320     catch (AlreadyBound e)
321       {
322         throw new NameAlreadyBoundException();
323       }
324     catch (InvalidName e)
325       {
326         throw new InvalidNameException();
327       }
328     catch (Exception ex)
329       {
330         throw new NamingException(ex.toString());
331       }
332   }
333
334   /**
335    * Creates the new naming subcontext and binds it to the current (this)
336    * context. The returned object will wrap around the newly created CORBA
337    * subcontext
338    * 
339    * @param subContext
340    *          the name of the new context being created
341    * @return the newly created context, bound to the instance of the context on
342    *         that the method has been called
343    * @throws NameAlreadyBoundException
344    *           if this name is already bound
345    * @throws InvalidAttributesException
346    *           if the creation of the new context requires the missing mandatory
347    *           attributes
348    * @throws NamingException
349    */
350   public Context createSubcontext(String subContext) throws NamingException
351   {
352     try
353       {
354         org.omg.CORBA.Object subcontext = 
355           service.bind_new_context(transformer.toName(subContext));
356         Hashtable clonedProps = new Hashtable();
357         clonedProps.putAll(properties);
358
359         // Nulls are passed both for orb and factory, as the child contexts
360         // need not to do any cleanup.
361         return new ContextContinuation(subcontext, clonedProps, null,
362                                                null);
363       }
364     catch (AlreadyBound e)
365       {
366         throw new NameAlreadyBoundException(subContext);
367       }
368     catch (InvalidName e)
369       {
370         throw new InvalidNameException(subContext);
371       }
372     catch (Exception ex)
373       {
374         throw new NamingException(ex.toString());
375       }
376   }
377
378   /**
379    * Removes the naming subcontext from this naming context. Returns without
380    * action if such subcontext does not exist. The context being destroyed must
381    * be empty.
382    * 
383    * @param subContext
384    *          the name of the subcontext beig removed.
385    * @throws ContextNotEmptyException
386    *           if the named context is not empty.
387    * @throws NamingException
388    */
389   public void destroySubcontext(Name subContext) throws NamingException
390   {
391     unbind(subContext);
392   }
393
394   /**
395    * Removes the naming subcontext from this naming context. Returns without
396    * action if such subcontext does not exist. The context being destroyed must
397    * be empty.
398    * 
399    * @param subContext
400    *          the name of the subcontext beig removed.
401    * @throws ContextNotEmptyException
402    *           if the named context is not empty.
403    * @throws NamingException
404    */
405   public void destroySubcontext(String subContext) throws NamingException
406   {
407     unbind(subContext);
408   }
409
410   /**
411    * Returs the full name of this naming context. The returned string is not a
412    * JNDI composite name and should not be passed directly to the methods of the
413    * naming context. This implementation returns the IOR.
414    * 
415    * @return the full name of this naming context, in its own namespace.
416    * @throws OperationNotSupportedException
417    *           if the naming system, represented by this context, does not
418    *           support the notation of the full name.
419    * @throws NamingException
420    */
421   public String getNameInNamespace() throws NamingException
422   {
423     if (orb != null)
424       return orb.object_to_string(service);
425     else
426       {
427         try
428           {
429             ObjectImpl impl = (ObjectImpl) service;
430             return impl._orb().object_to_string(impl);
431           }
432         catch (ClassCastException e)
433           {
434             throw new UnsupportedOperationException();
435           }
436       }
437   }
438
439   /**
440    * Not supported.
441    */
442   public NameParser getNameParser(Name name) throws NamingException
443   {
444     throw new UnsupportedOperationException();
445   }
446
447   /**
448    * Not supported.
449    */
450   public NameParser getNameParser(String name) throws NamingException
451   {
452     throw new UnsupportedOperationException();
453   }
454
455   /**
456    * Creates and returns the enumeration over the name bindings that are present
457    * the given subcontext. The enumeration elements have the type of
458    * {@link NameClassPair}, providing also information about the class of the
459    * bound object. The behaviour in the case if the bindings are added or
460    * removed later is not defined. The contents of the subcontexts are not
461    * included.
462    * 
463    * @param name
464    *          the name of the subcontext
465    * @return the enumeration over the names, known for the given subcontext.
466    * @throws NamingException
467    */
468   public NamingEnumeration list(Name name) throws NamingException
469   {
470     BindingIteratorHolder bi = new BindingIteratorHolder();
471     BindingListHolder bl = new BindingListHolder();
472
473     NamingContext subcontext;
474
475     if (name.size() == 0)
476       subcontext = service;
477     else
478       {
479         try
480           {
481             subcontext = (NamingContextHelper.narrow(service.resolve(toGiop(name))));
482           }
483         catch (Exception e)
484           {
485             throw new NamingException(e.toString());
486           }
487
488       }
489
490     subcontext.list(howMany, bl, bi);
491
492     return new ListEnumeration(bl, bi, howMany);
493   }
494
495   /**
496    * Creates and returns the enumeration over the name bindings that are present
497    * the given subcontext. The enumeration elements have the type of
498    * {@link NameClassPair}, providing also information about the class of the
499    * bound object. The behaviour in the case if the bindings are added or
500    * removed later is not defined. The contents of the subcontexts are not
501    * included.
502    * 
503    * @param name
504    *          the name of the subcontext
505    * @return the enumeration over the names, known for the given subcontext.
506    * @throws NamingException
507    */
508   public NamingEnumeration list(String name) throws NamingException
509   {
510     BindingIteratorHolder bi = new BindingIteratorHolder();
511     BindingListHolder bl = new BindingListHolder();
512
513     NamingContext subcontext;
514
515     if (name.length() == 0)
516       subcontext = service;
517     else
518       {
519         try
520           {
521             subcontext = (NamingContextHelper.narrow(service.resolve_str(name)));
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 ListEnumeration(bl, bi, howMany);
533   }
534
535   /**
536    * Creates and returns the enumeration over the name - object bindings that
537    * are present the given subcontext. The enumeration elements have the type of
538    * {@link Binding}, providing also information about the class of the bound
539    * object. The behaviour in the case if the bindings are added or removed
540    * later is not defined. The contents of the subcontexts are not included.
541    * 
542    * @param name
543    *          the name of the subcontext
544    * @return the enumeration over the names, known for the given subcontext.
545    * @throws NamingException
546    */
547   public NamingEnumeration listBindings(Name name) throws NamingException
548   {
549     BindingIteratorHolder bi = new BindingIteratorHolder();
550     BindingListHolder bl = new BindingListHolder();
551
552     NamingContext subcontext;
553
554     if (name.size() == 0)
555       subcontext = service;
556     else
557       {
558         try
559           {
560             subcontext = (NamingContextHelper.narrow(service.resolve(toGiop(name))));
561           }
562         catch (Exception e)
563           {
564             throw new NamingException(e.toString());
565           }
566       }
567
568     subcontext.list(howMany, bl, bi);
569
570     return new ListBindingsEnumeration(bl, bi, howMany, subcontext);
571   }
572
573   /**
574    * Creates and returns the enumeration over the name - object bindings that
575    * are present the given subcontext. The enumeration elements have the type of
576    * {@link Binding}, providing also information about the class of the bound
577    * object. The behaviour in the case if the bindings are added or removed
578    * later is not defined. The contents of the subcontexts are not included.
579    * 
580    * @param name
581    *          the name of the subcontext
582    * @return the enumeration over the names, known for the given subcontext.
583    * @throws NamingException
584    */
585   public NamingEnumeration listBindings(String name) throws NamingException
586   {
587     BindingIteratorHolder bi = new BindingIteratorHolder();
588     BindingListHolder bl = new BindingListHolder();
589
590     NamingContext subcontext;
591
592     if (name.length() == 0)
593       subcontext = service;
594     else
595       {
596         try
597           {
598             subcontext = (NamingContextHelper.narrow(service.resolve_str(name)));
599           }
600         catch (Exception e)
601           {
602             throw new NamingException(e.toString());
603           }
604
605       }
606
607     subcontext.list(howMany, bl, bi);
608
609     return new ListBindingsEnumeration(bl, bi, howMany, subcontext);
610   }
611
612   /**
613    * Gets the previously named object by name. If the passed name is empty, the
614    * method should return a cloned instance of this naming context.
615    * 
616    * @param name
617    *          the name of the object being searched in this context
618    * @return the named object
619    * @throws NameNotFountException
620    *           if the name is not found
621    */
622   public Object lookup(Name name) throws NamingException
623   {
624     try
625       {
626         return service.resolve(toGiop(name));
627       }
628     catch (NotFound e)
629       {
630         throw new NameNotFoundException();
631       }
632     catch (InvalidName e)
633       {
634         throw new InvalidNameException();
635       }
636     catch (Exception e)
637       {
638         throw new NamingException(e.toString());
639       }
640   }
641
642   /**
643    * Gets the previously named object by name. If the passed name is empty, the
644    * method should return a cloned instance of this naming context.
645    * 
646    * @param name
647    *          the name of the object being searched in this context
648    * @return the named object
649    * @throws NamingException
650    *           if the naming fails.
651    */
652   public Object lookup(String name) throws NamingException
653   {
654     try
655       {
656         return service.resolve_str(name);
657       }
658     catch (NotFound e)
659       {
660         throw new NameNotFoundException();
661       }
662     catch (InvalidName e)
663       {
664         throw new InvalidNameException();
665       }
666     catch (Exception e)
667       {
668         throw new NamingException(e.toString());
669       }
670   }
671
672   /**
673    * Not supported.
674    */
675   public Object lookupLink(Name name) throws NamingException
676   {
677     throw new OperationNotSupportedException();
678   }
679
680   /**
681    * Not supported.
682    */
683   public Object lookupLink(String name) throws NamingException
684   {
685     throw new OperationNotSupportedException();
686   }
687
688   /**
689    * Give the specified name for the specified object. Unlike bind, this method
690    * silently replaces the existing binding for this name, if one exists.
691    * 
692    * @param name
693    *          the name that will be given to the object (in the scope of this
694    *          context).
695    * @param obj
696    *          the object being named.
697    * @throws InvalidAttributesException
698    *           if the object does not supply all required attributes.
699    * @throws NamingException
700    *           if the naming operation has failed due other reasons.
701    */
702   public void rebind(Name name, Object obj) throws NamingException
703   {
704     try
705       {
706         org.omg.CORBA.Object object = (org.omg.CORBA.Object) obj;
707         service.rebind(toGiop(name), object);
708       }
709     catch (ClassCastException e)
710       {
711         throw new NamingException(org.omg.CORBA.Object.class + " required ");
712       }
713     catch (InvalidName e)
714       {
715         throw new InvalidNameException();
716       }
717     catch (Exception e)
718       {
719         throw new NamingException(e.toString());
720       }
721   }
722
723   /**
724    * Give the specified name for the specified object. Unlike bind, this method
725    * silently replaces the existing binding for this name, if one exists.
726    * 
727    * @param name
728    *          the name that will be given to the object (in the scope of this
729    *          context).
730    * @param obj
731    *          the object being named.
732    * @throws InvalidAttributesException
733    *           if the object does not supply all required attributes.
734    * @throws NamingException
735    *           if the naming operation has failed due other reasons.
736    */
737   public void rebind(String name, Object obj) throws NamingException
738   {
739     try
740       {
741         org.omg.CORBA.Object object = (org.omg.CORBA.Object) obj;
742         service.rebind(transformer.toName(name), object);
743       }
744     catch (ClassCastException e)
745       {
746         throw new NamingException(org.omg.CORBA.Object.class + " required ");
747       }
748     catch (InvalidName e)
749       {
750         throw new InvalidNameException();
751       }
752     catch (Exception e)
753       {
754         throw new NamingException(e.toString());
755       }
756   }
757
758   /**
759    * Renames the existing binding, removing the existing and giving the new name
760    * for the same object.
761    * 
762    * @param oldName
763    *          the existing name of the known object
764    * @param newName
765    *          the new name of the same object
766    * @throws NameNotFoundException
767    *           if the oldName is unknown for this context
768    * @throws NamingException
769    *           if the naming operation has failed due other reasons.
770    */
771   public void rename(Name oldName, Name newName) throws NamingException
772   {
773     Object object = lookup(oldName);
774     unbind(oldName);
775     bind(newName, object);
776   }
777
778   /**
779    * Renames the existing binding, removing the existing and giving the new name
780    * for the same object.
781    * 
782    * @param oldName
783    *          the existing name of the known object
784    * @param newName
785    *          the new name of the same object
786    * @throws NameNotFoundException
787    *           if the oldName is unknown for this context
788    * @throws NamingException
789    *           if the naming operation has failed due other reasons.
790    */
791   public void rename(String oldName, String newName) throws NamingException
792   {
793     Object object = lookup(oldName);
794     unbind(oldName);
795     bind(newName, object);
796   }
797
798   /**
799    * Removes the name - object mapping from the current context. This method
800    * returns without action if the name is not bound to an object in the
801    * terminal context, but throws {@link NameNotFoundException} if one of the
802    * intermadiate contexts does not exist.
803    * 
804    * @param name
805    *          the name to be removed
806    * @throws NameNotFoundException
807    *           if one of the intermediate naming contexts does not exist. Will
808    *           not be thrown if just the terminal binding is missing.
809    * @throws NamingException
810    *           if the naming operation has failed due other reasons.
811    */
812   public void unbind(Name name) throws NamingException
813   {
814     try
815       {
816         service.unbind(toGiop(name));
817       }
818     catch (NotFound e)
819       {
820         throw new NameNotFoundException();
821       }
822     catch (CannotProceed e)
823       {
824         throw new ContextNotEmptyException();
825       }
826     catch (InvalidName e)
827       {
828         throw new InvalidNameException();
829       }
830   }
831
832   /**
833    * Removes the name - object mapping from the current context. This method
834    * returns without action if the name is not bound to an object in the
835    * terminal context, but throws {@link NameNotFoundException} if one of the
836    * intermadiate contexts does not exist.
837    * 
838    * @param name
839    *          the name to be removed
840    * @throws NameNotFoundException
841    *           if one of the intermediate naming contexts does not exist. Will
842    *           not be thrown if just the terminal binding is missing.
843    * @throws NamingException
844    *           if the naming operation has failed due other reasons.
845    */
846   public void unbind(String name) throws NamingException
847   {
848     try
849       {
850         service.unbind(transformer.toName(name));
851       }
852     catch (NotFound e)
853       {
854         throw new NameNotFoundException(name);
855       }
856     catch (CannotProceed e)
857       {
858         throw new ContextNotEmptyException(name);
859       }
860     catch (InvalidName e)
861       {
862         throw new InvalidNameException(name);
863       }
864   }
865   
866  /**
867    * Add new environment property to the environment of this context. Both name
868    * and value of the new property must not be null. If the property is already
869    * defined, is current value is replaced by the propVal.
870    * 
871    * @param key
872    *          the name of the new property
873    * @param value
874    *          the value of the new property
875    * @return the previous value of this property or null if the property has not
876    *         been previously defined
877    * @throws NamingException
878    */
879   public Object addToEnvironment(String key, Object value)
880       throws NamingException
881   {
882     if (key == null || value == null)
883       throw new NullPointerException();
884     return properties.put(key, value);
885   }
886
887   /**
888    * Returns the environment, associated with this naming context. The returned
889    * table should never be modified by the caller. Use {@link #addToEnvironment}
890    * and {@link #removeFromEnvironment} to modify the environement, if needed.
891    * 
892    * @return the table, representing the environment of this context
893    * @throws NamingException
894    */
895   public Hashtable getEnvironment() throws NamingException
896   {
897     return properties;
898   }
899
900   /**
901    * Removes the property with the given name from the environment. Returns
902    * without action if this property is not defined.
903    * 
904    * @param propName
905    *          the name of the property being removed.
906    * @return the value of the property that has been removed or null if the
907    *         property was not defined.
908    * @throws NamingException
909    */
910   public Object removeFromEnvironment(String propName) throws NamingException
911   {
912     return properties.remove(propName);
913   }
914   
915   /**
916    * Convert the {@link Name} into array of the name components, required to the
917    * CORBA naming service. First the string representation is obtained, then
918    * it is converted using parsing rules of the CORBA name.
919    * 
920    * @param name
921    *          then name to convert
922    * @return the converted array of components.
923    */
924   public NameComponent[] toGiop(Name name) throws InvalidName
925   {
926     return transformer.toName(name.toString());
927   }
928   
929   /**
930    * Get the batch size from the environment properties. The batch size is used
931    * for listing operations.
932    * 
933    * @return the batch size, or some default value if not specified.
934    */
935   public int getBatchSize()
936   {
937     int batchSize = DEFAULT_BATCH_SIZE;
938     Object bs = properties.get(Context.BATCHSIZE);
939     if (bs != null)
940       {
941         try
942           {
943             int b = Integer.parseInt(bs.toString());
944             if (b >= 0)
945               batchSize = b;
946           }
947         catch (NumberFormatException e)
948           {
949             // OK, use default value.
950           }
951       }
952     return batchSize;
953   }
954   
955   
956 }