001package org.biojava.naming;
002
003import java.util.Enumeration;
004import java.util.Hashtable;
005import java.util.NoSuchElementException;
006
007import javax.naming.Binding;
008import javax.naming.CompositeName;
009import javax.naming.Context;
010import javax.naming.InvalidNameException;
011import javax.naming.Name;
012import javax.naming.NameClassPair;
013import javax.naming.NameNotFoundException;
014import javax.naming.NameParser;
015import javax.naming.NamingEnumeration;
016import javax.naming.NamingException;
017import javax.naming.NotContextException;
018import javax.naming.OperationNotSupportedException;
019import javax.naming.directory.Attributes;
020import javax.naming.directory.BasicAttributes;
021import javax.naming.directory.DirContext;
022import javax.naming.directory.ModificationItem;
023import javax.naming.directory.SearchControls;
024
025/**
026 *
027 *
028 * @author Matthew Pocock
029 */
030public class ObdaContext
031        implements DirContext
032{
033  private ObdaContext parent;
034  private String myAtomicName;
035  private Hashtable bindings;
036  private Hashtable env;
037  private BasicAttributes attrs;
038
039  protected Name getMyComponents(Name name) throws NamingException
040  {
041    if(name instanceof CompositeName) {
042      if(name.size() > 1) {
043        throw new InvalidNameException(
044                name.toString() +
045                " has more components than namespace can handle");
046      }
047
048      // Turn component that belongs to you into a compound name
049      return ObdaUriParser.getInstance().parse(name.get(0));
050    } else {
051      // Already parsed
052      return name;
053    }
054  }
055
056  ObdaContext(ObdaContext parent,
057              String myAtomicName,
058              Hashtable bindings,
059              Hashtable env,
060              BasicAttributes attrs)
061  {
062    this.parent = parent;
063    this.myAtomicName = myAtomicName;
064    this.bindings = new Hashtable(bindings);
065    this.env = new Hashtable(env);
066    this.attrs = (BasicAttributes) attrs.clone();
067  }
068
069  Hashtable getBindings()
070  {
071    return bindings;
072  }
073
074  BasicAttributes getAttrs()
075  {
076    return attrs;
077  }
078
079  public String getNameInNamespace() throws NamingException
080  {
081    ObdaContext ancestor = parent;
082
083    // No ancestor; at root of namespace
084    if(ancestor == null) {
085      return "";
086    }
087
088    Name name = ObdaUriParser.getInstance().parse("");
089    name.add(myAtomicName);
090
091    // Get the parent's names
092    while(ancestor != null && ancestor.myAtomicName != null) {
093      name.add(0, ancestor.myAtomicName);
094      ancestor = ancestor.parent;
095    }
096
097    return name.toString();
098  }
099
100  public Name composeName(Name name, Name prefix) throws NamingException
101  {
102    Name result;
103
104    // Both are compound names; compose using compound name rules
105    if(!(name instanceof CompositeName) &&
106            !(prefix instanceof CompositeName)) {
107      result = (Name) (prefix.clone());
108      result.addAll(name);
109      return new CompositeName().add(result.toString());
110    }
111
112    // Simplistic implementation; do not support federation
113    throw new OperationNotSupportedException(
114            "Do not support composing composite names");
115  }
116
117  public Object lookup(Name name) throws NamingException
118  {
119    System.err.println("lookup: '" + name + "' for " + bindings);
120    if(name.isEmpty()) {
121      // Ask to look up this context itself; create and return
122      // a new instance that has its own independent environment.
123      System.err.println("Empty - return copy");
124      return new ObdaContext(parent, myAtomicName, bindings, env, attrs);
125    }
126
127    // Extract the components that belong to this namespace
128    Name nm = getMyComponents(name);
129    System.err.println("My component is " + nm);
130
131    // Find the object in the internal hash table
132    String start = nm.get(0);
133    Object answer = bindings.get(start);
134    if(answer == null) {
135      throw new NameNotFoundException(name + " not found");
136    }
137
138    if(nm.size() == 1) {
139      return answer;
140    } else {
141      return ((Context) answer).lookup(nm.getSuffix(1));
142    }
143  }
144
145  public NamingEnumeration list(Name name) throws NamingException
146  {
147    if(name.isEmpty()) {
148      // Generate enumeration of context's contents
149      return new ListOfNames(bindings.keys());
150    }
151
152    // Perhaps "name" names a context
153    Object target = lookup(name);
154    if(target instanceof Context) {
155      try {
156        return ((Context) target).list("");
157      } finally {
158        ((Context) target).close();
159      }
160    }
161    throw new NotContextException(name + " cannot be listed");
162  }
163
164  public NamingEnumeration listBindings(Name name) throws NamingException
165  {
166    if(name.isEmpty()) {
167      // Generate enumeration of context's contents
168      return new ListOfBindings(bindings.keys());
169    }
170
171    // Perhaps "name" names a context
172    Object target = lookup(name);
173    if(target instanceof Context) {
174      try {
175        return ((Context) target).list("");
176      } finally {
177        ((Context) target).close();
178      }
179    }
180    throw new NotContextException(name + " cannot be listed");
181  }
182
183  public void bind(Name name, Object obj) throws NamingException
184  {
185    throw new OperationNotSupportedException();
186  }
187
188  public void rebind(Name name, Object obj) throws NamingException
189  {
190    throw new OperationNotSupportedException();
191  }
192
193  public void unbind(Name name) throws NamingException
194  {
195    throw new OperationNotSupportedException();
196  }
197
198  public void rename(Name oldName, Name newName) throws NamingException
199  {
200    throw new OperationNotSupportedException();
201  }
202
203  public Context createSubcontext(Name name) throws NamingException
204  {
205    throw new OperationNotSupportedException();
206  }
207
208  public void destroySubcontext(Name name) throws NamingException
209  {
210    throw new OperationNotSupportedException();
211  }
212
213  public NameParser getNameParser(Name name) throws NamingException
214  {
215    // Do lookup to verify that the name exists
216    Object obj = lookup(name);
217    if(obj instanceof Context) {
218      ((Context) obj).close();
219    }
220    return ObdaUriParser.getInstance();
221  }
222
223  public String composeName(String name, String prefix)
224          throws NamingException
225  {
226    throw new OperationNotSupportedException();
227  }
228
229  public Object addToEnvironment(String propName, Object propVal)
230          throws NamingException
231  {
232    return env.put(propName, propVal);
233  }
234
235  public Object removeFromEnvironment(String propName)
236          throws NamingException
237  {
238    return env.remove(propName);
239  }
240
241  public Hashtable getEnvironment() throws NamingException
242  {
243    return new Hashtable(env);
244  }
245
246  public void close() throws NamingException
247  {
248    // nothing to do
249  }
250
251
252
253  public NamingEnumeration list(String name) throws NamingException
254  {
255    return list(new CompositeName(name));
256  }
257
258  public NamingEnumeration listBindings(String name) throws NamingException
259  {
260    return listBindings(new CompositeName(name));
261  }
262
263  public Object lookup(String name) throws NamingException
264  {
265    return lookup(new CompositeName(name));
266  }
267
268  public Object lookupLink(Name name) throws NamingException
269  {
270    throw new OperationNotSupportedException();
271  }
272
273  public Attributes getAttributes(Name name) throws NamingException
274  {
275    return getAttributes(name, null);  // Same as attrIds == null
276  }
277
278  public Attributes getAttributes(Name name, String[] attrIds)
279          throws NamingException
280  {
281    if(name.isEmpty()) {
282      // Ask for the attributes of this context
283      return (Attributes) attrs.clone();
284    }
285
286    // Extract the components that belong to this namespace
287    Name nm = getMyComponents(name);
288    String atom = nm.get(0);
289    Object inter = bindings.get(atom);
290
291    if(nm.size() == 1) {
292      // Atomic name; find object in the internal data structure
293      if(inter == null) {
294        throw new NameNotFoundException(name + " not found");
295      }
296
297      if(inter instanceof DirContext) {
298        return ((DirContext) inter).getAttributes("", attrIds);
299      } else {
300        // Fetch the object's attributes from this context
301        return (Attributes) attrs.clone();
302      }
303    } else {
304      // Intermediate name; consume the name in this context
305      // and then continue
306      if(!(inter instanceof DirContext)) {
307        throw new NotContextException(atom + " does not name a dircontext");
308      }
309      return ((DirContext) inter).getAttributes(nm.getSuffix(1), attrIds);
310    }
311  }
312
313  public void modifyAttributes(Name name, int mod_op, Attributes attrs)
314          throws NamingException
315  {
316    throw new OperationNotSupportedException();
317  }
318
319  public void modifyAttributes(Name name, ModificationItem[] mods)
320          throws NamingException
321  {
322    throw new OperationNotSupportedException();
323  }
324
325  public void bind(Name name, Object obj, Attributes attrs)
326          throws NamingException
327  {
328    throw new OperationNotSupportedException();
329  }
330
331  public void rebind(Name name, Object obj, Attributes attrs)
332          throws NamingException
333  {
334    throw new OperationNotSupportedException();
335  }
336
337  public DirContext createSubcontext(Name name, Attributes attrs)
338          throws NamingException
339  {
340    throw new OperationNotSupportedException();
341  }
342
343  public DirContext getSchema(Name name) throws NamingException
344  {
345    throw new OperationNotSupportedException();
346  }
347
348  public DirContext getSchemaClassDefinition(Name name)
349          throws NamingException
350  {
351    throw new OperationNotSupportedException();
352  }
353
354  public NamingEnumeration search(Name name, Attributes matchingAttrs)
355          throws NamingException
356  {
357    throw new OperationNotSupportedException();
358  }
359
360  public NamingEnumeration search(Name name,
361                                  String filterExpr,
362                                  Object[] filterArgs,
363                                  SearchControls cons)
364          throws NamingException
365  {
366    throw new OperationNotSupportedException();
367  }
368
369  public NamingEnumeration search(Name name,
370                                  Attributes matchingAttributes,
371                                  String[] attributesToReturn)
372          throws NamingException
373  {
374    throw new OperationNotSupportedException();
375  }
376
377  public NamingEnumeration search(Name name,
378                                  String filter,
379                                  SearchControls cons)
380          throws NamingException
381  {
382    throw new OperationNotSupportedException();
383  }
384
385  public void bind(String name, Object obj) throws NamingException
386  {
387    bind(new CompositeName(name), obj);
388  }
389
390  public void rebind(String name, Object obj) throws NamingException
391  {
392    rebind(new CompositeName(name), obj);
393  }
394
395  public void unbind(String name) throws NamingException
396  {
397    unbind(new CompositeName(name));
398  }
399
400  public void rename(String oldName, String newName) throws NamingException
401  {
402    rename(new CompositeName(oldName), new CompositeName(newName));
403  }
404
405  public Context createSubcontext(String name) throws NamingException
406  {
407    return createSubcontext(new CompositeName(name));
408  }
409
410  public void destroySubcontext(String name) throws NamingException
411  {
412    destroySubcontext(new CompositeName(name));
413  }
414
415  public NameParser getNameParser(String name) throws NamingException
416  {
417    return getNameParser(new CompositeName(name));
418  }
419
420  public Object lookupLink(String name) throws NamingException
421  {
422    return lookupLink(new CompositeName(name));
423  }
424
425  public Attributes getAttributes(String name) throws NamingException
426  {
427    return getAttributes(new CompositeName(name));
428  }
429
430  public Attributes getAttributes(String name, String[] attrIds)
431          throws NamingException
432  {
433    return getAttributes(new CompositeName(name), attrIds);
434  }
435
436  public void modifyAttributes(String name, int mod_op, Attributes attrs)
437          throws NamingException
438  {
439    modifyAttributes(new CompositeName(name), mod_op, attrs);
440  }
441
442  public void modifyAttributes(String name, ModificationItem[] mods)
443          throws NamingException
444  {
445    modifyAttributes(new CompositeName(name), mods);
446  }
447
448  public void bind(String name, Object obj, Attributes attrs)
449          throws NamingException
450  {
451    bind(new CompositeName(name), attrs);
452  }
453
454  public void rebind(String name, Object obj, Attributes attrs)
455          throws NamingException
456  {
457    rebind(new CompositeName(name), obj, attrs);
458  }
459
460  public DirContext createSubcontext(String name, Attributes attrs)
461          throws NamingException
462  {
463    return createSubcontext(new CompositeName(name), attrs);
464  }
465
466  public DirContext getSchema(String name) throws NamingException
467  {
468    return getSchema(new CompositeName(name));
469  }
470
471  public DirContext getSchemaClassDefinition(String name)
472          throws NamingException
473  {
474    return getSchemaClassDefinition(new CompositeName(name));
475  }
476
477  public NamingEnumeration search(String name,
478                                  Attributes matchingAttributes,
479                                  String[] attributesToReturn)
480          throws NamingException
481  {
482    return search(new CompositeName(name), matchingAttributes, attributesToReturn);
483  }
484
485  public NamingEnumeration search(String name,
486                                  Attributes matchingAttributes)
487          throws NamingException
488  {
489    return search(new CompositeName(name), matchingAttributes);
490  }
491
492  public NamingEnumeration search(String name,
493                                  String filter,
494                                  SearchControls cons)
495          throws NamingException
496  {
497    return search(new CompositeName(name), filter, cons);
498  }
499
500  public NamingEnumeration search(String name,
501                                  String filterExpr,
502                                  Object[] filterArgs,
503                                  SearchControls cons)
504          throws NamingException
505  {
506    return search(new CompositeName(name), filterExpr, filterArgs, cons);
507  }
508
509  class ListOfNames implements NamingEnumeration {
510    protected Enumeration names;
511
512    ListOfNames(Enumeration names)
513    {
514      this.names = names;
515    }
516
517    public boolean hasMoreElements()
518    {
519      try {
520        return hasMore();
521      } catch (NamingException e) {
522        return false;
523      }
524    }
525
526    public boolean hasMore() throws NamingException
527    {
528      return names.hasMoreElements();
529    }
530
531    public Object next() throws NamingException
532    {
533      String name = (String) names.nextElement();
534      String className = bindings.get(name).getClass().getName();
535      return new NameClassPair(name, className);
536    }
537
538    public Object nextElement()
539    {
540      try {
541        return next();
542      } catch (NamingException e) {
543        throw new NoSuchElementException(e.toString());
544      }
545    }
546
547    public void close()
548    {
549    }
550  }
551
552  class ListOfBindings implements NamingEnumeration {
553    protected Enumeration names;
554
555    ListOfBindings(Enumeration names)
556    {
557      this.names = names;
558    }
559
560    public boolean hasMoreElements()
561    {
562      try {
563        return hasMore();
564      } catch (NamingException e) {
565        return false;
566      }
567    }
568
569    public boolean hasMore() throws NamingException
570    {
571      return names.hasMoreElements();
572    }
573
574    public Object next() throws NamingException
575    {
576      String name = (String) names.nextElement();
577      Object bound = bindings.get(name);
578      return new Binding(name, bound);
579    }
580
581    public Object nextElement()
582    {
583      try {
584        return next();
585      } catch (NamingException e) {
586        throw new NoSuchElementException(e.toString());
587      }
588    }
589
590    public void close()
591    {
592    }
593  }
594 }