KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > relaxng > datatype > helpers > DatatypeLibraryLoader


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 JavaDoc;
39 import java.util.NoSuchElementException JavaDoc;
40 import java.util.Vector JavaDoc;
41 import java.io.Reader JavaDoc;
42 import java.io.InputStream JavaDoc;
43 import java.io.InputStreamReader JavaDoc;
44 import java.io.BufferedReader JavaDoc;
45 import java.io.IOException JavaDoc;
46 import java.io.UnsupportedEncodingException JavaDoc;
47 import java.net.URL JavaDoc;
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 JavaDoc uri) {
60     for (Enumeration JavaDoc 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 JavaDoc serviceClass;
73       private final Enumeration JavaDoc configFiles;
74       private Enumeration JavaDoc classNames = null;
75       private final Vector JavaDoc providers = new Vector JavaDoc();
76       private Loader loader;
77
78       private class ProviderEnumeration implements Enumeration JavaDoc {
79         private int nextIndex = 0;
80
81         public boolean hasMoreElements() {
82           return nextIndex < providers.size() || moreProviders();
83         }
84
85         public Object JavaDoc nextElement() {
86           try {
87         return providers.elementAt(nextIndex++);
88           }
89           catch (ArrayIndexOutOfBoundsException JavaDoc e) {
90         throw new NoSuchElementException JavaDoc();
91           }
92         }
93       }
94
95       private static class Singleton implements Enumeration JavaDoc {
96         private Object JavaDoc obj;
97         private Singleton(Object JavaDoc obj) {
98           this.obj = obj;
99         }
100
101         public boolean hasMoreElements() {
102           return obj != null;
103         }
104
105         public Object JavaDoc nextElement() {
106           if (obj == null)
107         throw new NoSuchElementException JavaDoc();
108           Object JavaDoc tem = obj;
109           obj = null;
110           return tem;
111         }
112       }
113
114       // JDK 1.1
115
private static class Loader {
116         Enumeration JavaDoc getResources(String JavaDoc resName) {
117           ClassLoader JavaDoc cl = Loader.class.getClassLoader();
118           URL JavaDoc 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 JavaDoc loadClass(String JavaDoc name) throws ClassNotFoundException JavaDoc {
127           return Class.forName(name);
128         }
129       }
130
131       // JDK 1.2+
132
private static class Loader2 extends Loader {
133         private ClassLoader JavaDoc 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 JavaDoc clt = Thread.currentThread().getContextClassLoader();
142           for (ClassLoader JavaDoc tem = clt; tem != null; tem = tem.getParent())
143         if (tem == cl) {
144           cl = clt;
145           break;
146         }
147         }
148
149         Enumeration JavaDoc getResources(String JavaDoc resName) {
150           try {
151                 Enumeration JavaDoc resources = cl.getResources(resName);
152                 if (resources.hasMoreElements())
153                   return resources;
154                 // Some application servers apparently do not implement findResources
155
// in their class loaders, so fall back to getResource.
156
return new Singleton(cl.getResource(resName));
157           }
158           catch (IOException JavaDoc e) {
159         return new Singleton(null);
160           }
161         }
162
163         Class JavaDoc loadClass(String JavaDoc name) throws ClassNotFoundException JavaDoc {
164           return Class.forName(name, true, cl);
165         }
166       }
167
168       public Service(Class JavaDoc cls) {
169         try {
170           loader = new Loader2();
171         }
172         catch (NoSuchMethodError JavaDoc e) {
173           loader = new Loader();
174         }
175         serviceClass = cls;
176         String JavaDoc resName = "META-INF/services/" + serviceClass.getName();
177         configFiles = loader.getResources(resName);
178       }
179
180       public Enumeration JavaDoc getProviders() {
181         return new ProviderEnumeration();
182       }
183
184       synchronized private boolean moreProviders() {
185         for (;;) {
186           while (classNames == null) {
187         if (!configFiles.hasMoreElements())
188           return false;
189         classNames = parseConfigFile((URL JavaDoc)configFiles.nextElement());
190           }
191           while (classNames.hasMoreElements()) {
192         String JavaDoc className = (String JavaDoc)classNames.nextElement();
193         try {
194           Class JavaDoc cls = loader.loadClass(className);
195           Object JavaDoc obj = cls.newInstance();
196           if (serviceClass.isInstance(obj)) {
197             providers.addElement(obj);
198             return true;
199           }
200         }
201         catch (ClassNotFoundException JavaDoc e) { }
202         catch (InstantiationException JavaDoc e) { }
203         catch (IllegalAccessException JavaDoc e) { }
204         catch (LinkageError JavaDoc e) { }
205           }
206           classNames = null;
207         }
208       }
209
210       private static final int START = 0;
211       private static final int IN_NAME = 1;
212       private static final int IN_COMMENT = 2;
213
214       private static Enumeration JavaDoc parseConfigFile(URL JavaDoc url) {
215         try {
216           InputStream JavaDoc in = url.openStream();
217           Reader JavaDoc r;
218           try {
219         r = new InputStreamReader JavaDoc(in, "UTF-8");
220           }
221           catch (UnsupportedEncodingException JavaDoc e) {
222         r = new InputStreamReader JavaDoc(in, "UTF8");
223           }
224           r = new BufferedReader JavaDoc(r);
225           Vector JavaDoc tokens = new Vector JavaDoc();
226           StringBuffer JavaDoc tokenBuf = new StringBuffer JavaDoc();
227           int state = START;
228           for (;;) {
229         int n = r.read();
230         if (n < 0)
231           break;
232         char c = (char)n;
233         switch (c) {
234         case '\r':
235         case '\n':
236           state = START;
237           break;
238         case ' ':
239         case '\t':
240           break;
241         case '#':
242           state = IN_COMMENT;
243           break;
244         default:
245           if (state != IN_COMMENT) {
246             state = IN_NAME;
247             tokenBuf.append(c);
248           }
249           break;
250         }
251         if (tokenBuf.length() != 0 && state != IN_NAME) {
252           tokens.addElement(tokenBuf.toString());
253           tokenBuf.setLength(0);
254         }
255           }
256           if (tokenBuf.length() != 0)
257         tokens.addElement(tokenBuf.toString());
258           return tokens.elements();
259         }
260         catch (IOException JavaDoc e) {
261           return null;
262         }
263       }
264     }
265   
266 }
267
268
Popular Tags