package com.kokakiwi.mclauncher.core.updater;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import net.contrapunctus.lzma.LzmaInputStream;
import com.kokakiwi.mclauncher.api.LauncherAPI;
import com.kokakiwi.mclauncher.core.updater.UpdaterWorker.GameFile;
public class FileExtractor
{
public static boolean extract(LauncherAPI api, GameFile source, File dest,
int min, int max, boolean recursive) throws Exception
{
final String[] exts = source.getFileName()
.substring(source.getFileName().indexOf('.', 0) + 1)
.split("\\.");
File file = source.getFile();
for (int i = exts.length - 1; i > -1; i--)
{
final String ext = exts[i];
boolean pass = false;
if (ext.equalsIgnoreCase("lzma"))
{
file = extractLZMA(api, source, file, dest, min, max);
}
if (ext.equalsIgnoreCase("zip"))
{
extractZIP(api, source, file, dest, min, max);
pass = true;
}
if (ext.equalsIgnoreCase("jar"))
{
extractJAR(api, source, file, dest, min, max);
pass = true;
}
if (!recursive || pass)
{
i = -1;
}
}
return false;
}
public static File extractLZMA(LauncherAPI api, GameFile source, File file,
File dest, int min, int max) throws Exception
{
final File uncompressed = new File(dest, file.getName().substring(0,
file.getName().lastIndexOf('.')));
final FileInputStream fileInput = new FileInputStream(file);
InputStream in = new LzmaInputStream(fileInput);
OutputStream out = new FileOutputStream(uncompressed);
final byte[] buffer = new byte[16384];
int ret = in.read(buffer);
while (ret >= 1)
{
out.write(buffer, 0, ret);
ret = in.read(buffer);
}
in.close();
out.close();
in = null;
out = null;
return uncompressed;
}
@SuppressWarnings("unchecked")
public static void extractZIP(LauncherAPI api, GameFile source, File file,
File dest, int min, int max) throws Exception
{
final ZipFile zip = new ZipFile(file);
Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>) zip.entries();
int total = 0;
while (entries.hasMoreElements())
{
final ZipEntry entry = entries.nextElement();
if (!entry.isDirectory())
{
total += entry.getSize();
}
}
entries = (Enumeration<ZipEntry>) zip.entries();
final int current = 0;
while (entries.hasMoreElements())
{
final ZipEntry entry = entries.nextElement();
if (entry.isDirectory())
{
final File dir = new File(dest, entry.getName());
if (!dir.exists())
{
dir.mkdirs();
}
}
else
{
final File e = new File(dest, entry.getName());
copyStream(api, source, zip.getInputStream(entry),
new FileOutputStream(e), current, total, min, max);
}
}
zip.close();
}
public static void extractJAR(LauncherAPI api, GameFile source, File file,
File dest, int min, int max) throws Exception
{
JarFile jar = null;
try
{
jar = new JarFile(file);
}
catch (final IOException e)
{
e.printStackTrace();
}
Enumeration<JarEntry> entries = jar.entries();
int total = 0;
while (entries.hasMoreElements())
{
final JarEntry entry = entries.nextElement();
if (!entry.isDirectory()
&& !entry.getName().equalsIgnoreCase("MANIFEST.MF"))
{
total += entry.getSize();
}
}
entries = jar.entries();
final int current = 0;
while (entries.hasMoreElements())
{
final JarEntry entry = entries.nextElement();
if (entry.isDirectory())
{
final File dir = new File(dest, entry.getName());
if (!dir.exists()
&& !dir.getName().equalsIgnoreCase("META-INF"))
{
dir.mkdirs();
}
}
else
{
final File e = new File(dest, entry.getName());
if (!e.getParent().contains("META-INF"))
{
copyStream(api, source, jar.getInputStream(entry),
new FileOutputStream(e), current, total, min, max);
}
}
}
}
private static void copyStream(LauncherAPI api, GameFile source,
InputStream in, OutputStream out, int current, int total, int min,
int max) throws Exception
{
copyStream(api, source, in, out, current, total, min, max, 65536);
}
private static void copyStream(LauncherAPI api, GameFile source,
InputStream in, OutputStream out, int current, int total, int min,
int max, int bufferLength) throws Exception
{
final byte[] buffer = new byte[bufferLength];
int bufferSize;
while ((bufferSize = in.read(buffer, 0, buffer.length)) != -1)
{
out.write(buffer, 0, bufferSize);
current += bufferSize;
source.setPercentage(current * 100 / total);
api.getUpdater().setPercentage(min + current * (max - min) / total);
}
in.close();
out.close();
}
}