1 /*
2 * Copyright (C) The Apache Software Foundation. All rights reserved.
3 *
4 * This software is published under the terms of the Apache Software License
5 * version 1.1, a copy of which has been included with this distribution in
6 * the LICENSE file.
7 */
8 package org.apache.avalon.excalibur.naming;
9
10 import java.util.Hashtable;
11 import javax.naming.Context;
12 import javax.naming.InvalidNameException;
13 import javax.naming.NamingEnumeration;
14 import javax.naming.Name;
15 import javax.naming.NameParser;
16 import javax.naming.ContextNotEmptyException;
17 import javax.naming.NameAlreadyBoundException;
18 import javax.naming.NamingException;
19 import javax.naming.NotContextException;
20 import javax.naming.Reference;
21 import javax.naming.Referenceable;
22 import javax.naming.OperationNotSupportedException;
23
24 /***
25 * Abstract local JNDI Context that can be inherited from to
26 * provide a particular type of Context. These contexts are assumed to be
27 * on the same machine.
28 *
29 * @author <a href="mailto:donaldp@apache.org">Peter Donald</a>
30 * @version $Revision: 1.2 $
31 */
32 public abstract class AbstractLocalContext
33 extends AbstractContext
34 {
35 protected Context m_parent;
36 protected Namespace m_namespace;
37
38 public AbstractLocalContext( final Namespace namespace,
39 final Hashtable environment,
40 final Context parent )
41 {
42 super( environment );
43 m_namespace = namespace;
44 m_parent = parent;
45 }
46
47 protected boolean isDestroyableContext( final Object object )
48 throws NamingException
49 {
50 return getClass().isInstance( object );
51 }
52
53 protected abstract Context newContext()
54 throws NamingException;
55
56 protected abstract Context cloneContext()
57 throws NamingException;
58
59 /***
60 * Helper method to bind
61 */
62 protected void bind( final Name name, Object object, final boolean rebind )
63 throws NamingException
64 {
65 if( isSelf( name ) )
66 {
67 throw new InvalidNameException( "Failed to bind self" );
68 }
69
70 if( 1 == name.size() )
71 {
72 boolean alreadyBound = false;
73 try
74 {
75 localLookup( name );
76 alreadyBound = true;
77 }
78 catch( final NamingException ne ) {}
79
80 if( !rebind && alreadyBound )
81 {
82 throw new NameAlreadyBoundException( name.get( 0 ) );
83 }
84 else
85 {
86 //Should this occur here or in the factories ???
87 if( object instanceof Referenceable )
88 {
89 object = ((Referenceable)object).getReference();
90 }
91
92 // Call getStateToBind for using any state factories
93 final Name atom = name.getPrefix( 1 );
94 object = m_namespace.getStateToBind( object, atom, this, m_environment );
95
96 doLocalBind( name, object );
97 }
98 }
99 else
100 {
101 final Context context = lookupSubContext( getPathName( name ) );
102 if( rebind )
103 {
104 context.rebind( getLeafName( name ), object );
105 }
106 else
107 {
108 context.bind( getLeafName( name ), object );
109 }
110 }
111 }
112
113 protected abstract void doLocalBind( Name name, Object object )
114 throws NamingException;
115
116 public void close()
117 {
118 m_parent = null;
119 m_namespace = null;
120 }
121
122 /***
123 * Create a Subcontext.
124 *
125 * @param name the name of subcontext
126 * @return the created context
127 * @exception NamingException if an error occurs (ie context exists, badly formated name etc)
128 */
129 public Context createSubcontext( final Name name )
130 throws NamingException
131 {
132 final Context context = newContext();
133 bind( name, context );
134 return context;
135 }
136
137 public void destroySubcontext( final Name name )
138 throws NamingException
139 {
140 if( isSelf( name ) )
141 {
142 throw new InvalidNameException( "Failed to destroy self" );
143 }
144
145 if( 1 == name.size() )
146 {
147 Object object = null;
148 try
149 {
150 object = localLookup( name );
151 }
152 catch( final NamingException ne )
153 {
154 return;
155 }
156
157 checkUnbindContext( name, object );
158
159 doLocalUnbind( name );
160 }
161 else
162 {
163 final Context context = lookupSubContext( getPathName( name ) );
164
165 Object object = null;
166
167 final Name atom = getLeafName( name );
168 try
169 {
170 object = context.lookup( atom );
171 }
172 catch( final NamingException ne )
173 {
174 return;
175 }
176
177 checkUnbindContext( atom, object );
178
179 context.destroySubcontext( atom );
180 }
181 }
182
183 protected void checkUnbindContext( final Name name, final Object entry )
184 throws NamingException
185 {
186 if( !isDestroyableContext( entry ) )
187 {
188 throw new NotContextException( name.toString() );
189 }
190
191 final Context context = (Context)entry;
192 if( context.list( "" ).hasMoreElements() )
193 {
194 throw new ContextNotEmptyException( name.toString() );
195 }
196 }
197
198 public String getNameInNamespace()
199 throws NamingException
200 {
201 throw new OperationNotSupportedException( "Namespace has no notion of a 'full name'" );
202 }
203
204 protected NameParser getNameParser()
205 throws NamingException
206 {
207 return m_namespace.getNameParser();
208 }
209
210 /***
211 * Enumerates the names bound in the named context.
212 *
213 * @param name the name of the context
214 * @return the enumeration
215 * @exception NamingException if an error occurs
216 */
217 public NamingEnumeration list( final Name name )
218 throws NamingException
219 {
220 if( isSelf( name ) )
221 {
222 return doLocalList();
223 }
224 else
225 {
226 // Perhaps 'name' names a context
227 final Context context = lookupSubContext( name );
228 return context.list( "" );
229 }
230 }
231
232 protected abstract NamingEnumeration doLocalList()
233 throws NamingException;
234
235 protected abstract NamingEnumeration doLocalListBindings()
236 throws NamingException;
237
238 /***
239 * Enumerates the names bound in the named context, along with the objects bound to them.
240 *
241 * @param name the name of the context
242 * @return the enumeration
243 * @exception NamingException if an error occurs
244 */
245 public NamingEnumeration listBindings( final Name name )
246 throws NamingException
247 {
248 if( isSelf( name ) )
249 {
250 return doLocalListBindings();
251 }
252 else
253 {
254 // Perhaps 'name' names a context
255 final Context context = lookupSubContext( name );
256 return context.listBindings( "" );
257 }
258 }
259
260 /***
261 * Get the object named.
262 *
263 * @param name the name
264 * @return the object
265 * @exception NamingException if an error occurs (ie object name is inavlid or unbound)
266 */
267 public Object lookup( final Name name )
268 throws NamingException
269 {
270 //if it refers to base context return a copy of it.
271 if( isSelf( name ) )
272 {
273 return cloneContext();
274 }
275
276 if( 1 == name.size() )
277 {
278 return localLookup( name );
279 }
280 else
281 {
282 final Context context = lookupSubContext( getPathName( name ) );
283 return context.lookup( getLeafName( name ) );
284 }
285 }
286
287 /***
288 * Lookup entry in local context.
289 *
290 * @param name the name in local context (size() == 1)
291 * @return the bound object
292 * @exception NamingException if an error occurs
293 */
294 protected Object localLookup( final Name name )
295 throws NamingException
296 {
297 final Object value = doLocalLookup( name );
298
299 // Call getObjectInstance for using any object factories
300 try
301 {
302 final Name atom = name.getPrefix( 1 );
303 return m_namespace.getObjectInstance( value, atom, this, m_environment );
304 }
305 catch( final Exception e )
306 {
307 final NamingException ne = new NamingException( "getObjectInstance failed" );
308 ne.setRootCause( e );
309 throw ne;
310 }
311 }
312
313 /***
314 * Actually lookup raw entry in local context.
315 * When overidding this it is not neccesary to resolve references etc.
316 *
317 * @param name the name in local context (size() == 1)
318 * @return the bound object
319 * @exception NamingException if an error occurs
320 */
321 protected abstract Object doLocalLookup( Name name )
322 throws NamingException;
323
324 /***
325 * Lookup a sub-context of current context.
326 * Note that name must have 1 or more elements.
327 *
328 * @param name the name of subcontext
329 * @return the sub-Context
330 * @exception NamingException if an error occurs (like named entry is not a Context)
331 */
332 protected Context lookupSubContext( final Name name )
333 throws NamingException
334 {
335 final Name atom = name.getPrefix( 1 );
336 Object object = localLookup( atom );
337
338 if( 1 != name.size() )
339 {
340 if( !(object instanceof Context) )
341 {
342 throw new NotContextException( atom.toString() );
343 }
344
345 object = ((Context)object).lookup( name.getSuffix( 1 ) );
346 }
347
348 if( !(object instanceof Context) )
349 {
350 throw new NotContextException( name.toString() );
351 }
352
353 //((Context)object).close();
354 return (Context)object;
355 }
356
357 /***
358 * Unbind a object from a name.
359 *
360 * @param name the name
361 * @exception NamingException if an error occurs
362 */
363 public void unbind( final Name name )
364 throws NamingException
365 {
366 if( isSelf( name ) )
367 {
368 throw new InvalidNameException( "Cannot unbind self" );
369 }
370 else if( 1 == name.size() )
371 {
372 doLocalUnbind( name );
373 }
374 else
375 {
376 final Context context = lookupSubContext( getPathName ( name ) );
377 context.unbind( getLeafName( name ) );
378 }
379 }
380
381 /***
382 * Actually unbind raw entry in local context.
383 *
384 * @param name the name in local context (size() == 1)
385 * @exception NamingException if an error occurs
386 */
387 protected abstract void doLocalUnbind( Name name )
388 throws NamingException;
389 }
This page was automatically generated by Maven