NamingContextImpl.java revision 608:7e06bf1dcb09
1/*
2 * Copyright (c) 1996, 2003, 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.corba.se.impl.naming.cosnaming;
27
28// Imports for Logging
29import java.util.logging.Logger;
30import java.util.logging.Level;
31import com.sun.corba.se.impl.orbutil.LogKeywords;
32
33// Import general CORBA classes
34import org.omg.CORBA.Object;
35import org.omg.CORBA.BAD_PARAM;
36import org.omg.CORBA.INTERNAL;
37import org.omg.CORBA.CompletionStatus;
38import org.omg.PortableServer.POA;
39import org.omg.PortableServer.Servant;
40
41// Import org.omg.CosNaming classes
42import org.omg.CosNaming.BindingType;
43import org.omg.CosNaming.BindingTypeHolder;
44import org.omg.CosNaming.BindingListHolder;
45import org.omg.CosNaming.BindingIteratorHolder;
46import org.omg.CosNaming.NameComponent;
47import org.omg.CosNaming.NamingContextHelper;
48import org.omg.CosNaming.NamingContext;
49import org.omg.CosNaming.NamingContextPackage.*;
50import org.omg.CosNaming._NamingContextImplBase;
51import org.omg.CosNaming.NamingContextExtHelper;
52import org.omg.CosNaming.NamingContextExt;
53import org.omg.CosNaming.NamingContextExtPOA;
54import org.omg.CosNaming.NamingContextExtPackage.*;
55import org.omg.CosNaming.NamingContextPackage.NotFound;
56
57import com.sun.corba.se.impl.naming.cosnaming.NamingContextDataStore;
58
59import com.sun.corba.se.impl.naming.namingutil.INSURLHandler;
60import com.sun.corba.se.spi.logging.CORBALogDomains;
61import com.sun.corba.se.impl.logging.NamingSystemException ;
62
63import com.sun.corba.se.spi.orb.ORB;
64
65/**
66 * Class NamingContextImpl implements the org.omg.CosNaming::NamingContext
67 * interface, but does not implement the methods associated with
68 * maintaining the "table" of current bindings in a NamingContext.
69 * Instead, this implementation assumes that the derived implementation
70 * implements the NamingContextDataStore interface, which has the necessary
71 * methods. This allows multiple
72 * NamingContext implementations that differ in storage of the bindings,
73 * as well as implementations of interfaces derived from
74 * CosNaming::NamingContext that still reuses the implementation.
75 * <p>
76 * The operations bind(), rebind(), bind_context() and rebind_context()
77 * are all really implemented by doBind(). resolve() is really implemented
78 * by doResolve(), unbind() by doUnbind(). list(), new_context() and
79 * destroy() uses the NamingContextDataStore interface directly. All the
80 * doX() methods are public static.
81 * They synchronize on the NamingContextDataStore object.
82 * <p>
83 * An implementation a NamingContext must extend this class and implement
84 * the NamingContextDataStore interface with the operations:
85 * Bind(), Resolve(),
86 * Unbind(), List(), NewContext() and Destroy(). Calls
87 * to these methods are synchronized; these methods should
88 * therefore not be synchronized.
89 */
90public abstract class NamingContextImpl
91    extends NamingContextExtPOA
92    implements NamingContextDataStore
93{
94
95    protected POA nsPOA;
96    private Logger readLogger, updateLogger, lifecycleLogger;
97    private NamingSystemException wrapper ;
98    private static NamingSystemException staticWrapper =
99        NamingSystemException.get( CORBALogDomains.NAMING_UPDATE ) ;
100
101    // The grammer for Parsing and Building Interoperable Stringified Names
102    // are implemented in this class
103    private InterOperableNamingImpl insImpl;
104    /**
105     * Create a naming context servant.
106     * Runs the super constructor.
107     * @param orb an ORB object.
108     * @exception java.lang.Exception a Java exception.
109     */
110    public NamingContextImpl(ORB orb, POA poa) throws java.lang.Exception {
111        super();
112        this.orb = orb;
113        wrapper = NamingSystemException.get( orb,
114            CORBALogDomains.NAMING_UPDATE ) ;
115
116        insImpl = new InterOperableNamingImpl( );
117        this.nsPOA = poa;
118        readLogger = orb.getLogger( CORBALogDomains.NAMING_READ);
119        updateLogger = orb.getLogger( CORBALogDomains.NAMING_UPDATE);
120        lifecycleLogger = orb.getLogger(
121            CORBALogDomains.NAMING_LIFECYCLE);
122    }
123
124    public POA getNSPOA( ) {
125        return nsPOA;
126    }
127
128    /**
129     * Bind an object under a name in this NamingContext. If the name
130     * contains multiple (n) components, n-1 will be resolved in this
131     * NamingContext and the object bound in resulting NamingContext.
132     * An exception is thrown if a binding with the supplied name already
133     * exists. If the
134     * object to be bound is a NamingContext it will not participate in
135     * a recursive resolve.
136     * @param n a sequence of NameComponents which is the name under which
137     * the object will be bound.
138     * @param obj the object reference to be bound.
139     * @exception org.omg.CosNaming.NamingContextPackage.NotFound A name with
140     * multiple components was supplied, but the first component could not be
141     * resolved.
142     * @exception org.omg.CosNaming.NamingContextPackage.CannotProceed Could
143     * not proceed in resolving the n-1 components of the supplied name.
144     * @exception org.omg.CosNaming.NamingContextPackage.InvalidName The
145     * supplied name is invalid (i.e., has length less than 1).
146     * @exception org.omg.CosNaming.NamingContextPackage.AlreadyBound An object
147     * is already bound under the supplied name.
148     * @exception org.omg.CORBA.SystemException One of a fixed set of CORBA
149     * system exceptions.
150     * @see doBind
151     */
152    public void bind(NameComponent[] n, org.omg.CORBA.Object obj)
153        throws org.omg.CosNaming.NamingContextPackage.NotFound,
154               org.omg.CosNaming.NamingContextPackage.CannotProceed,
155               org.omg.CosNaming.NamingContextPackage.InvalidName,
156               org.omg.CosNaming.NamingContextPackage.AlreadyBound
157    {
158        if( obj == null )
159        {
160            updateLogger.warning( LogKeywords.NAMING_BIND +
161                " unsuccessful because NULL Object cannot be Bound " );
162            throw wrapper.objectIsNull() ;
163        }
164        // doBind implements all four flavors of binding
165        NamingContextDataStore impl = (NamingContextDataStore)this;
166        doBind(impl,n,obj,false,BindingType.nobject);
167        if( updateLogger.isLoggable( Level.FINE  ) ) {
168            // isLoggable call to make sure that we save some precious
169            // processor cycles, if there is no need to log.
170            updateLogger.fine( LogKeywords.NAMING_BIND_SUCCESS + " Name = " +
171                NamingUtils.getDirectoryStructuredName( n ) );
172        }
173    }
174
175
176    /**
177     * Bind a NamingContext under a name in this NamingContext. If the name
178     * contains multiple (n) components, n-1 will be resolved in this
179     * NamingContext and the object bound in resulting NamingContext.
180     * An exception is thrown if a binding with the supplied name already
181     * exists. The NamingContext will participate in recursive resolving.
182     * @param n a sequence of NameComponents which is the name under which
183     * the object will be bound.
184     * @param obj the NamingContect object reference to be bound.
185     * @exception org.omg.CosNaming.NamingContextPackage.NotFound A name with
186     * multiple components was supplied, but the first component could not be
187     * resolved.
188     * @exception org.omg.CosNaming.NamingContextPackage.CannotProceed Could
189     * not proceed in resolving the n-1 components of the supplied name.
190     * @exception org.omg.CosNaming.NamingContextPackage.InvalidName The
191     * supplied name is invalid (i.e., has length less than 1).
192     * @exception org.omg.CosNaming.NamingContextPackage.AlreadyBound An object
193     * is already bound under the supplied name.
194     * @exception org.omg.CORBA.SystemException One of a fixed set of CORBA
195     * system exceptions.
196     * @see doBind
197     */
198    public void bind_context(NameComponent[] n, NamingContext nc)
199        throws org.omg.CosNaming.NamingContextPackage.NotFound,
200               org.omg.CosNaming.NamingContextPackage.CannotProceed,
201               org.omg.CosNaming.NamingContextPackage.InvalidName,
202               org.omg.CosNaming.NamingContextPackage.AlreadyBound
203    {
204        if( nc == null ) {
205            updateLogger.warning( LogKeywords.NAMING_BIND_FAILURE +
206                " NULL Context cannot be Bound " );
207            throw new BAD_PARAM( "Naming Context should not be null " );
208        }
209        // doBind implements all four flavors of binding
210        NamingContextDataStore impl = (NamingContextDataStore)this;
211        doBind(impl,n,nc,false,BindingType.ncontext);
212        if( updateLogger.isLoggable( Level.FINE ) ) {
213            // isLoggable call to make sure that we save some precious
214            // processor cycles, if there is no need to log.
215            updateLogger.fine( LogKeywords.NAMING_BIND_SUCCESS + " Name = " +
216                NamingUtils.getDirectoryStructuredName( n ) );
217        }
218    }
219
220    /**
221     * Bind an object under a name in this NamingContext. If the name
222     * contains multiple (n) components, n-1 will be resolved in this
223     * NamingContext and the object bound in resulting NamingContext.
224     * If a binding under the supplied name already exists it will be
225     * unbound first. If the
226     * object to be bound is a NamingContext it will not participate in
227     * a recursive resolve.
228     * @param n a sequence of NameComponents which is the name under which
229     * the object will be bound.
230     * @param obj the object reference to be bound.
231     * @exception org.omg.CosNaming.NamingContextPackage.NotFound A name with
232     * multiple components was supplied, but the first component could not be
233     * resolved.
234     * @exception org.omg.CosNaming.NamingContextPackage.CannotProceed Could not
235     * proceed in resolving the n-1 components of the supplied name.
236     * @exception org.omg.CosNaming.NamingContextPackage.InvalidName The
237     * supplied name is invalid (i.e., has length less than 1).
238     * @exception org.omg.CORBA.SystemException One of a fixed set of CORBA
239     * system exceptions.
240     * @see doBind
241     */
242    public  void rebind(NameComponent[] n, org.omg.CORBA.Object obj)
243        throws       org.omg.CosNaming.NamingContextPackage.NotFound,
244                     org.omg.CosNaming.NamingContextPackage.CannotProceed,
245                     org.omg.CosNaming.NamingContextPackage.InvalidName
246    {
247        if( obj == null )
248        {
249            updateLogger.warning( LogKeywords.NAMING_REBIND_FAILURE +
250                " NULL Object cannot be Bound " );
251            throw wrapper.objectIsNull() ;
252        }
253        try {
254            // doBind implements all four flavors of binding
255            NamingContextDataStore impl = (NamingContextDataStore)this;
256            doBind(impl,n,obj,true,BindingType.nobject);
257        } catch (org.omg.CosNaming.NamingContextPackage.AlreadyBound ex) {
258            updateLogger.warning( LogKeywords.NAMING_REBIND_FAILURE +
259                NamingUtils.getDirectoryStructuredName( n ) +
260                " is already bound to a Naming Context" );
261            // This should not happen
262            throw wrapper.namingCtxRebindAlreadyBound( ex ) ;
263        }
264        if( updateLogger.isLoggable( Level.FINE  ) ) {
265            // isLoggable call to make sure that we save some precious
266            // processor cycles, if there is no need to log.
267            updateLogger.fine( LogKeywords.NAMING_REBIND_SUCCESS + " Name = " +
268                NamingUtils.getDirectoryStructuredName( n ) );
269        }
270    }
271
272    /**
273     * Bind a NamingContext under a name in this NamingContext. If the name
274     * contains multiple (n) components, the first n-1 components will be
275     * resolved in this NamingContext and the object bound in resulting
276     * NamingContext. If a binding under the supplied name already exists it
277     * will be unbound first. The NamingContext will participate in recursive
278     * resolving.
279     * @param n a sequence of NameComponents which is the name under which
280     * the object will be bound.
281     * @param obj the object reference to be bound.
282     * @exception org.omg.CosNaming.NamingContextPackage.NotFound A name with
283     * multiple components was supplied, but the first component could not be
284     * resolved.
285     * @exception org.omg.CosNaming.NamingContextPackage.CannotProceed Could not
286     * proceed in resolving the n-1 components of the supplied name.
287     * @exception org.omg.CosNaming.NamingContextPackage.InvalidName The
288     * supplied name is invalid (i.e., has length less than 1).
289     * @exception org.omg.CORBA.SystemException One of a fixed set of CORBA
290     * system exceptions.
291     * @see doBind
292     */
293    public  void rebind_context(NameComponent[] n, NamingContext nc)
294        throws org.omg.CosNaming.NamingContextPackage.NotFound,
295               org.omg.CosNaming.NamingContextPackage.CannotProceed,
296               org.omg.CosNaming.NamingContextPackage.InvalidName
297    {
298        if( nc == null )
299        {
300            updateLogger.warning( LogKeywords.NAMING_REBIND_FAILURE +
301                " NULL Context cannot be Bound " );
302            throw wrapper.objectIsNull() ;
303        }
304        try {
305            // doBind implements all four flavors of binding
306            NamingContextDataStore impl = (NamingContextDataStore)this;
307            doBind(impl,n,nc,true,BindingType.ncontext);
308        } catch (org.omg.CosNaming.NamingContextPackage.AlreadyBound ex) {
309            // This should not happen
310            updateLogger.warning( LogKeywords.NAMING_REBIND_FAILURE +
311                NamingUtils.getDirectoryStructuredName( n ) +
312                " is already bound to a CORBA Object" );
313            throw wrapper.namingCtxRebindctxAlreadyBound( ex ) ;
314        }
315        if( updateLogger.isLoggable( Level.FINE ) ) {
316            // isLoggable call to make sure that we save some precious
317            // processor cycles, if there is no need to log.
318            updateLogger.fine( LogKeywords.NAMING_REBIND_SUCCESS + " Name = " +
319                NamingUtils.getDirectoryStructuredName( n ) );
320        }
321    }
322
323    /**
324     * Resolve a name in this NamingContext and return the object reference
325     * bound to the name. If the name contains multiple (n) components,
326     * the first component will be resolved in this NamingContext and the
327     * remaining components resolved in the resulting NamingContext, provided
328     * that the NamingContext bound to the first component of the name was
329     * bound with bind_context().
330     * @param n a sequence of NameComponents which is the name to be resolved.
331     * @return the object reference bound under the supplied name.
332     * @exception org.omg.CosNaming.NamingContextPackage.NotFound A name with
333     * multiple components was supplied, but the first component could not be
334     * resolved.
335     * @exception org.omg.CosNaming.NamingContextPackage.CannotProceed Could not
336     * proceed in resolving the n-1 components of the supplied name.
337     * @exception org.omg.CosNaming.NamingContextPackage.InvalidName The
338     * supplied name is invalid (i.e., has length less than 1).
339     * @exception org.omg.CORBA.SystemException One of a fixed set of CORBA
340     * system exceptions.
341     * @see doResolve
342     */
343    public  org.omg.CORBA.Object resolve(NameComponent[] n)
344        throws org.omg.CosNaming.NamingContextPackage.NotFound,
345               org.omg.CosNaming.NamingContextPackage.CannotProceed,
346               org.omg.CosNaming.NamingContextPackage.InvalidName
347    {
348        // doResolve actually resolves
349        NamingContextDataStore impl = (NamingContextDataStore)this;
350        org.omg.CORBA.Object obj = doResolve(impl,n);
351        if( obj != null ) {
352            if( readLogger.isLoggable( Level.FINE ) ) {
353                 readLogger.fine( LogKeywords.NAMING_RESOLVE_SUCCESS +
354                 " Name: " + NamingUtils.getDirectoryStructuredName( n ) );
355            }
356        } else {
357             readLogger.warning( LogKeywords.NAMING_RESOLVE_FAILURE +
358                 " Name: " + NamingUtils.getDirectoryStructuredName( n ) );
359        }
360        return obj;
361    }
362
363
364    /**
365     * Remove a binding from this NamingContext. If the name contains
366     * multiple (n) components, the first n-1 components will be resolved
367     * from this NamingContext and the final component unbound in
368     * the resulting NamingContext.
369     * @param n a sequence of NameComponents which is the name to be unbound.
370     * @exception org.omg.CosNaming.NamingContextPackage.NotFound A name with
371     * multiple components was supplied, but the first component could not be
372     * resolved.
373     * @exception org.omg.CosNaming.NamingContextPackage.CannotProceed Could not
374     * proceed in resolving the n-1 components of the supplied name.
375     * @exception org.omg.CosNaming.NamingContextPackage.InvalidName The
376     * supplied name is invalid (i.e., has length less than 1).
377     * @exception org.omg.CORBA.SystemException One of a fixed set of CORBA
378     * system exceptions.
379     * @see doUnbind
380     */
381    public  void unbind(NameComponent[] n)
382        throws org.omg.CosNaming.NamingContextPackage.NotFound,
383               org.omg.CosNaming.NamingContextPackage.CannotProceed,
384               org.omg.CosNaming.NamingContextPackage.InvalidName
385    {
386        // doUnbind actually unbinds
387        NamingContextDataStore impl = (NamingContextDataStore)this;
388        doUnbind(impl,n);
389        if( updateLogger.isLoggable( Level.FINE ) ) {
390            // isLoggable call to make sure that we save some precious
391            // processor cycles, if there is no need to log.
392            updateLogger.fine( LogKeywords.NAMING_UNBIND_SUCCESS +
393                " Name: " + NamingUtils.getDirectoryStructuredName( n ) );
394        }
395    }
396
397    /**
398     * List the contents of this NamingContest. A sequence of bindings
399     * is returned (a BindingList) containing up to the number of requested
400     * bindings, and a BindingIterator object reference is returned for
401     * iterating over the remaining bindings.
402     * @param how_many The number of requested bindings in the BindingList.
403     * @param bl The BindingList as an out parameter.
404     * @param bi The BindingIterator as an out parameter.
405     * @exception org.omg.CORBA.SystemException One of a fixed set of CORBA
406     * system exceptions.
407     * @see BindingListHolder
408     * @see BindingIteratorImpl
409     */
410    public  void list(int how_many, BindingListHolder bl,
411        BindingIteratorHolder bi)
412    {
413        // List actually generates the list
414        NamingContextDataStore impl = (NamingContextDataStore)this;
415        synchronized (impl) {
416            impl.List(how_many,bl,bi);
417        }
418        if( readLogger.isLoggable( Level.FINE ) && (bl.value != null )) {
419            // isLoggable call to make sure that we save some precious
420            // processor cycles, if there is no need to log.
421            readLogger.fine ( LogKeywords.NAMING_LIST_SUCCESS +
422                "list(" + how_many + ") -> bindings[" + bl.value.length +
423                "] + iterator: " + bi.value);
424        }
425    }
426
427    /**
428     * Create a NamingContext object and return its object reference.
429     * @return an object reference for a new NamingContext object implemented
430     * by this Name Server.
431     * @exception org.omg.CORBA.SystemException One of a fixed set of CORBA
432     * system exceptions.
433     */
434    public synchronized NamingContext new_context()
435    {
436        // Create actually creates a new naming context
437        lifecycleLogger.fine( "Creating New Naming Context " );
438        NamingContextDataStore impl = (NamingContextDataStore)this;
439        synchronized (impl) {
440            NamingContext nctx = impl.NewContext();
441            if( nctx != null ) {
442                lifecycleLogger.fine( LogKeywords.LIFECYCLE_CREATE_SUCCESS );
443            } else {
444                // If naming context is null, then that must be a serious
445                // error.
446                lifecycleLogger.severe ( LogKeywords.LIFECYCLE_CREATE_FAILURE );
447            }
448            return nctx;
449        }
450    }
451
452    /**
453     * Create a new NamingContext, bind it in this Naming Context and return
454     * its object reference. This is equivalent to using new_context() followed
455     * by bind_context() with the supplied name and the object reference for
456     * the newly created NamingContext.
457     * @param n a sequence of NameComponents which is the name to be unbound.
458     * @return an object reference for a new NamingContext object implemented
459     * by this Name Server, bound to the supplied name.
460     * @exception org.omg.CosNaming.NamingContextPackage.AlreadyBound An object
461     * is already bound under the supplied name.
462     * @exception org.omg.CosNaming.NamingContextPackage.NotFound A name with
463     * multiple components was supplied, but the first component could not be
464     * resolved.
465     * @exception org.omg.CosNaming.NamingContextPackage.CannotProceed Could not
466     * proceed in resolving the n-1 components of the supplied name.
467     * @exception org.omg.CosNaming.NamingContextPackage.InvalidName The
468     * supplied name is invalid (i.e., has length less than 1).
469     * @exception org.omg.CORBA.SystemException One of a fixed set of CORBA
470     * system exceptions.
471     * @see new_context
472     * @see bind_context
473     */
474    public  NamingContext bind_new_context(NameComponent[] n)
475        throws org.omg.CosNaming.NamingContextPackage.NotFound,
476               org.omg.CosNaming.NamingContextPackage.AlreadyBound,
477               org.omg.CosNaming.NamingContextPackage.CannotProceed,
478               org.omg.CosNaming.NamingContextPackage.InvalidName
479    {
480        NamingContext nc = null;
481        NamingContext rnc = null;
482        try {
483            if (debug)
484                dprint("bind_new_context " + nameToString(n));
485            // The obvious solution:
486            nc = this.new_context();
487            this.bind_context(n,nc);
488            rnc = nc;
489            nc = null;
490        } finally {
491            try {
492                if(nc != null)
493                    nc.destroy();
494            } catch (org.omg.CosNaming.NamingContextPackage.NotEmpty e) {
495            }
496        }
497        if( updateLogger.isLoggable( Level.FINE ) ) {
498            // isLoggable call to make sure that we save some precious
499            // processor cycles, if there is no need to log.
500            updateLogger.fine ( LogKeywords.NAMING_BIND +
501                "New Context Bound To " +
502                NamingUtils.getDirectoryStructuredName( n ) );
503        }
504        return rnc;
505    }
506
507    /**
508     * Destroy this NamingContext object. If this NamingContext contains
509     * no bindings, the NamingContext is deleted.
510     * @exception org.omg.CosNaming.NamingContextPackage.NotEmpty This
511     * NamingContext is not empty (i.e., contains bindings).
512     * @exception org.omg.CORBA.SystemException One of a fixed set of CORBA
513     * system exceptions.
514     */
515    public  void destroy()
516        throws org.omg.CosNaming.NamingContextPackage.NotEmpty
517    {
518        lifecycleLogger.fine( "Destroying Naming Context " );
519        NamingContextDataStore impl = (NamingContextDataStore)this;
520        synchronized (impl) {
521            if (impl.IsEmpty() == true) {
522                // The context is empty so it can be destroyed
523                impl.Destroy();
524                lifecycleLogger.fine ( LogKeywords.LIFECYCLE_DESTROY_SUCCESS );
525            }
526            else {
527                // This context is not empty!
528                // Not a fatal error, warning should do.
529                lifecycleLogger.warning( LogKeywords.LIFECYCLE_DESTROY_FAILURE +
530                    " NamingContext children are not destroyed still.." );
531                throw new NotEmpty();
532            }
533        }
534    }
535
536    /**
537     * Implements all four flavors of binding. It uses Resolve() to
538     * check if a binding already exists (for bind and bind_context), and
539     * unbind() to ensure that a binding does not already exist.
540     * If the length of the name is 1, then Bind() is called with
541     * the name and the object to bind. Otherwise, the first component
542     * of the name is resolved in this NamingContext and the appropriate
543     * form of bind passed to the resulting NamingContext.
544     * This method is static for maximal reuse - even for extended naming
545     * context implementations where the recursive semantics still apply.
546     * @param impl an implementation of NamingContextDataStore
547     * @param n a sequence of NameComponents which is the name under which
548     * the object will be bound.
549     * @param obj the object reference to be bound.
550     * @param rebind Replace an existing binding or not.
551     * @param bt Type of binding (as object or as context).
552     * @exception org.omg.CosNaming.NamingContextPackage.NotFound A name with
553     * multiple components was supplied, but the first component could not be
554     * resolved.
555     * @exception org.omg.CosNaming.NamingContextPackage.CannotProceed Could not     * proceed
556     * in resolving the first component of the supplied name.
557     * @exception org.omg.CosNaming.NamingContextPackage.InvalidName The
558     * supplied name is invalid (i.e., has length less than 1).
559     * @exception org.omg.CosNaming.NamingContextPackage.AlreadyBound An object
560     * is already bound under the supplied name.
561     * @exception org.omg.CORBA.SystemException One of a fixed set of CORBA
562     * system exceptions.
563     * @see resolve
564     * @see unbind
565     * @see bind
566     * @see bind_context
567     * @see rebind
568     * @see rebind_context
569     */
570    public static void doBind(NamingContextDataStore impl,
571                              NameComponent[] n,
572                              org.omg.CORBA.Object obj,
573                              boolean rebind,
574                              org.omg.CosNaming.BindingType bt)
575        throws org.omg.CosNaming.NamingContextPackage.NotFound,
576               org.omg.CosNaming.NamingContextPackage.CannotProceed,
577               org.omg.CosNaming.NamingContextPackage.InvalidName,
578               org.omg.CosNaming.NamingContextPackage.AlreadyBound
579    {
580        // Valid name?
581        if (n.length < 1)
582            throw new InvalidName();
583
584    // At bottom level?
585        if (n.length == 1) {
586            // The identifier must be set
587            if ( (n[0].id.length() == 0) && (n[0].kind.length() == 0 ) ) {
588                throw new InvalidName();
589            }
590
591            // Ensure synchronization of backend
592            synchronized (impl) {
593                // Yes: bind object in this context under the name
594                BindingTypeHolder bth = new BindingTypeHolder();
595                if (rebind) {
596                    org.omg.CORBA.Object objRef = impl.Resolve( n[0], bth );
597                    if( objRef != null ) {
598                        // Refer Naming Service Doc:00-11-01 section 2.2.3.4
599                        // If there is an object already bound with the name
600                        // and the binding type is not ncontext a NotFound
601                        // Exception with a reason of not a context has to be
602                        // raised.
603                        // Fix for bug Id: 4384628
604                        if ( bth.value.value() == BindingType.nobject.value() ){
605                            if ( bt.value() == BindingType.ncontext.value() ) {
606                                throw new NotFound(
607                                    NotFoundReason.not_context, n);
608                            }
609                        } else {
610                            // Previously a Context was bound and now trying to
611                            // bind Object. It is invalid.
612                            if ( bt.value() == BindingType.nobject.value() ) {
613                                throw new NotFound(
614                                    NotFoundReason.not_object, n);
615                            }
616                        }
617                        impl.Unbind(n[0]);
618                    }
619
620                } else {
621                    if (impl.Resolve(n[0],bth) != null)
622                        // "Resistence is futile." [Borg pickup line]
623                        throw new AlreadyBound();
624                }
625
626                // Now there are no other bindings under this name
627                impl.Bind(n[0],obj,bt);
628            }
629        } else {
630            // No: bind in a different context
631            NamingContext context = resolveFirstAsContext(impl,n);
632
633            // Compute tail
634            NameComponent[] tail = new NameComponent[n.length - 1];
635            System.arraycopy(n,1,tail,0,n.length-1);
636
637      // How should we propagate the bind
638            switch (bt.value()) {
639            case BindingType._nobject:
640                {
641                    // Bind as object
642                    if (rebind)
643                        context.rebind(tail,obj);
644                    else
645                        context.bind(tail,obj);
646                }
647                break;
648            case BindingType._ncontext:
649                {
650                    // Narrow to a naming context using Java casts. It must
651                    // work.
652                    NamingContext objContext = (NamingContext)obj;
653                    // Bind as context
654                    if (rebind)
655                        context.rebind_context(tail,objContext);
656                    else
657                        context.bind_context(tail,objContext);
658                }
659                break;
660            default:
661                // This should not happen
662                throw staticWrapper.namingCtxBadBindingtype() ;
663            }
664        }
665    }
666
667    /**
668   * Implements resolving names in this NamingContext. The first component
669   * of the supplied name is resolved in this NamingContext by calling
670   * Resolve(). If there are no more components in the name, the
671   * resulting object reference is returned. Otherwise, the resulting object
672   * reference must have been bound as a context and be narrowable to
673   * a NamingContext. If this is the case, the remaining
674   * components of the name is resolved in the resulting NamingContext.
675   * This method is static for maximal reuse - even for extended naming
676   * context implementations where the recursive semantics still apply.
677   * @param impl an implementation of NamingContextDataStore
678   * @param n a sequence of NameComponents which is the name to be resolved.
679   * @return the object reference bound under the supplied name.
680   * @exception org.omg.CosNaming.NamingContextPackage.NotFound A name with
681   * multiple components was supplied, but the first component could not be
682   * resolved.
683   * @exception org.omg.CosNaming.NamingContextPackage.CannotProceed Could not
684   * proceed
685   * in resolving the first component of the supplied name.
686   * @exception org.omg.CosNaming.NamingContextPackage.InvalidName The supplied
687   * name is invalid (i.e., has length less than 1).
688   * @exception org.omg.CORBA.SystemException One of a fixed set of CORBA system
689   * exceptions.
690   * @see resolve
691   */
692    public static org.omg.CORBA.Object doResolve(NamingContextDataStore impl,
693                                                 NameComponent[] n)
694        throws org.omg.CosNaming.NamingContextPackage.NotFound,
695               org.omg.CosNaming.NamingContextPackage.CannotProceed,
696               org.omg.CosNaming.NamingContextPackage.InvalidName
697    {
698        org.omg.CORBA.Object obj = null;
699        BindingTypeHolder bth = new BindingTypeHolder();
700
701
702        // Length must be greater than 0
703        if (n.length < 1)
704            throw new InvalidName();
705
706        // The identifier must be set
707        if (n.length == 1) {
708            synchronized (impl) {
709                // Resolve first level in this context
710                obj = impl.Resolve(n[0],bth);
711            }
712            if (obj == null) {
713                // Object was not found
714                throw new NotFound(NotFoundReason.missing_node,n);
715            }
716            return obj;
717        } else {
718            // n.length > 1
719            if ( (n[1].id.length() == 0) && (n[1].kind.length() == 0) ) {
720                throw new InvalidName();
721            }
722
723            NamingContext context = resolveFirstAsContext(impl,n);
724
725            // Compute restOfName = name[1..length]
726            NameComponent[] tail = new NameComponent[n.length -1];
727            System.arraycopy(n,1,tail,0,n.length-1);
728
729            // Resolve rest of name in context
730            try {
731                // First try to resolve using the local call, this should work
732                // most of the time unless there are federated naming contexts.
733                Servant servant = impl.getNSPOA().reference_to_servant(
734                    context );
735                return doResolve(((NamingContextDataStore)servant), tail) ;
736            } catch( Exception e ) {
737                return context.resolve(tail);
738            }
739        }
740    }
741
742    /**
743   * Implements unbinding bound names in this NamingContext. If the
744   * name contains only one component, the name is unbound in this
745   * NamingContext using Unbind(). Otherwise, the first component
746   * of the name is resolved in this NamingContext and
747   * unbind passed to the resulting NamingContext.
748   * This method is static for maximal reuse - even for extended naming
749   * context implementations where the recursive semantics still apply.
750   * @param impl an implementation of NamingContextDataStore
751   * @param n a sequence of NameComponents which is the name to be unbound.
752   * @exception org.omg.CosNaming.NamingContextPackage.NotFound A name with multiple
753   * components was supplied, but the first component could not be
754   * resolved.
755   * @exception org.omg.CosNaming.NamingContextPackage.CannotProceed Could not proceed
756   * in resolving the n-1 components of the supplied name.
757   * @exception org.omg.CosNaming.NamingContextPackage.InvalidName The supplied name
758   * is invalid (i.e., has length less than 1).
759   * @exception org.omg.CORBA.SystemException One of a fixed set of CORBA system exceptions.
760   * @see resolve
761   */
762    public static void doUnbind(NamingContextDataStore impl,
763                                NameComponent[] n)
764        throws org.omg.CosNaming.NamingContextPackage.NotFound,
765               org.omg.CosNaming.NamingContextPackage.CannotProceed,
766               org.omg.CosNaming.NamingContextPackage.InvalidName
767    {
768        // Name valid?
769        if (n.length < 1)
770            throw new InvalidName();
771
772    // Unbind here?
773        if (n.length == 1) {
774            // The identifier must be set
775            if ( (n[0].id.length() == 0) && (n[0].kind.length() == 0 ) ) {
776                throw new InvalidName();
777            }
778
779            org.omg.CORBA.Object objRef = null;
780            synchronized (impl) {
781                // Yes: unbind in this context
782                objRef = impl.Unbind(n[0]);
783            }
784
785            if (objRef == null)
786                // It was not bound
787                throw new NotFound(NotFoundReason.missing_node,n);
788            // Done
789            return;
790        } else {
791            // No: unbind in a different context
792
793      // Resolve first  - must be resolveable
794            NamingContext context = resolveFirstAsContext(impl,n);
795
796            // Compute tail
797            NameComponent[] tail = new NameComponent[n.length - 1];
798            System.arraycopy(n,1,tail,0,n.length-1);
799
800      // Propagate unbind to this context
801            context.unbind(tail);
802        }
803    }
804
805    /**
806   * Implements resolving a NameComponent in this context and
807   * narrowing it to CosNaming::NamingContext. It will throw appropriate
808   * exceptions if not found or not narrowable.
809   * @param impl an implementation of NamingContextDataStore
810   * @param n a NameComponents which is the name to be found.
811   * @exception org.omg.CosNaming.NamingContextPackage.NotFound The
812   * first component could not be resolved.
813   * @exception org.omg.CosNaming.NamingContextPackage.CannotProceed Could not proceed
814   * in resolving the first component of the supplied name.
815   * @exception org.omg.CORBA.SystemException One of a fixed set of CORBA system exceptions.
816   * @see resolve
817   */
818    protected static NamingContext resolveFirstAsContext(NamingContextDataStore impl,
819                                                         NameComponent[] n)
820        throws org.omg.CosNaming.NamingContextPackage.NotFound {
821        org.omg.CORBA.Object topRef = null;
822        BindingTypeHolder bth = new BindingTypeHolder();
823        NamingContext context = null;
824
825        synchronized (impl) {
826            // Resolve first  - must be resolveable
827            topRef = impl.Resolve(n[0],bth);
828            if (topRef == null) {
829                // It was not bound
830                throw new NotFound(NotFoundReason.missing_node,n);
831            }
832        }
833
834        // Was it bound as a context?
835        if (bth.value != BindingType.ncontext) {
836            // It was not a context
837            throw new NotFound(NotFoundReason.not_context,n);
838        }
839
840        // Narrow to a naming context
841        try {
842            context = NamingContextHelper.narrow(topRef);
843        } catch (org.omg.CORBA.BAD_PARAM ex) {
844            // It was not a context
845            throw new NotFound(NotFoundReason.not_context,n);
846        }
847
848        // Hmm. must be ok
849        return context;
850    }
851
852
853   /**
854    * This operation creates a stringified name from the array of Name
855    * components.
856    * @param n Name of the object <p>
857    * @exception org.omg.CosNaming.NamingContextExtPackage.InvalidName
858    * Indicates the name does not identify a binding.<p>
859    *
860    */
861    public String to_string(org.omg.CosNaming.NameComponent[] n)
862         throws org.omg.CosNaming.NamingContextPackage.InvalidName
863    {
864        // Name valid?
865        if ( (n == null ) || (n.length == 0) )
866        {
867                throw new InvalidName();
868        }
869        NamingContextDataStore impl = (NamingContextDataStore)this;
870
871        String theStringifiedName = insImpl.convertToString( n );
872
873        if( theStringifiedName == null )
874        {
875                throw new InvalidName();
876        }
877
878        return theStringifiedName;
879    }
880
881
882   /**
883    * This operation  converts a Stringified Name into an  equivalent array
884    * of Name Components.
885    * @param sn Stringified Name of the object <p>
886    * @exception org.omg.CosNaming.NamingContextExtPackage.InvalidName
887    * Indicates the name does not identify a binding.<p>
888    *
889    */
890    public org.omg.CosNaming.NameComponent[] to_name(String sn)
891         throws org.omg.CosNaming.NamingContextPackage.InvalidName
892    {
893        // Name valid?
894        if  ( (sn == null ) || (sn.length() == 0) )
895        {
896                throw new InvalidName();
897        }
898        NamingContextDataStore impl = (NamingContextDataStore)this;
899        org.omg.CosNaming.NameComponent[] theNameComponents =
900                insImpl.convertToNameComponent( sn );
901        if( ( theNameComponents == null ) || (theNameComponents.length == 0 ) )
902        {
903                throw new InvalidName();
904        }
905        for( int i = 0; i < theNameComponents.length; i++ ) {
906            // If there is a name component whose id and kind null or
907            // zero length string, then an invalid name exception needs to be
908            // raised.
909            if ( ( ( theNameComponents[i].id  == null )
910                 ||( theNameComponents[i].id.length() == 0 ) )
911               &&( ( theNameComponents[i].kind == null )
912                 ||( theNameComponents[i].kind.length() == 0 ) ) ) {
913                throw new InvalidName();
914            }
915        }
916        return theNameComponents;
917    }
918
919   /**
920    * This operation creates a URL based "iiopname://" format name
921    * from the Stringified Name of the object.
922    * @param addr internet based address of the host machine where
923    * Name Service is running <p>
924    * @param sn Stringified Name of the object <p>
925    * @exception org.omg.CosNaming.NamingContextExtPackage.InvalidName
926    * Indicates the name does not identify a binding.<p>
927    * @exception org.omg.CosNaming.NamingContextPackage.InvalidAddress
928    * Indicates the internet based address of the host machine is
929    * incorrect <p>
930    *
931    */
932
933    public String to_url(String addr, String sn)
934        throws org.omg.CosNaming.NamingContextExtPackage.InvalidAddress,
935               org.omg.CosNaming.NamingContextPackage.InvalidName
936    {
937        // Name valid?
938        if  ( (sn == null ) || (sn.length() == 0) )
939        {
940            throw new InvalidName();
941        }
942        if( addr == null )
943        {
944            throw new
945                org.omg.CosNaming.NamingContextExtPackage.InvalidAddress();
946        }
947        NamingContextDataStore impl = (NamingContextDataStore)this;
948        String urlBasedAddress = null;
949        urlBasedAddress = insImpl.createURLBasedAddress( addr, sn );
950        // Extra check to see that corba name url created is valid as per
951        // INS spec grammer.
952        try {
953            INSURLHandler.getINSURLHandler( ).parseURL( urlBasedAddress );
954        } catch( BAD_PARAM e ) {
955            throw new
956                org.omg.CosNaming.NamingContextExtPackage.InvalidAddress();
957        }
958        return urlBasedAddress;
959    }
960
961    /**
962     * This operation resolves the Stringified name into the object
963     * reference.
964     * @param sn Stringified Name of the object <p>
965     * @exception org.omg.CosNaming.NamingContextPackage.NotFound
966     * Indicates there is no object reference for the given name. <p>
967     * @exception org.omg.CosNaming.NamingContextPackage.CannotProceed
968     * Indicates that the given compound name is incorrect <p>
969     * @exception org.omg.CosNaming.NamingContextExtPackage.InvalidName
970     * Indicates the name does not identify a binding.<p>
971     * @exception org.omg.CosNaming.NamingContextPackage.AlreadyBound
972     * Indicates the name is already bound.<p>
973     *
974     */
975    public org.omg.CORBA.Object resolve_str(String sn)
976        throws org.omg.CosNaming.NamingContextPackage.NotFound,
977               org.omg.CosNaming.NamingContextPackage.CannotProceed,
978               org.omg.CosNaming.NamingContextPackage.InvalidName
979    {
980        org.omg.CORBA.Object theObject = null;
981        // Name valid?
982        if  ( (sn == null ) || (sn.length() == 0) )
983        {
984                throw new InvalidName();
985        }
986        NamingContextDataStore impl = (NamingContextDataStore)this;
987        org.omg.CosNaming.NameComponent[] theNameComponents =
988                insImpl.convertToNameComponent( sn );
989
990        if( ( theNameComponents == null ) || (theNameComponents.length == 0 ) )
991        {
992                throw new InvalidName();
993        }
994        theObject = resolve( theNameComponents );
995        return theObject;
996    }
997
998
999    transient protected ORB orb;
1000
1001    public static String nameToString(NameComponent[] name)
1002    {
1003        StringBuffer s = new StringBuffer("{");
1004        if (name != null || name.length > 0) {
1005            for (int i=0;i<name.length;i++) {
1006                if (i>0)
1007                    s.append(",");
1008                s.append("[").
1009                    append(name[i].id).
1010                    append(",").
1011                    append(name[i].kind).
1012                    append("]");
1013            }
1014        }
1015        s.append("}");
1016        return s.toString();
1017    }
1018
1019    // Debugging aids.
1020    public static final boolean debug = false;
1021
1022    private static void dprint(String msg) {
1023        NamingUtils.dprint("NamingContextImpl("  +
1024                           Thread.currentThread().getName() + " at " +
1025                           System.currentTimeMillis() +
1026                           " ems): " + msg);
1027    }
1028}
1029