trip.spi.helpers.LazyClassReader Maven / Gradle / Ivy
package trip.spi.helpers;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.ServiceConfigurationError;
import lombok.Cleanup;
import lombok.Getter;
@Getter
public class LazyClassReader implements Iterator> {
private static final String PREFIX = "META-INF/services/";
private static final int NOT_FOUND = -1;
final List> cache = new ArrayList>();
final String serviceClassCanonicalName;
final ClassLoader loader;
final Enumeration resources;
Iterator currentResourceLines;
public LazyClassReader( final Class serviceClass, final ClassLoader loader ) {
this( serviceClass.getCanonicalName(), loader );
}
public LazyClassReader(
final String serviceClassCanonicalName,
final ClassLoader loader ) {
this.serviceClassCanonicalName = serviceClassCanonicalName;
this.loader = loader;
this.resources = readAllServiceResources();
}
Enumeration readAllServiceResources() {
try {
final String fullName = PREFIX + serviceClassCanonicalName;
return loader.getResources( fullName );
} catch ( final IOException cause ) {
throw new ServiceConfigurationError( serviceClassCanonicalName + ": " + cause.getMessage(), cause );
}
}
@Override
public boolean hasNext() {
try {
if ( currentResourceLines == null || !currentResourceLines.hasNext() )
readNextResourceFile();
return currentResourceLines != null && currentResourceLines.hasNext();
} catch ( final FileNotFoundException cause ) {
return false;
} catch ( final IOException cause ) {
throw new IllegalStateException( cause );
}
}
void readNextResourceFile() throws IOException {
if ( getResources().hasMoreElements() ) {
final URL nextElement = getResources().nextElement();
currentResourceLines = readLines( nextElement );
}
}
@Override
@SuppressWarnings( "unchecked" )
public Class next() {
final String classCanonicalName = currentResourceLines.next();
try {
final Class clazz = (Class)Class.forName( classCanonicalName, false, loader );
cache.add( clazz );
return clazz;
} catch ( final ClassNotFoundException cause ) {
throw new IllegalStateException( "Could not read class " + classCanonicalName, cause );
} catch ( final NoClassDefFoundError cause ) {
throw new IllegalStateException( "Could not read class " + classCanonicalName, cause );
}
}
@Override
public void remove() {
}
Iterator readLines( final URL url ) throws IOException {
@Cleanup final InputStream inputStream = url.openStream();
@Cleanup final BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream, "utf-8" ) );
final List lines = new ArrayList();
String line = null;
while ( ( line = readNextLine( reader ) ) != null )
lines.add( line );
return lines.iterator();
}
String readNextLine( final BufferedReader reader ) throws IOException {
final String ln = reader.readLine();
if ( ln != null && !isValidClassName( ln ) )
throw new IOException( "Invalid class name: " + ln );
return ln;
}
boolean isValidClassName( final String className ) {
return className.indexOf( ' ' ) == NOT_FOUND
&& className.indexOf( '\t' ) == NOT_FOUND;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy