Home » Open-JDK-6.b17-src » org.relaxng » datatype » helpers » [javadoc | source]

    1   /**
    2    * Copyright (c) 2001, Thai Open Source Software Center Ltd
    3    * All rights reserved.
    4    *
    5    * Redistribution and use in source and binary forms, with or without
    6    * modification, are permitted provided that the following conditions are
    7    * met:
    8    *
    9    *     Redistributions of source code must retain the above copyright
   10    *     notice, this list of conditions and the following disclaimer.
   11    *
   12    *     Redistributions in binary form must reproduce the above copyright
   13    *     notice, this list of conditions and the following disclaimer in
   14    *     the documentation and/or other materials provided with the
   15    *     distribution.
   16    *
   17    *     Neither the name of the Thai Open Source Software Center Ltd nor
   18    *     the names of its contributors may be used to endorse or promote
   19    *     products derived from this software without specific prior written
   20    *     permission.
   21    *
   22    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   23    * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   24    * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   25    * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
   26    * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   27    * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   28    * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   29    * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   30    * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   31    * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   32    * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   33    */
   34   package org.relaxng.datatype.helpers;
   35   
   36   import org.relaxng.datatype.DatatypeLibraryFactory;
   37   import org.relaxng.datatype.DatatypeLibrary;
   38   import java.util.Enumeration;
   39   import java.util.NoSuchElementException;
   40   import java.util.Vector;
   41   import java.io.Reader;
   42   import java.io.InputStream;
   43   import java.io.InputStreamReader;
   44   import java.io.BufferedReader;
   45   import java.io.IOException;
   46   import java.io.UnsupportedEncodingException;
   47   import java.net.URL;
   48   
   49   /**
   50    * Discovers the datatype library implementation from the classpath.
   51    *
   52    * <p>
   53    * The call of the createDatatypeLibrary method finds an implementation
   54    * from a given datatype library URI at run-time.
   55    */
   56   public class DatatypeLibraryLoader implements DatatypeLibraryFactory {
   57     private final Service service = new Service(DatatypeLibraryFactory.class);
   58   
   59     public DatatypeLibrary createDatatypeLibrary(String uri) {
   60       for (Enumeration e = service.getProviders();
   61            e.hasMoreElements();) {
   62         DatatypeLibraryFactory factory
   63           = (DatatypeLibraryFactory)e.nextElement();
   64         DatatypeLibrary library = factory.createDatatypeLibrary(uri);
   65         if (library != null)
   66           return library;
   67       }
   68       return null;
   69     }
   70   
   71           private static class Service {
   72             private final Class serviceClass;
   73             private final Enumeration configFiles;
   74             private Enumeration classNames = null;
   75             private final Vector providers = new Vector();
   76             private Loader loader;
   77   
   78             private class ProviderEnumeration implements Enumeration {
   79               private int nextIndex = 0;
   80   
   81               public boolean hasMoreElements() {
   82                 return nextIndex < providers.size() || moreProviders();
   83               }
   84   
   85               public Object nextElement() {
   86                 try {
   87                   return providers.elementAt(nextIndex++);
   88                 }
   89                 catch (ArrayIndexOutOfBoundsException e) {
   90                   throw new NoSuchElementException();
   91                 }
   92               }
   93             }
   94   
   95             private static class Singleton implements Enumeration {
   96               private Object obj;
   97               private Singleton(Object obj) {
   98                 this.obj = obj;
   99               }
  100   
  101               public boolean hasMoreElements() {
  102                 return obj != null;
  103               }
  104   
  105               public Object nextElement() {
  106                 if (obj == null)
  107                   throw new NoSuchElementException();
  108                 Object tem = obj;
  109                 obj = null;
  110                 return tem;
  111               }
  112             }
  113   
  114             // JDK 1.1
  115             private static class Loader {
  116               Enumeration getResources(String resName) {
  117                 ClassLoader cl = Loader.class.getClassLoader();
  118                 URL url;
  119                 if (cl == null)
  120                   url = ClassLoader.getSystemResource(resName);
  121                 else
  122                   url = cl.getResource(resName);
  123                 return new Singleton(url);
  124               }
  125   
  126               Class loadClass(String name) throws ClassNotFoundException {
  127                 return Class.forName(name);
  128               }
  129             }
  130   
  131             // JDK 1.2+
  132             private static class Loader2 extends Loader {
  133               private ClassLoader cl;
  134   
  135               Loader2() {
  136                 cl = Loader2.class.getClassLoader();
  137                 // If the thread context class loader has the class loader
  138                 // of this class as an ancestor, use the thread context class
  139                 // loader.  Otherwise, the thread context class loader
  140                 // probably hasn't been set up properly, so don't use it.
  141                 ClassLoader clt = Thread.currentThread().getContextClassLoader();
  142                 for (ClassLoader tem = clt; tem != null; tem = tem.getParent())
  143                   if (tem == cl) {
  144                     cl = clt;
  145                     break;
  146                   }
  147               }
  148   
  149               Enumeration getResources(String resName) {
  150                 try {
  151                   return cl.getResources(resName);
  152                 }
  153                 catch (IOException e) {
  154                   return new Singleton(null);
  155                 }
  156               }
  157   
  158               Class loadClass(String name) throws ClassNotFoundException {
  159                 return Class.forName(name, true, cl);
  160               }
  161             }
  162   
  163             public Service(Class cls) {
  164               try {
  165                 loader = new Loader2();
  166               }
  167               catch (NoSuchMethodError e) {
  168                 loader = new Loader();
  169               }
  170               serviceClass = cls;
  171               String resName = "META-INF/services/" + serviceClass.getName();
  172               configFiles = loader.getResources(resName);
  173             }
  174   
  175             public Enumeration getProviders() {
  176               return new ProviderEnumeration();
  177             }
  178   
  179             synchronized private boolean moreProviders() {
  180               for (;;) {
  181                 while (classNames == null) {
  182                   if (!configFiles.hasMoreElements())
  183                     return false;
  184                   classNames = parseConfigFile((URL)configFiles.nextElement());
  185                 }
  186                 while (classNames.hasMoreElements()) {
  187                   String className = (String)classNames.nextElement();
  188                   try {
  189                     Class cls = loader.loadClass(className);
  190                     Object obj = cls.newInstance();
  191                     if (serviceClass.isInstance(obj)) {
  192                       providers.addElement(obj);
  193                       return true;
  194                     }
  195                   }
  196                   catch (ClassNotFoundException e) { }
  197                   catch (InstantiationException e) { }
  198                   catch (IllegalAccessException e) { }
  199                   catch (LinkageError e) { }
  200                 }
  201                 classNames = null;
  202               }
  203             }
  204   
  205             private static final int START = 0;
  206             private static final int IN_NAME = 1;
  207             private static final int IN_COMMENT = 2;
  208   
  209             private static Enumeration parseConfigFile(URL url) {
  210               try {
  211                 InputStream in = url.openStream();
  212                 Reader r;
  213                 try {
  214                   r = new InputStreamReader(in, "UTF-8");
  215                 }
  216                 catch (UnsupportedEncodingException e) {
  217                   r = new InputStreamReader(in, "UTF8");
  218                 }
  219                 r = new BufferedReader(r);
  220                 Vector tokens = new Vector();
  221                 StringBuffer tokenBuf = new StringBuffer();
  222                 int state = START;
  223                 for (;;) {
  224                   int n = r.read();
  225                   if (n < 0)
  226                     break;
  227                   char c = (char)n;
  228                   switch (c) {
  229                   case '\r':
  230                   case '\n':
  231                     state = START;
  232                     break;
  233                   case ' ':
  234                   case '\t':
  235                     break;
  236                   case '#':
  237                     state = IN_COMMENT;
  238                     break;
  239                   default:
  240                     if (state != IN_COMMENT) {
  241                       state = IN_NAME;
  242                       tokenBuf.append(c);
  243                     }
  244                     break;
  245                   }
  246                   if (tokenBuf.length() != 0 && state != IN_NAME) {
  247                     tokens.addElement(tokenBuf.toString());
  248                     tokenBuf.setLength(0);
  249                   }
  250                 }
  251                 if (tokenBuf.length() != 0)
  252                   tokens.addElement(tokenBuf.toString());
  253                 return tokens.elements();
  254               }
  255               catch (IOException e) {
  256                 return null;
  257               }
  258             }
  259           }
  260   
  261   }

Home » Open-JDK-6.b17-src » org.relaxng » datatype » helpers » [javadoc | source]