2 * Copyright (c) 2001, Thai Open Source Software Center Ltd
\r
3 * All rights reserved.
\r
5 * Redistribution and use in source and binary forms, with or without
\r
6 * modification, are permitted provided that the following conditions are
\r
9 * Redistributions of source code must retain the above copyright
\r
10 * notice, this list of conditions and the following disclaimer.
\r
12 * Redistributions in binary form must reproduce the above copyright
\r
13 * notice, this list of conditions and the following disclaimer in
\r
14 * the documentation and/or other materials provided with the
\r
17 * Neither the name of the Thai Open Source Software Center Ltd nor
\r
18 * the names of its contributors may be used to endorse or promote
\r
19 * products derived from this software without specific prior written
\r
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
\r
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
\r
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
\r
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
\r
26 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
\r
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
\r
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
\r
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
\r
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
\r
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
\r
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
34 package org.relaxng.datatype.helpers;
\r
36 import org.relaxng.datatype.DatatypeLibraryFactory;
\r
37 import org.relaxng.datatype.DatatypeLibrary;
\r
38 import java.util.Enumeration;
\r
39 import java.util.NoSuchElementException;
\r
40 import java.util.Vector;
\r
41 import java.io.Reader;
\r
42 import java.io.InputStream;
\r
43 import java.io.InputStreamReader;
\r
44 import java.io.BufferedReader;
\r
45 import java.io.IOException;
\r
46 import java.io.UnsupportedEncodingException;
\r
47 import java.net.URL;
\r
50 * Discovers the datatype library implementation from the classpath.
\r
53 * The call of the createDatatypeLibrary method finds an implementation
\r
54 * from a given datatype library URI at run-time.
\r
56 public class DatatypeLibraryLoader implements DatatypeLibraryFactory {
\r
57 private final Service service = new Service(DatatypeLibraryFactory.class);
\r
59 public DatatypeLibrary createDatatypeLibrary(String uri) {
\r
60 for (Enumeration e = service.getProviders();
\r
61 e.hasMoreElements();) {
\r
62 DatatypeLibraryFactory factory
\r
63 = (DatatypeLibraryFactory)e.nextElement();
\r
64 DatatypeLibrary library = factory.createDatatypeLibrary(uri);
\r
65 if (library != null)
\r
71 private static class Service {
\r
72 private final Class serviceClass;
\r
73 private final Enumeration configFiles;
\r
74 private Enumeration classNames = null;
\r
75 private final Vector providers = new Vector();
\r
76 private Loader loader;
\r
78 private class ProviderEnumeration implements Enumeration {
\r
79 private int nextIndex = 0;
\r
81 public boolean hasMoreElements() {
\r
82 return nextIndex < providers.size() || moreProviders();
\r
85 public Object nextElement() {
\r
87 return providers.elementAt(nextIndex++);
\r
89 catch (ArrayIndexOutOfBoundsException e) {
\r
90 throw new NoSuchElementException();
\r
95 private static class Singleton implements Enumeration {
\r
97 private Singleton(Object obj) {
\r
101 public boolean hasMoreElements() {
\r
102 return obj != null;
\r
105 public Object nextElement() {
\r
107 throw new NoSuchElementException();
\r
115 private static class Loader {
\r
116 Enumeration getResources(String resName) {
\r
117 ClassLoader cl = Loader.class.getClassLoader();
\r
120 url = ClassLoader.getSystemResource(resName);
\r
122 url = cl.getResource(resName);
\r
123 return new Singleton(url);
\r
126 Class loadClass(String name) throws ClassNotFoundException {
\r
127 return Class.forName(name);
\r
132 private static class Loader2 extends Loader {
\r
133 private ClassLoader cl;
\r
136 cl = Loader2.class.getClassLoader();
\r
137 // If the thread context class loader has the class loader
\r
138 // of this class as an ancestor, use the thread context class
\r
139 // loader. Otherwise, the thread context class loader
\r
140 // probably hasn't been set up properly, so don't use it.
\r
141 ClassLoader clt = Thread.currentThread().getContextClassLoader();
\r
142 for (ClassLoader tem = clt; tem != null; tem = tem.getParent())
\r
149 Enumeration getResources(String resName) {
\r
151 return cl.getResources(resName);
\r
153 catch (IOException e) {
\r
154 return new Singleton(null);
\r
158 Class loadClass(String name) throws ClassNotFoundException {
\r
159 return Class.forName(name, true, cl);
\r
163 public Service(Class cls) {
\r
165 loader = new Loader2();
\r
167 catch (NoSuchMethodError e) {
\r
168 loader = new Loader();
\r
170 serviceClass = cls;
\r
171 String resName = "META-INF/services/" + serviceClass.getName();
\r
172 configFiles = loader.getResources(resName);
\r
175 public Enumeration getProviders() {
\r
176 return new ProviderEnumeration();
\r
179 synchronized private boolean moreProviders() {
\r
181 while (classNames == null) {
\r
182 if (!configFiles.hasMoreElements())
\r
184 classNames = parseConfigFile((URL)configFiles.nextElement());
\r
186 while (classNames.hasMoreElements()) {
\r
187 String className = (String)classNames.nextElement();
\r
189 Class cls = loader.loadClass(className);
\r
190 Object obj = cls.newInstance();
\r
191 if (serviceClass.isInstance(obj)) {
\r
192 providers.addElement(obj);
\r
196 catch (ClassNotFoundException e) { }
\r
197 catch (InstantiationException e) { }
\r
198 catch (IllegalAccessException e) { }
\r
199 catch (LinkageError e) { }
\r
205 private static final int START = 0;
\r
206 private static final int IN_NAME = 1;
\r
207 private static final int IN_COMMENT = 2;
\r
209 private static Enumeration parseConfigFile(URL url) {
\r
211 InputStream in = url.openStream();
\r
214 r = new InputStreamReader(in, "UTF-8");
\r
216 catch (UnsupportedEncodingException e) {
\r
217 r = new InputStreamReader(in, "UTF8");
\r
219 r = new BufferedReader(r);
\r
220 Vector tokens = new Vector();
\r
221 StringBuffer tokenBuf = new StringBuffer();
\r
237 state = IN_COMMENT;
\r
240 if (state != IN_COMMENT) {
\r
242 tokenBuf.append(c);
\r
246 if (tokenBuf.length() != 0 && state != IN_NAME) {
\r
247 tokens.addElement(tokenBuf.toString());
\r
248 tokenBuf.setLength(0);
\r
251 if (tokenBuf.length() != 0)
\r
252 tokens.addElement(tokenBuf.toString());
\r
253 return tokens.elements();
\r
255 catch (IOException e) {
\r