001package org.biojava.naming;
002
003import java.util.Hashtable;
004
005import javax.naming.Context;
006import javax.naming.Name;
007import javax.naming.NamingException;
008import javax.naming.directory.BasicAttributes;
009import javax.naming.spi.InitialContextFactory;
010import javax.xml.parsers.SAXParserFactory;
011
012import org.biojava.utils.ClassTools;
013import org.xml.sax.Attributes;
014import org.xml.sax.InputSource;
015import org.xml.sax.SAXException;
016import org.xml.sax.XMLReader;
017import org.xml.sax.helpers.DefaultHandler;
018
019/**
020 *
021 *
022 * @author Matthew Pocock
023 */
024public class ObdaInitialContextFactory
025        implements InitialContextFactory
026{
027  private static final String CORE = "obda/naming/core.xml";
028
029  public Context getInitialContext(Hashtable environment)
030          throws NamingException
031  {
032    try {
033      InputSource iSource = new InputSource(ClassTools.getClassLoader(ObdaInitialContextFactory.class).getResourceAsStream(CORE));
034      SAXParserFactory spf = SAXParserFactory.newInstance();
035      spf.setValidating(false);
036      spf.setNamespaceAware(true);
037      XMLReader reader = spf.newSAXParser().getXMLReader();
038      ObdaHandler handler = new ObdaHandler(environment);
039      reader.setContentHandler(handler);
040      reader.parse(iSource);
041      return handler.getRoot();
042    } catch (Exception e) {
043      throw new Error(e);
044    }
045  }
046
047  private class ObdaHandler
048          extends DefaultHandler
049  {
050    Hashtable env;
051    ObdaContext root;
052    ObdaContext current;
053    StringBuffer description = null;
054
055    ObdaHandler(Hashtable env)
056    {
057      this.env = env;
058    }
059
060    public ObdaContext getRoot()
061    {
062      return root;
063    }
064
065    public void startDocument()
066            throws SAXException
067    {
068      root = new ObdaContext(null, null,
069                             new Hashtable(), env, new BasicAttributes());
070    }
071
072    public void startElement(String uri, String localName,
073                             String qName, Attributes attributes)
074            throws SAXException
075    {
076      if(qName.equals("directory")) {
077        // do directory things
078      } else if(qName.equals("urn")) {
079        // unpack the URN, break it into words, make the contexts (if needed)
080        try {
081          Name name = ObdaUriParser.getInstance()
082                  .parse(attributes.getValue("name"));
083          ObdaContext ctxt = root;
084          for(int i = 0; i < name.size(); i++) {
085            ctxt = resolve(ctxt, name.get(i));
086          }
087          current = ctxt;
088        } catch (NamingException e) {
089          throw new SAXException(e);
090        }
091      } else if(qName.equals("description")) {
092        // add the description to the current context - we will first have to
093        // collect all the description text together and then set it on
094        // end element
095        description = new StringBuffer();
096      }
097    }
098
099    public void endElement(String uri, String localName, String qName)
100            throws SAXException
101    {
102      if(qName.equals("description") && description != null) {
103        current.getAttrs().put("description", description.toString());
104        description = null;
105      }
106    }
107
108    public void characters(char ch[], int start, int length)
109            throws SAXException
110    {
111      if(description != null) {
112        description.append(ch, start, length);
113      }
114    }
115
116    private ObdaContext resolve(ObdaContext parent, String name)
117    {
118      Hashtable bindings = parent.getBindings();
119      ObdaContext child = (ObdaContext) bindings.get(name);
120
121      if(child == null) {
122        child = new ObdaContext(
123                parent, name,
124                new Hashtable(), new Hashtable(), new BasicAttributes());
125        bindings.put(name, child);
126      }
127
128      return child;
129    }
130  }
131}