package aQute.bnd.maven.indexer.plugin; import static java.util.Arrays.asList; import static org.apache.maven.plugins.annotations.LifecyclePhase.PROCESS_RESOURCES; import java.io.File; import java.net.URI; import java.nio.file.Path; import java.util.HashSet; import java.util.Set; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import aQute.bnd.osgi.repository.ResourcesRepository; import aQute.bnd.osgi.repository.XMLResourceGenerator; import aQute.bnd.osgi.resource.ResourceBuilder; import aQute.lib.io.IO; /** * Exports project dependencies to OSGi R5 index format. */ @Mojo(name = "local-index", defaultPhase = PROCESS_RESOURCES) public class LocalIndexerMojo extends AbstractMojo { private static final Logger logger = LoggerFactory.getLogger(LocalIndexerMojo.class); @Parameter(property = "bnd.indexer.input.dir", required=true) private File inputDir; @Parameter(property = "bnd.indexer.output.file", defaultValue = "${project.build.directory}/index.xml") private File outputFile; @Parameter(property = "bnd.indexer.base.file") private File baseFile; @Parameter(property = "bnd.indexer.include.gzip", defaultValue = "true") private boolean includeGzip; @Parameter(property = "bnd.indexer.skip", defaultValue = "false") private boolean skip; private boolean fail; public void execute() throws MojoExecutionException, MojoFailureException { if ( skip ) { logger.debug("skip project as configured"); return; } if(baseFile == null) { baseFile = outputFile.getParentFile(); } logger.debug("Indexing dependencies in folder: {}", inputDir.getAbsolutePath()); logger.debug("Outputting index to: {}", outputFile.getAbsolutePath()); logger.debug("Producing additional gzip index: {}", includeGzip); logger.debug("URI paths will be relative to: {}", baseFile); Set<File> toIndex = new HashSet<>(); toIndex.addAll(asList(inputDir.listFiles())); BaseFileURLResolver baseFileURLResolver = new BaseFileURLResolver(); ResourcesRepository resourcesRepository = new ResourcesRepository(); XMLResourceGenerator xmlResourceGenerator = new XMLResourceGenerator(); for (File file : toIndex) { ResourceBuilder resourceBuilder = new ResourceBuilder(); try { resourceBuilder.addFile(file, baseFileURLResolver.resolver(file)); } catch (Exception e) { throw new MojoExecutionException(e.getMessage(), e); } resourcesRepository.add(resourceBuilder.build()); } try { IO.mkdirs(outputFile.getParentFile()); xmlResourceGenerator.repository(resourcesRepository).save(outputFile); } catch (Exception e) { throw new MojoExecutionException(e.getMessage(), e); } if (fail) { throw new MojoExecutionException("One or more URI lookups failed"); } if (includeGzip) { File gzipOutputFile = new File(outputFile.getPath() + ".gz"); try { xmlResourceGenerator.save(gzipOutputFile); } catch (Exception e) { throw new MojoExecutionException("Unable to create the gzipped output file"); } } } class BaseFileURLResolver { public URI resolver(File file) throws Exception { try { logger.debug("Resolving {} relative to {}", file.getAbsolutePath(), baseFile.getAbsolutePath()); Path relativePath = baseFile.getAbsoluteFile().toPath().relativize(file.getAbsoluteFile().toPath()); logger.debug("Relative Path is: {}", relativePath); // Note that relativePath.toURI() gives the wrong answer for us! // We have to do some Windows related mashing here too :( URI relativeURI = URI.create(relativePath.toString().replace(File.separatorChar, '/')); logger.debug("Relative URI is: {}", relativeURI); return relativeURI; } catch (Exception e) { logger.error("Exception resolving URI", e); fail = true; throw e; } } } }