OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / lib / classpath / external / relaxngDatatype / org / relaxng / datatype / helpers / DatatypeLibraryLoader.java
1 /**\r
2  * Copyright (c) 2001, Thai Open Source Software Center Ltd\r
3  * All rights reserved.\r
4  * \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
7  * met:\r
8  * \r
9  *     Redistributions of source code must retain the above copyright\r
10  *     notice, this list of conditions and the following disclaimer.\r
11  * \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
15  *     distribution.\r
16  * \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
20  *     permission.\r
21  * \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
33  */\r
34 package org.relaxng.datatype.helpers;\r
35 \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
48 \r
49 /**\r
50  * Discovers the datatype library implementation from the classpath.\r
51  * \r
52  * <p>\r
53  * The call of the createDatatypeLibrary method finds an implementation\r
54  * from a given datatype library URI at run-time.\r
55  */\r
56 public class DatatypeLibraryLoader implements DatatypeLibraryFactory {\r
57   private final Service service = new Service(DatatypeLibraryFactory.class);\r
58 \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
66         return library;\r
67     }\r
68     return null;\r
69   }\r
70 \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
77 \r
78           private class ProviderEnumeration implements Enumeration {\r
79             private int nextIndex = 0;\r
80 \r
81             public boolean hasMoreElements() {\r
82               return nextIndex < providers.size() || moreProviders();\r
83             }\r
84 \r
85             public Object nextElement() {\r
86               try {\r
87                 return providers.elementAt(nextIndex++);\r
88               }\r
89               catch (ArrayIndexOutOfBoundsException e) {\r
90                 throw new NoSuchElementException();\r
91               }\r
92             }\r
93           }\r
94 \r
95           private static class Singleton implements Enumeration {\r
96             private Object obj;\r
97             private Singleton(Object obj) {\r
98               this.obj = obj;\r
99             }\r
100 \r
101             public boolean hasMoreElements() {\r
102               return obj != null;\r
103             }\r
104 \r
105             public Object nextElement() {\r
106               if (obj == null)\r
107                 throw new NoSuchElementException();\r
108               Object tem = obj;\r
109               obj = null;\r
110               return tem;\r
111             }\r
112           }\r
113 \r
114           // JDK 1.1\r
115           private static class Loader {\r
116             Enumeration getResources(String resName) {\r
117               ClassLoader cl = Loader.class.getClassLoader();\r
118               URL url;\r
119               if (cl == null)\r
120                 url = ClassLoader.getSystemResource(resName);\r
121               else\r
122                 url = cl.getResource(resName);\r
123               return new Singleton(url);\r
124             }\r
125 \r
126             Class loadClass(String name) throws ClassNotFoundException {\r
127               return Class.forName(name);\r
128             }\r
129           }\r
130 \r
131           // JDK 1.2+\r
132           private static class Loader2 extends Loader {\r
133             private ClassLoader cl;\r
134 \r
135             Loader2() {\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
143                 if (tem == cl) {\r
144                   cl = clt;\r
145                   break;\r
146                 }\r
147             }\r
148 \r
149             Enumeration getResources(String resName) {\r
150               try {\r
151                 return cl.getResources(resName);\r
152               }\r
153               catch (IOException e) {\r
154                 return new Singleton(null);\r
155               }\r
156             }\r
157 \r
158             Class loadClass(String name) throws ClassNotFoundException {\r
159               return Class.forName(name, true, cl);\r
160             }\r
161           }\r
162 \r
163           public Service(Class cls) {\r
164             try {\r
165               loader = new Loader2();\r
166             }\r
167             catch (NoSuchMethodError e) {\r
168               loader = new Loader();\r
169             }\r
170             serviceClass = cls;\r
171             String resName = "META-INF/services/" + serviceClass.getName();\r
172             configFiles = loader.getResources(resName);\r
173           }\r
174 \r
175           public Enumeration getProviders() {\r
176             return new ProviderEnumeration();\r
177           }\r
178 \r
179           synchronized private boolean moreProviders() {\r
180             for (;;) {\r
181               while (classNames == null) {\r
182                 if (!configFiles.hasMoreElements())\r
183                   return false;\r
184                 classNames = parseConfigFile((URL)configFiles.nextElement());\r
185               }\r
186               while (classNames.hasMoreElements()) {\r
187                 String className = (String)classNames.nextElement();\r
188                 try {\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
193                     return true;\r
194                   }\r
195                 }\r
196                 catch (ClassNotFoundException e) { }\r
197                 catch (InstantiationException e) { }\r
198                 catch (IllegalAccessException e) { }\r
199                 catch (LinkageError e) { }\r
200               }\r
201               classNames = null;\r
202             }\r
203           }\r
204 \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
208 \r
209           private static Enumeration parseConfigFile(URL url) {\r
210             try {\r
211               InputStream in = url.openStream();\r
212               Reader r;\r
213               try {\r
214                 r = new InputStreamReader(in, "UTF-8");\r
215               }\r
216               catch (UnsupportedEncodingException e) {\r
217                 r = new InputStreamReader(in, "UTF8");\r
218               }\r
219               r = new BufferedReader(r);\r
220               Vector tokens = new Vector();\r
221               StringBuffer tokenBuf = new StringBuffer();\r
222               int state = START;\r
223               for (;;) {\r
224                 int n = r.read();\r
225                 if (n < 0)\r
226                   break;\r
227                 char c = (char)n;\r
228                 switch (c) {\r
229                 case '\r':\r
230                 case '\n':\r
231                   state = START;\r
232                   break;\r
233                 case ' ':\r
234                 case '\t':\r
235                   break;\r
236                 case '#':\r
237                   state = IN_COMMENT;\r
238                   break;\r
239                 default:\r
240                   if (state != IN_COMMENT) {\r
241                     state = IN_NAME;\r
242                     tokenBuf.append(c);\r
243                   }\r
244                   break;\r
245                 }\r
246                 if (tokenBuf.length() != 0 && state != IN_NAME) {\r
247                   tokens.addElement(tokenBuf.toString());\r
248                   tokenBuf.setLength(0);\r
249                 }\r
250               }\r
251               if (tokenBuf.length() != 0)\r
252                 tokens.addElement(tokenBuf.toString());\r
253               return tokens.elements();\r
254             }\r
255             catch (IOException e) {\r
256               return null;\r
257             }\r
258           }\r
259         }\r
260   \r
261 }\r
262 \r