1 29 package net.sourceforge.groboutils.util.classes.v1; 30 31 import java.util.Properties ; 32 import java.util.Enumeration ; 33 import java.util.NoSuchElementException ; 34 35 import java.net.URL ; 36 37 import java.io.IOException ; 38 import java.io.InputStream ; 39 40 import org.apache.log4j.Logger; 41 42 43 65 public class SPILoader 66 { 67 private static final Logger LOG = Logger.getLogger( 68 SPILoader.class.getName() ); 69 70 71 74 private Enumeration spiUrls; 75 76 79 private Enumeration propKeys = null; 80 81 private String nextKey = null; 82 83 private Class base; 84 85 private ClassLoadHelper clh; 86 87 88 97 public SPILoader( Class spiBase ) 98 throws IOException 99 { 100 this( spiBase, null ); 101 } 102 103 104 117 public SPILoader( Class spiBase, ClassLoader cl ) 118 throws IOException 119 { 120 if (spiBase == null) 121 { 122 throw new IllegalArgumentException ("spiBase cannot be null."); 123 } 124 125 126 if (cl == null) 127 { 128 this.clh = new ClassLoadHelper( spiBase ); 129 } 130 else 131 { 132 this.clh = new ClassLoadHelper( cl ); 133 } 134 135 String metaName = "/META-INF/services/" + spiBase.getName(); 136 137 this.spiUrls = this.clh.getResources( metaName ); 138 if (this.spiUrls == null) 139 { 140 throw new IOException ("No URLs were discovered."); 141 } 142 this.base = spiBase; 143 } 144 145 146 152 public boolean hasNext() 153 throws IOException 154 { 155 while (this.nextKey == null) 156 { 157 if (this.propKeys == null || !this.propKeys.hasMoreElements()) 158 { 159 if (!this.spiUrls.hasMoreElements()) 160 { 161 LOG.debug("No more URLs to process"); 162 return false; 163 } 164 URL url = (URL )this.spiUrls.nextElement(); 165 LOG.debug( "Processing next URL: "+url ); 166 Properties props = new Properties (); 167 LOG.debug( "Opening URL stream" ); 168 InputStream is = url.openStream(); 169 try 170 { 171 props.load( is ); 172 } 173 finally 174 { 175 is.close(); 176 } 177 this.propKeys = props.keys(); 178 LOG.debug( "URL contains "+props.size()+" class names" ); 179 } 180 else 181 { 182 this.nextKey = (String )this.propKeys.nextElement(); 183 LOG.debug( "Next classname is "+this.nextKey ); 184 } 185 } 186 return true; 187 } 188 189 190 202 public Object nextProvier() 203 throws IOException 204 { 205 hasNext(); 207 208 if (this.nextKey == null) 209 { 210 throw new NoSuchElementException ( "end of list" ); 212 } 213 String cn = this.nextKey; 214 215 this.nextKey = null; 217 218 Object o; 219 try 220 { 221 o = this.clh.createObject( cn ); 222 } 223 catch (IllegalStateException ise) 224 { 225 LOG.info( "create object for type "+cn+" threw exception.", ise ); 226 throw new IOException ( ise.getMessage() ); 227 } 228 229 if (o == null) 230 { 231 LOG.info( "create object for type "+cn+" returned null." ); 232 throw new IOException ( "Could not create an instance of type "+ 233 cn ); 234 } 235 236 if (!this.base.isInstance( o )) 237 { 238 throw new IOException ( "SPI defined class "+cn+ 239 ", but expected class of type "+this.base.getName() ); 240 } 241 return o; 242 } 243 } 244 245 | Popular Tags |