1 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 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 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 private static class Loader2 extends Loader { 133 private ClassLoader cl; 134 135 Loader2() { 136 cl = Loader2.class.getClassLoader(); 137 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 Enumeration resources = cl.getResources(resName); 152 if (resources.hasMoreElements()) 153 return resources; 154 return new Singleton(cl.getResource(resName)); 157 } 158 catch (IOException e) { 159 return new Singleton(null); 160 } 161 } 162 163 Class loadClass(String name) throws ClassNotFoundException { 164 return Class.forName(name, true, cl); 165 } 166 } 167 168 public Service(Class cls) { 169 try { 170 loader = new Loader2(); 171 } 172 catch (NoSuchMethodError e) { 173 loader = new Loader(); 174 } 175 serviceClass = cls; 176 String resName = "META-INF/services/" + serviceClass.getName(); 177 configFiles = loader.getResources(resName); 178 } 179 180 public Enumeration 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 )configFiles.nextElement()); 190 } 191 while (classNames.hasMoreElements()) { 192 String className = (String )classNames.nextElement(); 193 try { 194 Class cls = loader.loadClass(className); 195 Object obj = cls.newInstance(); 196 if (serviceClass.isInstance(obj)) { 197 providers.addElement(obj); 198 return true; 199 } 200 } 201 catch (ClassNotFoundException e) { } 202 catch (InstantiationException e) { } 203 catch (IllegalAccessException e) { } 204 catch (LinkageError 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 parseConfigFile(URL url) { 215 try { 216 InputStream in = url.openStream(); 217 Reader r; 218 try { 219 r = new InputStreamReader (in, "UTF-8"); 220 } 221 catch (UnsupportedEncodingException e) { 222 r = new InputStreamReader (in, "UTF8"); 223 } 224 r = new BufferedReader (r); 225 Vector tokens = new Vector (); 226 StringBuffer tokenBuf = new StringBuffer (); 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 e) { 261 return null; 262 } 263 } 264 } 265 266 } 267 268 | Popular Tags |