001: /*
002: * $Id: DefaultSpringJndiContext.java 10256 2008-01-08 15:20:25Z dfeist $
003: * --------------------------------------------------------------------------------------
004: * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.com
005: *
006: * The software in this package is published under the terms of the CPAL v1.0
007: * license, a copy of which has been included with this distribution in the
008: * LICENSE.txt file.
009: */
010: package org.mule.config.spring.jndi;
011:
012: import java.io.Serializable;
013: import java.util.HashMap;
014: import java.util.Hashtable;
015: import java.util.Iterator;
016: import java.util.Map;
017:
018: import javax.naming.Binding;
019: import javax.naming.CompositeName;
020: import javax.naming.Context;
021: import javax.naming.LinkRef;
022: import javax.naming.Name;
023: import javax.naming.NameClassPair;
024: import javax.naming.NameNotFoundException;
025: import javax.naming.NameParser;
026: import javax.naming.NamingEnumeration;
027: import javax.naming.NamingException;
028: import javax.naming.NotContextException;
029: import javax.naming.OperationNotSupportedException;
030: import javax.naming.Reference;
031: import javax.naming.spi.NamingManager;
032:
033: /**
034: * TODO
035: */
036: /**
037: * A simple spring based JNDI context which is mutable
038: *
039: * Borrowed from the XBean (xbean.codehaus.org) project. Thanks guys!
040: */
041: public class DefaultSpringJndiContext implements Context, Serializable {
042:
043: private static final long serialVersionUID = -5754338187296859149L;
044: protected static final NameParser nameParser = new DefaultNameParser();
045:
046: private boolean freeze = false;
047:
048: protected final Hashtable environment; // environment for this context
049: protected final Map bindings; // bindings at my level
050: protected final Map treeBindings; // all bindings under me
051:
052: private boolean frozen = false;
053: private String nameInNamespace = "";
054: public static final String SEPARATOR = "/";
055:
056: public DefaultSpringJndiContext() {
057: environment = new Hashtable();
058: bindings = new HashMap();
059: treeBindings = new HashMap();
060: }
061:
062: public DefaultSpringJndiContext(Hashtable env) {
063: if (env == null) {
064: this .environment = new Hashtable();
065: } else {
066: this .environment = new Hashtable(env);
067: }
068: this .bindings = new HashMap();
069: this .treeBindings = new HashMap();
070: }
071:
072: public DefaultSpringJndiContext(Hashtable environment, Map bindings) {
073: if (environment == null) {
074: this .environment = new Hashtable();
075: } else {
076: this .environment = new Hashtable(environment);
077: }
078: this .bindings = bindings;
079: treeBindings = new HashMap();
080: frozen = true;
081: }
082:
083: public DefaultSpringJndiContext(Hashtable environment,
084: Map bindings, String nameInNamespace) {
085: this (environment, bindings);
086: this .nameInNamespace = nameInNamespace;
087: }
088:
089: protected DefaultSpringJndiContext(DefaultSpringJndiContext clone,
090: Hashtable env) {
091: this .bindings = clone.bindings;
092: this .treeBindings = clone.treeBindings;
093: this .environment = new Hashtable(env);
094: }
095:
096: protected DefaultSpringJndiContext(DefaultSpringJndiContext clone,
097: Hashtable env, String nameInNamespace) {
098: this (clone, env);
099: this .nameInNamespace = nameInNamespace;
100: }
101:
102: public Object addToEnvironment(String propName, Object propVal)
103: throws NamingException {
104: return environment.put(propName, propVal);
105: }
106:
107: public Hashtable getEnvironment() throws NamingException {
108: return (Hashtable) environment.clone();
109: }
110:
111: public Object removeFromEnvironment(String propName)
112: throws NamingException {
113: return environment.remove(propName);
114: }
115:
116: public Object lookup(String name) throws NamingException {
117: if (name.length() == 0) {
118: return this ;
119: }
120: Object result = treeBindings.get(name);
121: if (result == null) {
122: result = bindings.get(name);
123: }
124: if (result == null) {
125: int pos = name.indexOf(':');
126: if (pos > 0) {
127: String scheme = name.substring(0, pos);
128: Context ctx = NamingManager.getURLContext(scheme,
129: environment);
130: if (ctx == null) {
131: throw new NamingException("scheme " + scheme
132: + " not recognized");
133: }
134: return ctx.lookup(name);
135: } else {
136: // Split out the first name of the path
137: // and look for it in the bindings map.
138: CompositeName path = new CompositeName(name);
139:
140: if (path.size() == 0) {
141: return this ;
142: } else {
143: String first = path.get(0);
144: Object obj = bindings.get(first);
145: if (obj == null) {
146: throw new NameNotFoundException(name);
147: } else if (obj instanceof Context
148: && path.size() > 1) {
149: Context subContext = (Context) obj;
150: obj = subContext.lookup(path.getSuffix(1));
151: }
152: return obj;
153: }
154: }
155: }
156: if (result instanceof LinkRef) {
157: LinkRef ref = (LinkRef) result;
158: result = lookup(ref.getLinkName());
159: }
160: if (result instanceof Reference) {
161: try {
162: result = NamingManager.getObjectInstance(result, null,
163: null, this .environment);
164: } catch (NamingException e) {
165: throw e;
166: } catch (Exception e) {
167: throw (NamingException) new NamingException(
168: "could not look up : " + name).initCause(e);
169: }
170: }
171: if (result instanceof DefaultSpringJndiContext) {
172: String prefix = getNameInNamespace();
173: if (prefix.length() > 0) {
174: prefix = prefix + SEPARATOR;
175: }
176: result = new DefaultSpringJndiContext(
177: (DefaultSpringJndiContext) result, environment,
178: prefix + name);
179: }
180: return result;
181: }
182:
183: public Object lookup(Name name) throws NamingException {
184: return lookup(name.toString());
185: }
186:
187: public Object lookupLink(String name) throws NamingException {
188: return lookup(name);
189: }
190:
191: public Name composeName(Name name, Name prefix)
192: throws NamingException {
193: Name result = (Name) prefix.clone();
194: result.addAll(name);
195: return result;
196: }
197:
198: public String composeName(String name, String prefix)
199: throws NamingException {
200: CompositeName result = new CompositeName(prefix);
201: result.addAll(new CompositeName(name));
202: return result.toString();
203: }
204:
205: public NamingEnumeration list(String name) throws NamingException {
206: Object o = lookup(name);
207: if (o == this ) {
208: return new DefaultSpringJndiContext.ListEnumeration();
209: } else if (o instanceof Context) {
210: return ((Context) o).list("");
211: } else {
212: throw new NotContextException();
213: }
214: }
215:
216: public NamingEnumeration listBindings(String name)
217: throws NamingException {
218: Object o = lookup(name);
219: if (o == this ) {
220: return new DefaultSpringJndiContext.ListBindingEnumeration();
221: } else if (o instanceof Context) {
222: return ((Context) o).listBindings("");
223: } else {
224: throw new NotContextException();
225: }
226: }
227:
228: public Object lookupLink(Name name) throws NamingException {
229: return lookupLink(name.toString());
230: }
231:
232: public NamingEnumeration list(Name name) throws NamingException {
233: return list(name.toString());
234: }
235:
236: public NamingEnumeration listBindings(Name name)
237: throws NamingException {
238: return listBindings(name.toString());
239: }
240:
241: public void bind(Name name, Object value) throws NamingException {
242: bind(name.toString(), value);
243: }
244:
245: public void bind(String name, Object value) throws NamingException {
246: checkFrozen();
247: internalBind(name, value);
248: }
249:
250: public void close() throws NamingException {
251: // ignore
252: }
253:
254: public Context createSubcontext(Name name) throws NamingException {
255: throw new OperationNotSupportedException();
256: }
257:
258: public Context createSubcontext(String name) throws NamingException {
259: throw new OperationNotSupportedException();
260: }
261:
262: public void destroySubcontext(Name name) throws NamingException {
263: throw new OperationNotSupportedException();
264: }
265:
266: public void destroySubcontext(String name) throws NamingException {
267: throw new OperationNotSupportedException();
268: }
269:
270: public String getNameInNamespace() throws NamingException {
271: return nameInNamespace;
272: }
273:
274: public NameParser getNameParser(Name name) throws NamingException {
275: return nameParser;
276: }
277:
278: public NameParser getNameParser(String name) throws NamingException {
279: return nameParser;
280: }
281:
282: public void rebind(Name name, Object value) throws NamingException {
283: rebind(name.toString(), value);
284: }
285:
286: public void rebind(String name, Object value)
287: throws NamingException {
288: checkFrozen();
289: internalBind(name, value, true);
290: }
291:
292: public void rename(Name oldName, Name newName)
293: throws NamingException {
294: checkFrozen();
295: Object value = lookup(oldName);
296: unbind(oldName);
297: bind(newName, value);
298: }
299:
300: public void rename(String oldName, String newName)
301: throws NamingException {
302: Object value = lookup(oldName);
303: unbind(oldName);
304: bind(newName, value);
305: }
306:
307: public void unbind(Name name) throws NamingException {
308: unbind(name.toString());
309: }
310:
311: public void unbind(String name) throws NamingException {
312: checkFrozen();
313: internalBind(name, null, true);
314: }
315:
316: private abstract class LocalNamingEnumeration implements
317: NamingEnumeration {
318: private Iterator i = bindings.entrySet().iterator();
319:
320: public boolean hasMore() throws NamingException {
321: return i.hasNext();
322: }
323:
324: public boolean hasMoreElements() {
325: return i.hasNext();
326: }
327:
328: protected Map.Entry getNext() {
329: return (Map.Entry) i.next();
330: }
331:
332: public void close() throws NamingException {
333: }
334: }
335:
336: private class ListEnumeration extends
337: DefaultSpringJndiContext.LocalNamingEnumeration {
338: public Object next() throws NamingException {
339: return nextElement();
340: }
341:
342: public Object nextElement() {
343: Map.Entry entry = getNext();
344: return new NameClassPair((String) entry.getKey(), entry
345: .getValue().getClass().getName());
346: }
347: }
348:
349: private class ListBindingEnumeration extends
350: DefaultSpringJndiContext.LocalNamingEnumeration {
351: public Object next() throws NamingException {
352: return nextElement();
353: }
354:
355: public Object nextElement() {
356: Map.Entry entry = getNext();
357: return new Binding((String) entry.getKey(), entry
358: .getValue());
359: }
360: }
361:
362: public Map getEntries() {
363: return new HashMap(bindings);
364: }
365:
366: public void setEntries(Map entries) throws NamingException {
367: if (entries != null) {
368: for (Iterator iter = entries.entrySet().iterator(); iter
369: .hasNext();) {
370: Map.Entry entry = (Map.Entry) iter.next();
371: String name = (String) entry.getKey();
372: Object value = entry.getValue();
373: internalBind(name, value);
374: }
375: }
376: }
377:
378: public boolean isFreeze() {
379: return freeze;
380: }
381:
382: public void setFreeze(boolean freeze) {
383: this .freeze = freeze;
384: }
385:
386: /**
387: * internalBind is intended for use only during setup or possibly by suitably synchronized superclasses.
388: * It binds every possible lookup into a map in each context. To do this, each context
389: * strips off one name segment and if necessary creates a new context for it. Then it asks that context
390: * to bind the remaining name. It returns a map containing all the bindings from the next context, plus
391: * the context it just created (if it in fact created it). (the names are suitably extended by the segment
392: * originally lopped off).
393: *
394: * @param name
395: * @param value
396: * @return
397: * @throws javax.naming.NamingException
398: */
399: protected Map internalBind(String name, Object value)
400: throws NamingException {
401: return internalBind(name, value, false);
402:
403: }
404:
405: protected Map internalBind(String name, Object value,
406: boolean allowRebind) throws NamingException {
407:
408: if (name == null || name.length() == 0) {
409: throw new NamingException("Invalid Name " + name);
410: }
411: if (frozen) {
412: throw new NamingException("Read only");
413: }
414:
415: Map newBindings = new HashMap();
416: int pos = name.indexOf('/');
417: if (pos == -1) {
418: Object oldValue = treeBindings.put(name, value);
419: if (!allowRebind && oldValue != null) {
420: throw new NamingException("Something already bound at "
421: + name);
422: }
423: bindings.put(name, value);
424: newBindings.put(name, value);
425: } else {
426: String segment = name.substring(0, pos);
427:
428: if (segment == null || segment.length() == 0) {
429: throw new NamingException("Invalid segment " + segment);
430: }
431: Object o = treeBindings.get(segment);
432: if (o == null) {
433: o = newContext();
434: treeBindings.put(segment, o);
435: bindings.put(segment, o);
436: newBindings.put(segment, o);
437: } else if (!(o instanceof DefaultSpringJndiContext)) {
438: throw new NamingException(
439: "Something already bound where a subcontext should go");
440: }
441: DefaultSpringJndiContext defaultContext = (DefaultSpringJndiContext) o;
442: String remainder = name.substring(pos + 1);
443: Map subBindings = defaultContext.internalBind(remainder,
444: value, allowRebind);
445: for (Iterator iterator = subBindings.entrySet().iterator(); iterator
446: .hasNext();) {
447: Map.Entry entry = (Map.Entry) iterator.next();
448: String subName = segment + "/"
449: + (String) entry.getKey();
450: Object bound = entry.getValue();
451: treeBindings.put(subName, bound);
452: newBindings.put(subName, bound);
453: }
454: }
455: return newBindings;
456: }
457:
458: protected void checkFrozen() throws OperationNotSupportedException {
459: if (isFreeze()) {
460: throw new OperationNotSupportedException(
461: "JNDI context is frozen!");
462: }
463: }
464:
465: protected DefaultSpringJndiContext newContext() {
466: return new DefaultSpringJndiContext();
467: }
468:
469: }
|