jaxws/src/jdk.xml.bind/share/classes/com/sun/xml/internal/org/relaxng/datatype/helpers/DatatypeLibraryLoader.java
changeset 32904 42076a665ea1
parent 25871 b80b84e87032
child 33547 e4c76ac38b12
equal deleted inserted replaced
32803:51b2db2fa04c 32904:42076a665ea1
       
     1 /**
       
     2  * Copyright (c) 2001, 2015 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 com.sun.xml.internal.org.relaxng.datatype.helpers;
       
    35 
       
    36 import com.sun.xml.internal.org.relaxng.datatype.DatatypeLibraryFactory;
       
    37 import com.sun.xml.internal.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 }