com.athaydes.osgiaas.javac.internal.compiler.OsgiaasClassLoader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of osgiaas-javac Show documentation
Show all versions of osgiaas-javac Show documentation
OSGiaaS Javac Runtime Compiler
package com.athaydes.osgiaas.javac.internal.compiler;
import com.athaydes.osgiaas.api.env.ClassLoaderContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.tools.JavaFileObject;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.athaydes.osgiaas.javac.internal.CompilerUtils.classNameFromPath;
import static com.athaydes.osgiaas.javac.internal.CompilerUtils.packageOf;
/**
* Implementation of {@link ClassLoaderContext} for use within OSGi.
*/
final class OsgiaasClassLoader extends ClassLoader
implements ClassLoaderContext {
private static final Logger logger = LoggerFactory.getLogger( OsgiaasClassLoader.class );
private final Map fileByClassName = new HashMap<>();
private final Map> filesByPackage = new HashMap<>();
private final ClassLoaderContext classLoaderContext;
OsgiaasClassLoader( final ClassLoaderContext classLoaderContext ) {
super( classLoaderContext.getClassLoader() );
this.classLoaderContext = classLoaderContext;
}
Collection filesIn( String packageName ) {
Stream compiledClasses = fileByClassName.entrySet().stream()
.filter( entry -> packageOf( entry.getKey() ).equals( packageName ) )
.map( Map.Entry::getValue );
Collection classLoaderClasses = filesByPackage
.computeIfAbsent( packageName, this::computeClassesIn );
return Stream.concat( compiledClasses, classLoaderClasses.stream() )
.collect( Collectors.toSet() );
}
private Collection computeClassesIn( String packageName ) {
logger.debug( "Computing classes in package {}", packageName );
return classLoaderContext.getClassesIn( packageName ).stream()
.map( path -> loadBytecodeFrom(
new OsgiaasFileObject( classNameFromPath( path ), JavaFileObject.Kind.CLASS ),
classLoaderContext.getInputStream( path ) ) )
.collect( Collectors.toList() );
}
private static JavaFileObject loadBytecodeFrom( OsgiaasFileObject file, InputStream input ) {
byte[] buffer = new byte[ 4096 ];
int len;
try ( OutputStream out = file.openOutputStream() ) {
while ( ( len = input.read( buffer ) ) != -1 ) {
out.write( buffer, 0, len );
}
} catch ( IOException e ) {
logger.warn( "Problem loading bytecode for {}: {}", file, e );
throw new RuntimeException( e );
} finally {
try {
input.close();
} catch ( IOException e ) {
e.printStackTrace();
}
}
return file;
}
// expose publicly
@Override
public Class> loadClass( String name, boolean resolve ) throws ClassNotFoundException {
try {
return super.loadClass( name, resolve );
} catch ( ClassNotFoundException e ) {
return classLoaderContext.getClassLoader().loadClass( name );
}
}
@Override
protected Class> findClass( String qualifiedClassName )
throws ClassNotFoundException {
OsgiaasFileObject file = fileByClassName.get( qualifiedClassName );
if ( file != null ) {
byte[] bytes = file.getByteCode();
return defineClass( qualifiedClassName, bytes, 0, bytes.length );
}
return super.findClass( qualifiedClassName );
}
void add( String qualifiedClassName, OsgiaasFileObject javaFile ) {
fileByClassName.put( qualifiedClassName, javaFile );
}
@Override
public InputStream getResourceAsStream( String name ) {
if ( name.endsWith( ".class" ) ) {
String qualifiedClassName = name.substring( 0,
name.length() - ".class".length() ).replace( '/', '.' );
OsgiaasFileObject file = fileByClassName.get( qualifiedClassName );
if ( file != null ) {
return new ByteArrayInputStream( file.getByteCode() );
}
}
InputStream inputStream = super.getResourceAsStream( name );
if ( inputStream == null ) {
inputStream = classLoaderContext.getClassLoader().getResourceAsStream( name );
}
return inputStream;
}
@Override
public ClassLoader getClassLoader() {
return this;
}
@Override
public Collection getClassesIn( String packageName ) {
Collection classes = classLoaderContext.getClassesIn( packageName );
Set customClasses = fileByClassName.keySet();
Set result = new HashSet<>( classes.size() + customClasses.size() );
result.addAll( classes );
result.addAll( customClasses );
return result;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy