Logo Search packages:      
Sourcecode: jing-trang version File versions  Download package

DatatypeLibraryLoader.java

/**
 * Copyright (c) 2001, Thai Open Source Software Center Ltd
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 * 
 *     Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 
 *     Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 * 
 *     Neither the name of the Thai Open Source Software Center Ltd nor
 *     the names of its contributors may be used to endorse or promote
 *     products derived from this software without specific prior written
 *     permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
00034 package org.relaxng.datatype.helpers;

import org.relaxng.datatype.DatatypeLibraryFactory;
import org.relaxng.datatype.DatatypeLibrary;
import java.util.Enumeration;
import java.util.NoSuchElementException;
import java.util.Vector;
import java.io.Reader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;

/**
 * Discovers the datatype library implementation from the classpath.
 * 
 * <p>
 * The call of the createDatatypeLibrary method finds an implementation
 * from a given datatype library URI at run-time.
 */
00056 public class DatatypeLibraryLoader implements DatatypeLibraryFactory {
  private final Service service = new Service(DatatypeLibraryFactory.class);

00059   public DatatypeLibrary createDatatypeLibrary(String uri) {
    for (Enumeration e = service.getProviders();
       e.hasMoreElements();) {
      DatatypeLibraryFactory factory
      = (DatatypeLibraryFactory)e.nextElement();
      DatatypeLibrary library = factory.createDatatypeLibrary(uri);
      if (library != null)
      return library;
    }
    return null;
  }

      private static class Service {
        private final Class serviceClass;
        private final Enumeration configFiles;
        private Enumeration classNames = null;
        private final Vector providers = new Vector();
        private Loader loader;

        private class ProviderEnumeration implements Enumeration {
          private int nextIndex = 0;

          public boolean hasMoreElements() {
            return nextIndex < providers.size() || moreProviders();
          }

          public Object nextElement() {
            try {
            return providers.elementAt(nextIndex++);
            }
            catch (ArrayIndexOutOfBoundsException e) {
            throw new NoSuchElementException();
            }
          }
        }

        private static class Singleton implements Enumeration {
          private Object obj;
          private Singleton(Object obj) {
            this.obj = obj;
          }

          public boolean hasMoreElements() {
            return obj != null;
          }

          public Object nextElement() {
            if (obj == null)
            throw new NoSuchElementException();
            Object tem = obj;
            obj = null;
            return tem;
          }
        }

        // JDK 1.1
        private static class Loader {
          Enumeration getResources(String resName) {
            ClassLoader cl = Loader.class.getClassLoader();
            URL url;
            if (cl == null)
            url = ClassLoader.getSystemResource(resName);
            else
            url = cl.getResource(resName);
            return new Singleton(url);
          }

          Class loadClass(String name) throws ClassNotFoundException {
            return Class.forName(name);
          }
        }

        // JDK 1.2+
        private static class Loader2 extends Loader {
          private ClassLoader cl;

          Loader2() {
            cl = Loader2.class.getClassLoader();
            // If the thread context class loader has the class loader
            // of this class as an ancestor, use the thread context class
            // loader.  Otherwise, the thread context class loader
            // probably hasn't been set up properly, so don't use it.
            ClassLoader clt = Thread.currentThread().getContextClassLoader();
            for (ClassLoader tem = clt; tem != null; tem = tem.getParent())
            if (tem == cl) {
              cl = clt;
              break;
            }
          }

          Enumeration getResources(String resName) {
            try {
                Enumeration resources = cl.getResources(resName);
                if (resources.hasMoreElements())
                  return resources;
                // Some application servers apparently do not implement findResources
                // in their class loaders, so fall back to getResource.
                return new Singleton(cl.getResource(resName));
            }
            catch (IOException e) {
            return new Singleton(null);
            }
          }

          Class loadClass(String name) throws ClassNotFoundException {
            return Class.forName(name, true, cl);
          }
        }

        public Service(Class cls) {
          try {
            loader = new Loader2();
          }
          catch (NoSuchMethodError e) {
            loader = new Loader();
          }
          serviceClass = cls;
          String resName = "META-INF/services/" + serviceClass.getName();
          configFiles = loader.getResources(resName);
        }

        public Enumeration getProviders() {
          return new ProviderEnumeration();
        }

        synchronized private boolean moreProviders() {
          for (;;) {
            while (classNames == null) {
            if (!configFiles.hasMoreElements())
              return false;
            classNames = parseConfigFile((URL)configFiles.nextElement());
            }
            while (classNames.hasMoreElements()) {
            String className = (String)classNames.nextElement();
            try {
              Class cls = loader.loadClass(className);
              Object obj = cls.newInstance();
              if (serviceClass.isInstance(obj)) {
                providers.addElement(obj);
                return true;
              }
            }
            catch (ClassNotFoundException e) { }
            catch (InstantiationException e) { }
            catch (IllegalAccessException e) { }
            catch (LinkageError e) { }
            }
            classNames = null;
          }
        }

        private static final int START = 0;
        private static final int IN_NAME = 1;
        private static final int IN_COMMENT = 2;

        private static Enumeration parseConfigFile(URL url) {
          try {
            InputStream in = url.openStream();
            Reader r;
            try {
            r = new InputStreamReader(in, "UTF-8");
            }
            catch (UnsupportedEncodingException e) {
            r = new InputStreamReader(in, "UTF8");
            }
            r = new BufferedReader(r);
            Vector tokens = new Vector();
            StringBuffer tokenBuf = new StringBuffer();
            int state = START;
            for (;;) {
            int n = r.read();
            if (n < 0)
              break;
            char c = (char)n;
            switch (c) {
            case '\r':
            case '\n':
              state = START;
              break;
            case ' ':
            case '\t':
              break;
            case '#':
              state = IN_COMMENT;
              break;
            default:
              if (state != IN_COMMENT) {
                state = IN_NAME;
                tokenBuf.append(c);
              }
              break;
            }
            if (tokenBuf.length() != 0 && state != IN_NAME) {
              tokens.addElement(tokenBuf.toString());
              tokenBuf.setLength(0);
            }
            }
            if (tokenBuf.length() != 0)
            tokens.addElement(tokenBuf.toString());
            return tokens.elements();
          }
          catch (IOException e) {
            return null;
          }
        }
      }
  
}


Generated by  Doxygen 1.6.0   Back to index