diff --git a/src/main/java/com/threerings/getdown/util/FileUtil.java b/src/main/java/com/threerings/getdown/util/FileUtil.java index 51a8353..d14de11 100644 --- a/src/main/java/com/threerings/getdown/util/FileUtil.java +++ b/src/main/java/com/threerings/getdown/util/FileUtil.java @@ -10,19 +10,23 @@ import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.Deque; +import java.util.Enumeration; import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; import java.util.jar.JarOutputStream; import java.util.jar.Pack200; import java.util.zip.GZIPInputStream; import com.samskivert.io.StreamUtil; +import com.samskivert.util.Logger; import static com.threerings.getdown.Log.log; /** * File related utilities. */ -public class FileUtil extends com.samskivert.util.FileUtil +public class FileUtil { /** * Gets the specified source file to the specified destination file by hook or crook. Windows @@ -96,11 +100,63 @@ public class FileUtil extends com.samskivert.util.FileUtil return lines; } + /** + * Unpacks the specified jar file intto the specified target directory. + */ + public static void unpackJar (JarFile jar, File target) throws IOException + { + try { + Enumeration entries = jar.entries(); + while (entries.hasMoreElements()) { + JarEntry entry = (JarEntry)entries.nextElement(); + File efile = new File(target, entry.getName()); + + // if we're unpacking a normal jar file, it will have special path + // entries that allow us to create our directories first + if (entry.isDirectory()) { + if (!efile.exists() && !efile.mkdir()) { + log.warning("Failed to create jar entry path", "jar", jar, "entry", entry); + } + continue; + } + + // but some do not, so we want to ensure that our directories exist + // prior to getting down and funky + File parent = new File(efile.getParent()); + if (!parent.exists() && !parent.mkdirs()) { + log.warning("Failed to create jar entry parent", "jar", jar, "parent", parent); + continue; + } + + BufferedOutputStream fout = null; + InputStream jin = null; + try { + fout = new BufferedOutputStream(new FileOutputStream(efile)); + jin = jar.getInputStream(entry); + StreamUtil.copy(jin, fout); + } catch (Exception e) { + throw new IOException( + Logger.format("Failure unpacking", "jar", jar, "entry", efile), e); + } finally { + StreamUtil.close(jin); + StreamUtil.close(fout); + } + } + + } finally { + try { + jar.close(); + } catch (Exception e) { + log.warning("Failed to close jar file", "jar", jar, "error", e); + } + } + } + /** * Unpacks a pack200 packed jar file from {@code packedJar} into {@code target}. If {@code * packedJar} has a {@code .gz} extension, it will be gunzipped first. */ - public static boolean unpackPacked200Jar (File packedJar, File target) + public static void unpackPacked200Jar (File packedJar, File target) throws IOException { InputStream packedJarIn = null; FileOutputStream extractedJarFileOut = null; @@ -114,11 +170,6 @@ public class FileUtil extends com.samskivert.util.FileUtil } Pack200.Unpacker unpacker = Pack200.newUnpacker(); unpacker.unpack(packedJarIn, jarOutputStream); - return true; - - } catch (IOException e) { - log.warning("Failed to unpack packed 200 jar file", "jar", packedJar, "error", e); - return false; } finally { StreamUtil.close(jarOutputStream); diff --git a/src/test/java/com/threerings/getdown/classpath/ClassPathsTest.java b/src/test/java/com/threerings/getdown/classpath/ClassPathsTest.java index 956585a..9b3c2a7 100644 --- a/src/test/java/com/threerings/getdown/classpath/ClassPathsTest.java +++ b/src/test/java/com/threerings/getdown/classpath/ClassPathsTest.java @@ -13,9 +13,9 @@ import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import static org.mockito.Mockito.when; +import com.samskivert.util.FileUtil; import com.threerings.getdown.data.Application; import com.threerings.getdown.data.Resource; -import com.threerings.getdown.util.FileUtil; @RunWith(MockitoJUnitRunner.class) public class ClassPathsTest