View Javadoc

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.io.Serializable;
11  import java.io.IOException;
12  import java.util.Hashtable;
13  import java.util.Iterator;
14  import java.rmi.MarshalledObject;
15  import javax.naming.*;
16  import javax.naming.Context;
17  
18  /***
19   * Context that hooks up to a remote source.
20   *
21   * @author <a href="mailto:donaldp@apache.org">Peter Donald</a>
22   * @version $Revision: 1.2 $
23   */
24  public class RemoteContext
25      extends AbstractContext
26      implements Serializable
27  {
28      public final static String  NAMESPACE_NAME   = "org.apache.avalon.excalibur.naming.Namespace/NAME";
29      public final static String  NAMESPACE        = "org.apache.avalon.excalibur.naming.Namespace";
30      public final static String  NAMING_PROVIDER  = "org.apache.avalon.excalibur.naming.NamingProvider";
31  
32      protected transient NamingProvider    m_provider;
33      protected transient NameParser        m_nameParser;
34      protected transient Namespace         m_namespace;
35  
36      protected Name              m_baseName;
37  
38      //for deserialisation
39      public RemoteContext()
40      {
41      }
42  
43      public RemoteContext( final Hashtable environment, final Name baseName )
44          throws NamingException
45      {
46          super( environment );
47          m_baseName = baseName;
48      }
49  
50      /***
51       * Helper method to bind
52       */
53      protected void bind( final Name name, Object object, final boolean rebind )
54          throws NamingException
55      {
56          if( isSelf( name ) )
57          {
58              throw new InvalidNameException( "Failed to bind self" );
59          }
60  
61          String className = null;
62  
63          object = getNamespace().getStateToBind( object, name, this, m_environment );
64  
65          if( object instanceof Reference )
66          {
67              className = ((Reference)object).getClassName();
68          }
69          else if( object instanceof Referenceable )
70          {
71              object = ((Referenceable)object).getReference();
72              className = ((Reference)object).getClassName();
73          }
74          else
75          {
76              className = object.getClass().getName();
77  
78              try { object = new MarshalledObject( object ); }
79              catch( final IOException ioe )
80              {
81                  throw new NamingException( "Only Reference, Referenceables and " +
82                                             "Serializable objects can be bound " +
83                                             "to context" );
84              }
85          }
86  
87          try
88          {
89              if( rebind )
90              {
91                  getProvider().rebind( getAbsoluteName( name ), className, object );
92              }
93              else
94              {
95                  getProvider().bind( getAbsoluteName( name ), className, object );
96              }
97          }
98          catch( final Exception e )
99          {
100                 throw handleException( e );
101         }
102     }
103 
104     /***
105      * Release resources associated with context.
106      */
107     public void close()
108     {
109         m_namespace = null;
110         m_environment = null;
111         m_provider = null;
112     }
113 
114     /***
115      * Create a Subcontext.
116      *
117      * @param name the name of subcontext
118      * @return the created context
119      * @exception NamingException if an error occurs (ie context exists, badly formated name etc)
120      */
121     public Context createSubcontext( final Name name )
122         throws NamingException
123     {
124         if( isSelf( name ) )
125         {
126             throw new InvalidNameException( "Failed to create null subcontext" );
127         }
128 
129         Context result = null;
130         try { result = getProvider().createSubcontext( getAbsoluteName( name ) ); }
131         catch( final Exception e )
132         {
133             throw handleException( e );
134         }
135 
136         fillInContext( result );
137 
138         return result;
139     }
140 
141     public void destroySubcontext( final Name name )
142         throws NamingException
143     {
144         if( isSelf( name ) )
145         {
146             throw new InvalidNameException( "Failed to destroy self" );
147         }
148 
149         try { getProvider().destroySubcontext( getAbsoluteName( name ) ); }
150         catch( final Exception e )
151         {
152             throw handleException( e );
153         }
154     }
155 
156     public String getNameInNamespace()
157         throws NamingException
158     {
159         return getAbsoluteName( getNameParser().parse( "" ) ).toString();
160     }
161 
162     /***
163      * Enumerates the names bound in the named context.
164      *
165      * @param name the name of the context
166      * @return the enumeration
167      * @exception NamingException if an error occurs
168      */
169     public NamingEnumeration list( final Name name )
170         throws NamingException
171     {
172         try
173         {
174             final NameClassPair[] result = getProvider().list( getAbsoluteName( name ) );
175             return new ArrayNamingEnumeration( this, m_namespace, result );
176         }
177         catch( final Exception e )
178         {
179             throw handleException( e );
180         }
181     }
182 
183     /***
184      * Enumerates the names bound in the named context, along with the objects bound to them.
185      *
186      * @param name the name of the context
187      * @return the enumeration
188      * @exception NamingException if an error occurs
189      */
190     public NamingEnumeration listBindings( final Name name )
191         throws NamingException
192     {
193         try
194         {
195             final Binding[] result = getProvider().listBindings( getAbsoluteName( name ) );
196 
197             for( int i = 0; i < result.length; i++ )
198             {
199                 final Object object = result[ i ].getObject();
200                 if( object instanceof Context )
201                 {
202                     fillInContext( (Context)object );
203                 }
204             }
205 
206             return new ArrayNamingEnumeration( this, m_namespace, result );
207         }
208         catch( final Exception e )
209         {
210             throw handleException( e );
211         }
212     }
213 
214     /***
215      * Get the object named.
216      *
217      * @param name the name
218      * @return the object
219      * @exception NamingException if an error occurs (ie object name is inavlid or unbound)
220      */
221     public Object lookup( final Name name )
222         throws NamingException
223     {
224         if( isSelf( name ) )
225         {
226             return new RemoteContext( m_environment, m_baseName );
227         }
228 
229         //TODO: actually do a real-lookup
230         Object object = null;
231         try
232         {
233             object = getProvider().lookup( getAbsoluteName( name ) );
234 
235             if( object instanceof MarshalledObject )
236             {
237                 object = ((MarshalledObject)object).get();
238             }
239 
240             object = getNamespace().getObjectInstance( object, name, this, m_environment );
241 
242             if( object instanceof Context )
243             {
244                 fillInContext( (Context)object );
245             }
246         }
247         catch( final Exception e )
248         {
249             throw handleException( e );
250         }
251 
252         return object;
253     }
254 
255     /***
256      * Unbind a object from a name.
257      *
258      * @param name the name
259      * @exception NamingException if an error occurs
260      */
261     public void unbind( final Name name )
262         throws NamingException
263     {
264         if( isSelf( name ) )
265         {
266             throw new InvalidNameException( "Failed to unbind self" );
267         }
268 
269         try { getProvider().unbind( getAbsoluteName( name ) ); }
270         catch( final Exception e )
271         {
272             throw handleException( e );
273         }
274     }
275 
276     protected void fillInContext( final Context object )
277         throws NamingException
278     {
279         final Iterator keys = m_environment.keySet().iterator();
280 
281         while( keys.hasNext() )
282         {
283             final String key = (String)keys.next();
284             final Object value = m_environment.get( key );
285             object.addToEnvironment( key , value );
286         }
287     }
288 
289     protected Namespace getNamespace()
290         throws NamingException
291     {
292         if( null == m_namespace )
293         {
294             final Object object = m_environment.get( RemoteContext.NAMESPACE );
295 
296             if( !(object instanceof Namespace) || null == object )
297             {
298                 throw new ConfigurationException( "Context does not contain Namespace" );
299             }
300             else
301             {
302                 m_namespace = (Namespace)object;
303             }
304         }
305 
306         return m_namespace;
307     }
308 
309     protected NamingProvider getProvider()
310         throws NamingException
311     {
312         if( null == m_provider )
313         {
314             final Object object = m_environment.get( RemoteContext.NAMING_PROVIDER );
315 
316             if( !(object instanceof NamingProvider) || null == object )
317             {
318                 throw new ConfigurationException( "Context does not contain provider" );
319             }
320             else
321             {
322                 m_provider = (NamingProvider)object;
323             }
324         }
325 
326         return m_provider;
327     }
328 
329     protected NameParser getNameParser()
330         throws NamingException
331     {
332         if( null == m_nameParser )
333         {
334             //Make sure provider is valid and returns nameparser
335             try { m_nameParser = getProvider().getNameParser(); }
336             catch( final Exception e )
337             {
338                 throw handleException( e );
339             }
340 
341         }
342         return m_nameParser;
343     }
344 
345     protected Name getAbsoluteName( final Name name )
346         throws NamingException
347     {
348         return composeName( name, m_baseName );
349     }
350 
351     protected NamingException handleException( final Exception e )
352     {
353         if( e instanceof NamingException )
354         {
355             return (NamingException)e;
356         }
357         else
358         {
359             return new CommunicationException( e.toString() );
360         }
361     }
362 }