package net.ayld.facade.bundle.impl;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import net.ayld.facade.bundle.JarExploder;
import net.ayld.facade.component.ListenableComponent;
import net.ayld.facade.event.model.JarExtractionStartEvent;
import net.ayld.facade.exception.ExtractionException;
import net.ayld.facade.model.ExplodedJar;
import net.ayld.facade.util.Tokenizer;
import net.ayld.facade.util.annotation.ThreadSafe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Required;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
@ThreadSafe
public class ManualJarExploder extends ListenableComponent implements JarExploder{
private static final Logger LOG = LoggerFactory.getLogger(ManualJarExploder.class);
private String workDir;
@Override
public Set<ExplodedJar> explode(Set<JarFile> jars) throws IOException {
final Set<ExplodedJar> result = Sets.newHashSet();
for (JarFile jar : jars) {
result.add(explode(jar));
}
return ImmutableSet.copyOf(result);
}
@Override
public ExplodedJar explode(JarFile jar) throws IOException {// XXX huge jumbo method
eventBus.post(new JarExtractionStartEvent("extracting: " + jar.getName() + ", to: " + workDir, this.getClass()));
final String jarName = Tokenizer.delimiter(File.separator).tokenize(jar.getName()).lastToken();
final String jarPath = Joiner.on(File.separator).join(workDir, jarName);
final File jarDir = new File(jarPath);
for (Enumeration<JarEntry> entries = jar.entries(); entries.hasMoreElements();) {
final JarEntry entry = entries.nextElement();
final String entryFilename = Joiner.on(File.separator).join(jarDir.getAbsolutePath(), entry.getName());
if (entry.isDirectory()) {
final File dirEntry = new File(entryFilename);
if (!dirEntry.exists() && !dirEntry.mkdirs()) {
throw new ExtractionException("could not create directory: " + dirEntry + ", contained in jar: " + jarName);
}
}
else {
final File fileEntry = new File(entryFilename);
if (!fileEntry.getParentFile().exists() && !fileEntry.getParentFile().mkdirs()) {
throw new ExtractionException("could not create: " + fileEntry + ", contained in jar: " + jarName);
}
explode(jar, entry, fileEntry);
}
}
return new ExplodedJar(jarPath, jar);
}
private static void explode(JarFile source, JarEntry content, File destination) throws IOException {
InputStream jarInputStream = null;
FileOutputStream classOutputStream = null;
try {
jarInputStream = source.getInputStream(content);
classOutputStream = new FileOutputStream(destination);
while (jarInputStream.available() > 0) {
classOutputStream.write(jarInputStream.read());
}
} finally {
if (jarInputStream != null) {
jarInputStream.close();
}
if (classOutputStream != null) {
classOutputStream.close();
}
}
}
@Required
public void setWorkDir(String workDir) {
final File dir = new File(workDir);
if (!dir.mkdirs()) {
LOG.warn("Unable to create working dir : {}", dir.getAbsoluteFile());
}
if (!dir.isDirectory()) {
throw new IllegalArgumentException("path " + workDir + ", is not a directory");
}
if (workDir.endsWith(File.separator)) {
workDir = workDir.replaceFirst(File.separator + "$", ""); // XXX remove last / if present
}
this.workDir = workDir;
}
}