package io.takari.maven.plugins.sisu;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Component;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation;
import com.google.common.base.Charsets;
import io.takari.incrementalbuild.Output;
import io.takari.incrementalbuild.aggregator.AggregatorBuildContext;
import io.takari.incrementalbuild.aggregator.InputSet;
import io.takari.incrementalbuild.aggregator.MetadataAggregator;
import io.takari.maven.plugins.TakariLifecycleMojo;
abstract class AbstractSisuIndexMojo extends TakariLifecycleMojo {
@Component
private AggregatorBuildContext context;
@Override
protected void executeMojo() throws MojoExecutionException {
try {
InputSet inputs = context.newInputSet();
inputs.addInputs(getOutputDirectory(), Collections.singleton("**/*.class"), null);
inputs.aggregateIfNecessary(getOutputFile(), new MetadataAggregator<String>() {
@Override
public Map<String, String> glean(File input) throws IOException {
return gleanNamedType(input);
}
@Override
public void aggregate(Output<File> output, Map<String, String> metadata) throws IOException {
writeIndex(output, metadata.keySet());
}
});
} catch (IOException e) {
throw new MojoExecutionException("Could not create sisu index " + getOutputFile(), e);
}
}
void writeIndex(Output<File> output, Set<String> types) throws IOException {
TreeSet<String> sorted = new TreeSet<>(types);
try (BufferedWriter w = new BufferedWriter(new OutputStreamWriter(output.newOutputStream(), Charsets.UTF_8))) {
for (String type : sorted) {
w.write(type);
w.newLine();
}
}
}
Map<String, String> gleanNamedType(File classfile) throws IOException {
// use jdt class reader to avoid extra runtime dependency, otherwise could use asm
try {
ClassFileReader type = ClassFileReader.read(classfile);
IBinaryAnnotation[] annotations = type.getAnnotations();
if (annotations != null) {
for (IBinaryAnnotation annotation : annotations) {
if ("Ljavax/inject/Named;".equals(new String(annotation.getTypeName()))) {
return Collections.singletonMap(new String(type.getName()).replace('/', '.'), null);
}
}
}
} catch (ClassFormatException e) {
// silently ignore classes we can't read/parse
}
return null;
}
protected abstract File getOutputDirectory();
protected abstract File getOutputFile();
}