001: /***************************************************************
002: * This file is part of the [fleXive](R) project.
003: *
004: * Copyright (c) 1999-2007
005: * UCS - unique computing solutions gmbh (http://www.ucs.at)
006: * All rights reserved
007: *
008: * The [fleXive](R) project is free software; you can redistribute
009: * it and/or modify it under the terms of the GNU General Public
010: * License as published by the Free Software Foundation;
011: * either version 2 of the License, or (at your option) any
012: * later version.
013: *
014: * The GNU General Public License can be found at
015: * http://www.gnu.org/copyleft/gpl.html.
016: * A copy is found in the textfile GPL.txt and important notices to the
017: * license from the author are found in LICENSE.txt distributed with
018: * these libraries.
019: *
020: * This library is distributed in the hope that it will be useful,
021: * but WITHOUT ANY WARRANTY; without even the implied warranty of
022: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
023: * GNU General Public License for more details.
024: *
025: * For further information about UCS - unique computing solutions gmbh,
026: * please see the company website: http://www.ucs.at
027: *
028: * For further information about [fleXive](R), please see the
029: * project website: http://www.flexive.org
030: *
031: *
032: * This copyright notice MUST APPEAR in all copies of the file!
033: ***************************************************************/package com.flexive.war.webdav;
034:
035: import javax.naming.*;
036: import javax.naming.directory.*;
037: import java.io.Serializable;
038: import java.util.*;
039:
040: /**
041: * Memory impementation ofthe DirContext.
042: */
043: public class FxDirContext extends DirContextStringImpl implements
044: DirContext, Serializable {
045: static final long serialVersionUID = 2547463437468465948L;
046: private static NameParser nameParser = DefaultName.getNameParser();
047: private HashMap<String, Object> bindings = new HashMap<String, Object>();
048: private HashMap<String, Attributes> bindingAttrs = new HashMap<String, Attributes>();
049: private FxDirContext parent;
050: private String contextName;
051: private Hashtable env;
052:
053: /**
054: * Constructor
055: */
056: public FxDirContext() {
057: this .contextName = "";
058: }
059:
060: /**
061: * Constructor.
062: *
063: * @param contextName
064: * @param parent
065: * @param attributes
066: * @throws javax.naming.NamingException
067: */
068: public FxDirContext(String contextName, FxDirContext parent,
069: Attributes attributes) throws NamingException {
070: this (contextName, parent, attributes, null);
071: }
072:
073: /**
074: * Constructor.
075: *
076: * @param contextName
077: * @param parent
078: * @param attributes
079: * @param env
080: * @throws javax.naming.NamingException
081: */
082: public FxDirContext(String contextName, FxDirContext parent,
083: Attributes attributes, Hashtable env)
084: throws NamingException {
085: this .contextName = contextName == null ? "" : contextName;
086: this .parent = parent;
087: bindingAttrs.put("", (Attributes) attributes.clone());
088: if (parent != null)
089: parent.bind(contextName, this );
090: this .env = (Hashtable) env.clone();
091: }
092:
093: /**
094: * Returns the name.
095: *
096: * @return the name
097: */
098: String getName() {
099: return contextName;
100: }
101:
102: /**
103: * Sets the name.
104: *
105: * @param contextName the new name
106: */
107: void setName(String contextName) {
108: this .contextName = contextName;
109: }
110:
111: /**
112: * Returns the full name.
113: *
114: * @return the full name
115: * @throws javax.naming.NamingException
116: */
117: Name getFullName() throws NamingException {
118: CompositeName name = new CompositeName(getName());
119: FxDirContext context = parent;
120: if (context == null)
121: return name;
122: try {
123: while (context.parent != null) {
124: name.add(0, context.getName());
125: context = context.parent;
126: }
127: } catch (NamingException e) {/*ignore*/
128: }
129: return name;
130: }
131:
132: /**
133: * @param name
134: * @param value
135: * @throws NamingException
136: */
137: public void bind(Name name, Object value) throws NamingException {
138: bind(name, value, null);
139: }
140:
141: /**
142: * @param name
143: * @param value
144: * @param attributes
145: * @throws NamingException
146: */
147: public void bind(Name name, Object value, Attributes attributes)
148: throws NamingException {
149: if (name.isEmpty()) {
150: throw new InvalidNameException("Cannot bind empty name");
151: }
152:
153: internalBind(name, value, attributes, true);
154: }
155:
156: /**
157: * @param name
158: * @return
159: * @throws NamingException
160: */
161: public Context createSubcontext(Name name) throws NamingException {
162: return createSubcontext(name, null);
163: }
164:
165: /**
166: * @param name
167: * @param attributes
168: * @return
169: * @throws NamingException
170: */
171: public DirContext createSubcontext(Name name, Attributes attributes)
172: throws NamingException {
173: if (name.isEmpty()) {
174: throw new InvalidNameException(
175: "Cannot createSubcontext with empty name");
176: }
177:
178: DirContext subctx;
179: String atom = name.get(0);
180: if (name.size() == 1) {
181: subctx = new FxDirContext(atom, this , attributes, env);
182: } else {
183: DirContext context = (DirContext) bindings.get(atom);
184: subctx = context.createSubcontext(name.getSuffix(1),
185: attributes);
186: }
187:
188: return subctx;
189: }
190:
191: /**
192: * @param name
193: * @throws NamingException
194: */
195: public void destroySubcontext(Name name) throws NamingException {
196: unbind(name);
197: }
198:
199: /**
200: * @param name
201: * @return
202: * @throws NamingException
203: */
204: public Attributes getAttributes(Name name) throws NamingException {
205: return getAttributes(name, null);
206: }
207:
208: /**
209: * @param name
210: * @param attrIDs
211: * @return
212: * @throws NamingException
213: */
214: public Attributes getAttributes(Name name, String[] attrIDs)
215: throws NamingException {
216: Attributes nameAttributes;
217: String atom = name.get(0);
218: if (name.isEmpty()) {
219: nameAttributes = bindingAttrs.get("");
220: } else if (name.size() == 1) {
221: Object binding = bindings.get(atom);
222: if (binding != null) {
223: if (binding instanceof DirContext) {
224: DirContext dirCtx = (DirContext) binding;
225: try {
226: return dirCtx.getAttributes(name.getSuffix(1),
227: attrIDs);
228: } catch (Exception exc) {
229: return new BasicAttributes();
230: }
231: }
232: }
233: nameAttributes = bindingAttrs.get(atom);
234: } else {
235: DirContext context = (DirContext) bindings.get(atom);
236: nameAttributes = context.getAttributes(name.getSuffix(1),
237: attrIDs);
238: }
239:
240: if (nameAttributes != null && attrIDs != null) {
241: BasicAttributes matches = new BasicAttributes(
242: nameAttributes.isCaseIgnored());
243: for (String attrID : attrIDs) {
244: Attribute attr = nameAttributes.get(attrID);
245: if (attr != null)
246: matches.put(attr);
247: }
248: nameAttributes = matches;
249: }
250: return nameAttributes;
251: }
252:
253: /**
254: * @return
255: * @throws NamingException
256: */
257: public Hashtable<?, ?> getEnvironment() throws NamingException {
258: return (Hashtable<?, ?>) Collections.unmodifiableMap(env);
259: }
260:
261: /**
262: * @return
263: * @throws NamingException
264: */
265: public String getNameInNamespace() throws NamingException {
266: return toString();
267: }
268:
269: /**
270: * @param p1
271: * @return
272: * @throws NamingException
273: */
274: public NameParser getNameParser(Name p1) throws NamingException {
275: return nameParser;
276: }
277:
278: /**
279: * @param p1
280: * @return
281: * @throws NamingException
282: */
283: public NamingEnumeration<NameClassPair> list(Name p1)
284: throws NamingException {
285: NamingEnumeration<Binding> result = listBindings(p1);
286: // Cast -> NameClassPair
287: ArrayList<NameClassPair> tmp = new ArrayList<NameClassPair>(50);
288: while (result.hasMore()) {
289: tmp.add((NameClassPair) result.next());
290: }
291: return new NameBindingIterator(tmp.iterator(), this );
292: }
293:
294: /**
295: * @param name
296: * @return
297: * @throws NamingException
298: */
299: public NamingEnumeration<Binding> listBindings(Name name)
300: throws NamingException {
301: NamingEnumeration<Binding> iter;
302:
303: if (name.isEmpty()) {
304: Iterator keys = bindings.keySet().iterator();
305: ArrayList<DirBinding> tmp = new ArrayList<DirBinding>();
306: while (keys.hasNext()) {
307: String key = (String) keys.next();
308: Object value = bindings.get(key);
309: Attributes attributes = bindingAttrs.get(key);
310: DirBinding tuple = new DirBinding(key, value,
311: attributes);
312: tmp.add(tuple);
313: }
314: iter = new NameBindingIterator(tmp.iterator(), this );
315: } else {
316: String atom = name.get(0);
317: Context context = (Context) bindings.get(atom);
318: iter = context.listBindings(name.getSuffix(1));
319: }
320:
321: return iter;
322: }
323:
324: /**
325: * @param name
326: * @return
327: * @throws NamingException
328: */
329: public Object lookup(Name name) throws NamingException {
330: if (name.isEmpty())
331: return this ;
332:
333: String atom = name.get(0);
334: Object binding = bindings.get(atom);
335: if (name.size() == 1) { /* Need to check that binding is null and atom is not a key
336: since a null value could have been bound.
337: */
338: if (binding == null && !bindings.containsKey(atom)) {
339: NameNotFoundException e = new NameNotFoundException(
340: "Failed to find: " + atom);
341: e.setRemainingName(name);
342: e.setResolvedObj(this );
343: throw e;
344: }
345: } else if ((binding instanceof Context)) {
346: Context context = (Context) binding;
347: binding = context.lookup(name.getSuffix(1));
348: } else {
349: NotContextException e = new NotContextException(
350: atom
351: + " does not name a directory context that supports attributes");
352: e.setRemainingName(name);
353: e.setResolvedObj(binding);
354: throw e;
355: }
356: return binding;
357: }
358:
359: /**
360: * @param name
361: * @param value
362: * @throws NamingException
363: */
364: public void rebind(Name name, Object value) throws NamingException {
365: rebind(name, value, null);
366: }
367:
368: /**
369: * @param name
370: * @param value
371: * @param attributes
372: * @throws NamingException
373: */
374: public void rebind(Name name, Object value, Attributes attributes)
375: throws NamingException {
376: if (name.isEmpty()) {
377: throw new InvalidNameException("Cannot bind empty name");
378: }
379:
380: internalBind(name, value, attributes, false);
381: }
382:
383: /**
384: * @param name
385: * @throws NamingException
386: */
387: public void unbind(Name name) throws NamingException {
388: if (name.isEmpty()) {
389: throw new InvalidNameException("Cannot unbind empty name");
390: }
391:
392: String atom = name.get(0);
393: Object binding = bindings.get(atom);
394: if (name.size() == 1) { /* Need to check that binding is null and atom is not a key
395: since a null value could have been bound.
396: */
397: if (binding == null && !bindings.containsKey(atom)) {
398: NameNotFoundException e = new NameNotFoundException(
399: "Failed to find: " + atom);
400: e.setRemainingName(name);
401: e.setResolvedObj(this );
402: throw e;
403: }
404: bindings.remove(atom);
405: bindingAttrs.remove(atom);
406: } else if ((binding instanceof Context)) {
407: Context context = (Context) binding;
408: context.unbind(name.getSuffix(1));
409: } else {
410: NotContextException e = new NotContextException(
411: atom
412: + " does not name a directory context that supports attributes");
413: e.setRemainingName(name);
414: e.setResolvedObj(binding);
415: throw e;
416: }
417: }
418:
419: /**
420: * @param name
421: * @param value
422: * @param attributes
423: * @param isBind
424: * @throws NamingException
425: */
426: private void internalBind(Name name, Object value,
427: Attributes attributes, boolean isBind)
428: throws NamingException {
429: String atom = name.get(0);
430: Object binding = bindings.get(atom);
431:
432: if (name.size() == 1) {
433: if (binding != null && !isBind) {
434: throw new NameAlreadyBoundException(
435: "Use rebind to override");
436: }
437:
438: // Add object to internal data structure
439: bindings.put(atom, value);
440:
441: // Add attributes
442: if (attributes != null) {
443: bindingAttrs.put(atom, attributes);
444: }
445: } else {
446: // Intermediate name: Consume name in this context and continue
447: if (!(binding instanceof Context)) {
448: NotContextException e = new NotContextException(atom
449: + " does not name a context");
450: e.setRemainingName(name);
451: e.setResolvedObj(binding);
452: throw e;
453: }
454:
455: if (attributes == null) {
456: Context context = (Context) binding;
457: if (isBind)
458: context.bind(name.getSuffix(1), value);
459: else
460: context.rebind(name.getSuffix(1), value);
461: } else if (!(binding instanceof DirContext)) {
462: NotContextException e = new NotContextException(
463: atom
464: + " does not name a directory context that supports attributes");
465: e.setRemainingName(name);
466: e.setResolvedObj(binding);
467: throw e;
468: } else {
469: DirContext context = (DirContext) binding;
470: if (isBind)
471: context.bind(name.getSuffix(1), value, attributes);
472: else
473: context
474: .rebind(name.getSuffix(1), value,
475: attributes);
476: }
477: }
478: }
479:
480: /**
481: * Returns a String representation of the object.
482: *
483: * @return a String representation of the object.
484: */
485: public String toString() {
486: try {
487: return getFullName().toString();
488: } catch (NamingException e) { /*ignore*/
489: }
490: return "";
491: }
492:
493: // ################## NI SECTION ###################################################
494:
495: public Object lookupLink(Name p1) throws NamingException {
496: throw new OperationNotSupportedException("Not implemented yet");
497: }
498:
499: public void modifyAttributes(Name p1, ModificationItem[] p2)
500: throws NamingException {
501: throw new OperationNotSupportedException("Not implemented yet");
502: }
503:
504: public void modifyAttributes(Name p1, int p2, Attributes p3)
505: throws NamingException {
506: throw new OperationNotSupportedException("Not implemented yet");
507: }
508:
509: public void rename(Name p1, Name p2) throws NamingException {
510: throw new OperationNotSupportedException("Not implemented yet");
511: }
512:
513: public NamingEnumeration<SearchResult> search(Name p1, Attributes p2)
514: throws NamingException {
515: throw new OperationNotSupportedException("Not implemented yet");
516: }
517:
518: public NamingEnumeration<SearchResult> search(Name p1, String p2,
519: SearchControls p3) throws NamingException {
520: throw new OperationNotSupportedException("Not implemented yet");
521: }
522:
523: public NamingEnumeration<SearchResult> search(Name p1,
524: Attributes p2, String[] p3) throws NamingException {
525: throw new OperationNotSupportedException("Not implemented yet");
526: }
527:
528: public NamingEnumeration<SearchResult> search(Name p1, String p2,
529: Object[] p3, SearchControls p4) throws NamingException {
530: throw new OperationNotSupportedException("Not implemented yet");
531: }
532:
533: public DirContext getSchema(Name p1) throws NamingException {
534: throw new OperationNotSupportedException("Not implemented yet");
535: }
536:
537: public DirContext getSchemaClassDefinition(Name p1)
538: throws NamingException {
539: throw new OperationNotSupportedException("Not implemented yet");
540: }
541:
542: public void close() throws NamingException {
543: // Nothing to do
544: }
545:
546: public Name composeName(Name p1, Name p2) throws NamingException {
547: return null;
548: }
549:
550: public Object addToEnvironment(String p1, Object p2)
551: throws NamingException {
552: return null;
553: }
554:
555: public Object removeFromEnvironment(String p1)
556: throws NamingException {
557: return null;
558: }
559:
560: }
|