Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/activemq/jndi/ReadOnlyContext.java


1   /**
2    *
3    * Copyright 2003-2004 The Apache Software Foundation
4    *
5    *  Licensed under the Apache License, Version 2.0 (the "License");
6    *  you may not use this file except in compliance with the License.
7    *  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  
18  package org.activemq.jndi;
19  
20  import javax.naming.*;
21  import javax.naming.spi.NamingManager;
22  import java.io.Serializable;
23  import java.util.Collections;
24  import java.util.HashMap;
25  import java.util.Hashtable;
26  import java.util.Iterator;
27  import java.util.Map;
28  
29  /**
30   * A read-only Context
31   * <p/>
32   * This version assumes it and all its subcontext are read-only and any attempt
33   * to modify (e.g. through bind) will result in an OperationNotSupportedException.
34   * Each Context in the tree builds a cache of the entries in all sub-contexts
35   * to optimise the performance of lookup.
36   * </p>
37   * <p>This implementation is intended to optimise the performance of lookup(String)
38   * to about the level of a HashMap get. It has been observed that the scheme
39   * resolution phase performed by the JVM takes considerably longer, so for
40   * optimum performance lookups should be coded like:</p>
41   * <code>
42   * Context componentContext = (Context)new InitialContext().lookup("java:comp");
43   * String envEntry = (String) componentContext.lookup("env/myEntry");
44   * String envEntry2 = (String) componentContext.lookup("env/myEntry2");
45   * </code>
46   *
47   * @version $Revision: 1.1.1.1 $ $Date: 2005/03/11 21:14:27 $
48   */
49  public class ReadOnlyContext implements Context, Serializable {
50      private static final long serialVersionUID = -5754338187296859149L;
51      protected static final NameParser nameParser = new NameParserImpl();
52  
53      protected final Hashtable environment;        // environment for this context
54      protected final Map bindings;         // bindings at my level
55      protected final Map treeBindings;     // all bindings under me
56  
57      private boolean frozen = false;
58      private String nameInNamespace = "";
59      public static final String SEPARATOR = "/";
60  
61      public ReadOnlyContext() {
62          environment = new Hashtable();
63          bindings = new HashMap();
64          treeBindings = new HashMap();
65      }
66  
67      public ReadOnlyContext(Hashtable env) {
68          if (env == null) {
69              this.environment = new Hashtable();
70          }
71          else {
72              this.environment = new Hashtable(env);
73          }
74          this.bindings = Collections.EMPTY_MAP;
75          this.treeBindings = Collections.EMPTY_MAP;
76      }
77  
78      public ReadOnlyContext(Hashtable environment, Map bindings) {
79          if (environment == null) {
80              this.environment = new Hashtable();
81          }
82          else {
83              this.environment = new Hashtable(environment);
84          }
85          this.bindings = bindings;
86          treeBindings = new HashMap();
87          frozen = true;
88      }
89  
90      public ReadOnlyContext(Hashtable environment, Map bindings, String nameInNamespace) {
91          this(environment, bindings);
92          this.nameInNamespace = nameInNamespace;
93      }
94  
95      protected ReadOnlyContext(ReadOnlyContext clone, Hashtable env) {
96          this.bindings = clone.bindings;
97          this.treeBindings = clone.treeBindings;
98          this.environment = new Hashtable(env);
99      }
100 
101     protected ReadOnlyContext(ReadOnlyContext clone, Hashtable env, String nameInNamespace) {
102         this(clone, env);
103         this.nameInNamespace = nameInNamespace;
104     }
105 
106     public void freeze() {
107         frozen = true;
108     }
109 
110     boolean isFrozen() {
111         return frozen;
112     }
113 
114     /**
115      * internalBind is intended for use only during setup or possibly by suitably synchronized superclasses.
116      * It binds every possible lookup into a map in each context.  To do this, each context
117      * strips off one name segment and if necessary creates a new context for it. Then it asks that context
118      * to bind the remaining name.  It returns a map containing all the bindings from the next context, plus
119      * the context it just created (if it in fact created it). (the names are suitably extended by the segment
120      * originally lopped off).
121      *
122      * @param name
123      * @param value
124      * @return
125      * @throws javax.naming.NamingException
126      */
127     protected Map internalBind(String name, Object value) throws NamingException {
128         assert name != null && name.length() > 0;
129         assert !frozen;
130 
131         Map newBindings = new HashMap();
132         int pos = name.indexOf('/');
133         if (pos == -1) {
134             if (treeBindings.put(name, value) != null) {
135                 throw new NamingException("Something already bound at " + name);
136             }
137             bindings.put(name, value);
138             newBindings.put(name, value);
139         }
140         else {
141             String segment = name.substring(0, pos);
142             assert segment != null;
143             assert !segment.equals("");
144             Object o = treeBindings.get(segment);
145             if (o == null) {
146                 o = newContext();
147                 treeBindings.put(segment, o);
148                 bindings.put(segment, o);
149                 newBindings.put(segment, o);
150             }
151             else if (!(o instanceof ReadOnlyContext)) {
152                 throw new NamingException("Something already bound where a subcontext should go");
153             }
154             ReadOnlyContext readOnlyContext = (ReadOnlyContext) o;
155             String remainder = name.substring(pos + 1);
156             Map subBindings = readOnlyContext.internalBind(remainder, value);
157             for (Iterator iterator = subBindings.entrySet().iterator(); iterator.hasNext();) {
158                 Map.Entry entry = (Map.Entry) iterator.next();
159                 String subName = segment + "/" + (String) entry.getKey();
160                 Object bound = entry.getValue();
161                 treeBindings.put(subName, bound);
162                 newBindings.put(subName, bound);
163             }
164         }
165         return newBindings;
166     }
167 
168     protected ReadOnlyContext newContext() {
169         return new ReadOnlyContext();
170     }
171 
172     public Object addToEnvironment(String propName, Object propVal) throws NamingException {
173         return environment.put(propName, propVal);
174     }
175 
176     public Hashtable getEnvironment() throws NamingException {
177         return (Hashtable) environment.clone();
178     }
179 
180     public Object removeFromEnvironment(String propName) throws NamingException {
181         return environment.remove(propName);
182     }
183 
184     public Object lookup(String name) throws NamingException {
185         if (name.length() == 0) {
186             return this;
187         }
188         Object result = treeBindings.get(name);
189         if (result == null) {
190             result = bindings.get(name);
191         }
192         if (result == null) {
193             int pos = name.indexOf(':');
194             if (pos > 0) {
195                 String scheme = name.substring(0, pos);
196                 Context ctx = NamingManager.getURLContext(scheme, environment);
197                 if (ctx == null) {
198                     throw new NamingException("scheme " + scheme + " not recognized");
199                 }
200                 return ctx.lookup(name);
201             }
202             else {
203                 // Split out the first name of the path
204                 // and look for it in the bindings map.
205                 CompositeName path = new CompositeName(name);
206 
207                 if (path.size() == 0) {
208                     return this;
209                 }
210                 else {
211                     String first = path.get(0);
212                     Object obj = bindings.get(first);
213                     if (obj == null) {
214                         throw new NameNotFoundException(name);
215                     }
216                     else if (obj instanceof Context && path.size() > 1) {
217                         Context subContext = (Context) obj;
218                         obj = subContext.lookup(path.getSuffix(1));
219                     }
220                     return obj;
221                 }
222             }
223         }
224         if (result instanceof LinkRef) {
225             LinkRef ref = (LinkRef) result;
226             result = lookup(ref.getLinkName());
227         }
228         if (result instanceof Reference) {
229             try {
230                 result = NamingManager.getObjectInstance(result, null, null, this.environment);
231             }
232             catch (NamingException e) {
233                 throw e;
234             }
235             catch (Exception e) {
236                 throw (NamingException) new NamingException("could not look up : " + name).initCause(e);
237             }
238         }
239         if (result instanceof ReadOnlyContext) {
240             String prefix = getNameInNamespace();
241             if (prefix.length() > 0) {
242                 prefix = prefix + SEPARATOR;
243             }
244             result = new ReadOnlyContext((ReadOnlyContext) result, environment, prefix + name);
245         }
246         return result;
247     }
248 
249     public Object lookup(Name name) throws NamingException {
250         return lookup(name.toString());
251     }
252 
253     public Object lookupLink(String name) throws NamingException {
254         return lookup(name);
255     }
256 
257     public Name composeName(Name name, Name prefix) throws NamingException {
258         Name result = (Name) prefix.clone();
259         result.addAll(name);
260         return result;
261     }
262 
263     public String composeName(String name, String prefix) throws NamingException {
264         CompositeName result = new CompositeName(prefix);
265         result.addAll(new CompositeName(name));
266         return result.toString();
267     }
268 
269     public NamingEnumeration list(String name) throws NamingException {
270         Object o = lookup(name);
271         if (o == this) {
272             return new ListEnumeration();
273         }
274         else if (o instanceof Context) {
275             return ((Context) o).list("");
276         }
277         else {
278             throw new NotContextException();
279         }
280     }
281 
282     public NamingEnumeration listBindings(String name) throws NamingException {
283         Object o = lookup(name);
284         if (o == this) {
285             return new ListBindingEnumeration();
286         }
287         else if (o instanceof Context) {
288             return ((Context) o).listBindings("");
289         }
290         else {
291             throw new NotContextException();
292         }
293     }
294 
295     public Object lookupLink(Name name) throws NamingException {
296         return lookupLink(name.toString());
297     }
298 
299     public NamingEnumeration list(Name name) throws NamingException {
300         return list(name.toString());
301     }
302 
303     public NamingEnumeration listBindings(Name name) throws NamingException {
304         return listBindings(name.toString());
305     }
306 
307     public void bind(Name name, Object obj) throws NamingException {
308         throw new OperationNotSupportedException();
309     }
310 
311     public void bind(String name, Object obj) throws NamingException {
312         throw new OperationNotSupportedException();
313     }
314 
315     public void close() throws NamingException {
316         // ignore
317     }
318 
319     public Context createSubcontext(Name name) throws NamingException {
320         throw new OperationNotSupportedException();
321     }
322 
323     public Context createSubcontext(String name) throws NamingException {
324         throw new OperationNotSupportedException();
325     }
326 
327     public void destroySubcontext(Name name) throws NamingException {
328         throw new OperationNotSupportedException();
329     }
330 
331     public void destroySubcontext(String name) throws NamingException {
332         throw new OperationNotSupportedException();
333     }
334 
335     public String getNameInNamespace() throws NamingException {
336         return nameInNamespace;
337     }
338 
339     public NameParser getNameParser(Name name) throws NamingException {
340         return nameParser;
341     }
342 
343     public NameParser getNameParser(String name) throws NamingException {
344         return nameParser;
345     }
346 
347     public void rebind(Name name, Object obj) throws NamingException {
348         throw new OperationNotSupportedException();
349     }
350 
351     public void rebind(String name, Object obj) throws NamingException {
352         throw new OperationNotSupportedException();
353     }
354 
355     public void rename(Name oldName, Name newName) throws NamingException {
356         throw new OperationNotSupportedException();
357     }
358 
359     public void rename(String oldName, String newName) throws NamingException {
360         throw new OperationNotSupportedException();
361     }
362 
363     public void unbind(Name name) throws NamingException {
364         throw new OperationNotSupportedException();
365     }
366 
367     public void unbind(String name) throws NamingException {
368         throw new OperationNotSupportedException();
369     }
370 
371     private abstract class LocalNamingEnumeration implements NamingEnumeration {
372         private Iterator i = bindings.entrySet().iterator();
373 
374         public boolean hasMore() throws NamingException {
375             return i.hasNext();
376         }
377 
378         public boolean hasMoreElements() {
379             return i.hasNext();
380         }
381 
382         protected Map.Entry getNext() {
383             return (Map.Entry) i.next();
384         }
385 
386         public void close() throws NamingException {
387         }
388     }
389 
390     private class ListEnumeration extends LocalNamingEnumeration {
391         public Object next() throws NamingException {
392             return nextElement();
393         }
394 
395         public Object nextElement() {
396             Map.Entry entry = getNext();
397             return new NameClassPair((String) entry.getKey(), entry.getValue().getClass().getName());
398         }
399     }
400 
401     private class ListBindingEnumeration extends LocalNamingEnumeration {
402         public Object next() throws NamingException {
403             return nextElement();
404         }
405 
406         public Object nextElement() {
407             Map.Entry entry = getNext();
408             return new Binding((String) entry.getKey(), entry.getValue());
409         }
410     }
411 }