1:
34: package ;
35:
36: import ;
37: import ;
38: import ;
39: import ;
40: import ;
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
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:
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:
132: private static class Loader2 extends Loader {
133: private ClassLoader cl;
134:
135: Loader2() {
136: cl = Loader2.class.getClassLoader();
137:
138:
139:
140:
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: }