1 package com.thaiopensource.util; 2 3 import java.util.Enumeration ; 4 import java.util.NoSuchElementException ; 5 import java.util.Vector ; 6 import java.io.Reader ; 7 import java.io.InputStream ; 8 import java.io.InputStreamReader ; 9 import java.io.BufferedReader ; 10 import java.io.IOException ; 11 import java.io.UnsupportedEncodingException ; 12 import java.net.URL ; 13 14 public class Service { 15 private final Class serviceClass; 16 private final Enumeration configFiles; 17 private Enumeration classNames = null; 18 private final Vector providers = new Vector (); 19 private Loader loader; 20 21 private class ProviderEnumeration implements Enumeration { 22 private int nextIndex = 0; 23 24 public boolean hasMoreElements() { 25 return nextIndex < providers.size() || moreProviders(); 26 } 27 28 public Object nextElement() { 29 try { 30 return providers.elementAt(nextIndex++); 31 } 32 catch (ArrayIndexOutOfBoundsException e) { 33 throw new NoSuchElementException (); 34 } 35 } 36 } 37 38 private static class Singleton implements Enumeration { 39 private Object obj; 40 private Singleton(Object obj) { 41 this.obj = obj; 42 } 43 44 public boolean hasMoreElements() { 45 return obj != null; 46 } 47 48 public Object nextElement() { 49 if (obj == null) 50 throw new NoSuchElementException (); 51 Object tem = obj; 52 obj = null; 53 return tem; 54 } 55 } 56 57 private static class Loader { 59 Enumeration getResources(String resName) { 60 ClassLoader cl = Loader.class.getClassLoader(); 61 URL url; 62 if (cl == null) 63 url = ClassLoader.getSystemResource(resName); 64 else 65 url = cl.getResource(resName); 66 return new Singleton(url); 67 } 68 69 Class loadClass(String name) throws ClassNotFoundException { 70 return Class.forName(name); 71 } 72 } 73 74 private static class Loader2 extends Loader { 76 private ClassLoader cl; 77 78 Loader2() { 79 cl = Loader2.class.getClassLoader(); 80 ClassLoader clt = Thread.currentThread().getContextClassLoader(); 85 for (ClassLoader tem = clt; tem != null; tem = tem.getParent()) 86 if (tem == cl) { 87 cl = clt; 88 break; 89 } 90 } 91 92 Enumeration getResources(String resName) { 93 try { 94 Enumeration resources = cl.getResources(resName); 95 if (resources.hasMoreElements()) 96 return resources; 97 return new Singleton(cl.getResource(resName)); 100 } 101 catch (IOException e) { 102 return new Singleton(null); 103 } 104 } 105 106 Class loadClass(String name) throws ClassNotFoundException { 107 return Class.forName(name, true, cl); 108 } 109 } 110 111 public Service(Class cls) { 112 try { 113 loader = new Loader2(); 114 } 115 catch (NoSuchMethodError e) { 116 loader = new Loader(); 117 } 118 serviceClass = cls; 119 String resName = "META-INF/services/" + serviceClass.getName(); 120 configFiles = loader.getResources(resName); 121 } 122 123 public Enumeration getProviders() { 124 return new ProviderEnumeration(); 125 } 126 127 synchronized private boolean moreProviders() { 128 for (;;) { 129 while (classNames == null) { 130 if (!configFiles.hasMoreElements()) 131 return false; 132 classNames = parseConfigFile((URL )configFiles.nextElement()); 133 } 134 while (classNames.hasMoreElements()) { 135 String className = (String )classNames.nextElement(); 136 try { 137 Class cls = loader.loadClass(className); 138 Object obj = cls.newInstance(); 139 if (serviceClass.isInstance(obj)) { 140 providers.addElement(obj); 141 return true; 142 } 143 } 144 catch (ClassNotFoundException e) { } 145 catch (InstantiationException e) { } 146 catch (IllegalAccessException e) { } 147 catch (LinkageError e) { } 148 } 149 classNames = null; 150 } 151 } 152 153 private static final int START = 0; 154 private static final int IN_NAME = 1; 155 private static final int IN_COMMENT = 2; 156 157 private static Enumeration parseConfigFile(URL url) { 158 try { 159 InputStream in = url.openStream(); 160 Reader r; 161 try { 162 r = new InputStreamReader (in, "UTF-8"); 163 } 164 catch (UnsupportedEncodingException e) { 165 r = new InputStreamReader (in, "UTF8"); 166 } 167 r = new BufferedReader (r); 168 Vector tokens = new Vector (); 169 StringBuffer tokenBuf = new StringBuffer (); 170 int state = START; 171 for (;;) { 172 int n = r.read(); 173 if (n < 0) 174 break; 175 char c = (char)n; 176 switch (c) { 177 case '\r': 178 case '\n': 179 state = START; 180 break; 181 case ' ': 182 case '\t': 183 break; 184 case '#': 185 state = IN_COMMENT; 186 break; 187 default: 188 if (state != IN_COMMENT) { 189 state = IN_NAME; 190 tokenBuf.append(c); 191 } 192 break; 193 } 194 if (tokenBuf.length() != 0 && state != IN_NAME) { 195 tokens.addElement(tokenBuf.toString()); 196 tokenBuf.setLength(0); 197 } 198 } 199 if (tokenBuf.length() != 0) 200 tokens.addElement(tokenBuf.toString()); 201 return tokens.elements(); 202 } 203 catch (IOException e) { 204 return null; 205 } 206 } 207 208 public static void main(String [] args) throws ClassNotFoundException { 209 Service svc = new Service(Class.forName(args[0])); 210 for (Enumeration e = svc.getProviders(); e.hasMoreElements();) 211 System.out.println(e.nextElement().getClass().getName()); 212 } 213 } 214 | Popular Tags |