package mandelbrot.ocamljava_maven_plugin.util; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Collection; import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarInputStream; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; import org.apache.maven.plugin.AbstractMojo; import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.base.Splitter; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; public class JarAppender { public static int BUFFER_SIZE = 10240; private final AbstractMojo abstractMojo; public JarAppender(final AbstractMojo abstractMojo) { this.abstractMojo = Preconditions.checkNotNull(abstractMojo); } public void addFiles(final String archiveFile, final Collection<String> toBeJaredFiles, final String prefixToFilter) { final Collection<File> toBeJaredArray = Collections2.transform( toBeJaredFiles, new Function<String, File>() { @Override public File apply(final String path) { return new File(path); } }); try { final byte buffer[] = new byte[BUFFER_SIZE]; final JarEntryReader jarEntryReader = new JarEntryReader(abstractMojo); final Collection<EntryInfo> entryInfos = jarEntryReader.readEntries(archiveFile, buffer); writeEntryInfos(entryInfos, archiveFile, prefixToFilter, toBeJaredArray, buffer, jarEntryReader.getManifest()); abstractMojo.getLog().info("Adding completed OK"); } catch (final Exception ex) { abstractMojo.getLog().error("Error: " + ex.getMessage(), ex); } } private void writeEntryInfos(Collection<EntryInfo> entryInfos, final String archiveFile, final String prefixToFilter, final Collection<File> toBeJaredArray, final byte[] buffer, final Optional<Manifest> manifest) throws IOException, FileNotFoundException { // Open archive file final FileOutputStream stream = new FileOutputStream(archiveFile); final JarOutputStream out = manifest.isPresent() ? new JarOutputStream(stream, manifest.get()) : new JarOutputStream(stream); for (final EntryInfo entryInfo : entryInfos) { out.putNextEntry(entryInfo.getJarEntry()); abstractMojo.getLog().info("Adding original entry: " + entryInfo.getJarEntry().getName()); pipe(out, buffer, new ByteArrayInputStream(entryInfo.getBytes())); } for (final File file : toBeJaredArray) { if (file == null || !file.exists() || file.isDirectory()) continue; // Just in case... abstractMojo.getLog().info("Adding new entry: " + file.getPath()); addEntry(file, out, buffer, prefixToFilter); } try { out.close(); } catch (final Exception e) {} try { stream.close(); } catch (final Exception e) {} } private void addEntry(final File file, final JarOutputStream out, final byte[] buffer, final String prefixToFilter) throws IOException { String substring = file.getPath(); if (prefixToFilter != null) { final List<String> split = ImmutableList.copyOf (Splitter.on(File.separator).split(Optional.fromNullable(prefixToFilter).or(""))); for (int k = 0; k < split.size();k++) { final String join = Joiner.on(File.separator).join(split.subList(k, split.size())); if (file.getPath().startsWith(join)) { substring = substring.substring(join.length(), substring.length()); break; } } } substring = StringTransforms.trim(substring, File.separator); abstractMojo.getLog().info("infered package: " + substring); final JarEntry jarAdd = new JarEntry(substring); jarAdd.setTime(file.lastModified()); out.putNextEntry(jarAdd); // Write file to archive final FileInputStream in = new FileInputStream(file); pipe(out, buffer, in); in.close(); } private void pipe(final OutputStream out, final byte[] buffer, final InputStream in) throws IOException { while (true) { final int nRead = in.read(buffer, 0, buffer.length); if (nRead <= 0) break; out.write(buffer, 0, nRead); } } public void appendEntries(final Collection<EntryInfo> entryInfos, final String targetJar) throws FileNotFoundException, IOException { final byte[] buffer = new byte[BUFFER_SIZE]; final JarInputStream jarInputStream = new JarInputStream(new FileInputStream(targetJar)); final Collection<EntryInfo> targetEntryInfos = new JarEntryReader(abstractMojo).readEntries(targetJar); try { writeEntryInfos(ImmutableSet.<EntryInfo>builder() .addAll(targetEntryInfos).addAll(entryInfos).build(), null, targetJar, ImmutableList.<File>of(), buffer, Optional.fromNullable(jarInputStream.getManifest())); } finally { jarInputStream.close(); } } }