package co.forsaken.projectindigo.data;
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.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import co.forsaken.projectindigo.gui.ProgressPanel;
import co.forsaken.projectindigo.log.LogManager;
import co.forsaken.projectindigo.utils.FileUtils;
public class FileDownloader {
private Server server;
protected Thread _downloadThread;
protected String _rawDownloadURL;
protected String _baseDir = "";
protected boolean _extract = false;
protected File _downloadedFile;
protected int _fileSize = -1;
protected URL _downloadURL;
protected String overrideName;
protected boolean addToOrder;
protected HttpURLConnection connection;
public FileDownloader(Server server, String downloadURL, String dir, String filename, boolean _addToOrder) {
this(server, downloadURL, dir, _addToOrder);
overrideName = filename;
}
public FileDownloader(Server server, String downloadURL, String dir, boolean extract, boolean _addToOrder) {
this(server, downloadURL, dir, _addToOrder);
_extract = extract;
}
public FileDownloader(Server server, String downloadURL, String dir, boolean _addToOrder) {
_rawDownloadURL = downloadURL;
_baseDir = dir;
addToOrder = _addToOrder;
if (addToOrder) {
try {
server.addToOrder(getFilename());
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
public String getRawDownloadURL() {
return _rawDownloadURL;
}
public boolean shouldExtract() {
return _extract;
}
public boolean shouldDownload() {
return _rawDownloadURL != null && !_rawDownloadURL.isEmpty();
}
private HttpURLConnection getConnection() {
if (this.connection == null) {
LogManager.debug("Opening connection to " + getDownloadURL(), 3);
try {
connection = (HttpURLConnection) getDownloadURL().openConnection();
connection.setUseCaches(false);
connection.setDefaultUseCaches(false);
connection.setRequestProperty("Accept-Encoding", "gzip");
connection.setRequestProperty("User-Agent", "Mozilla/4.76");
connection.setRequestProperty("Cache-Control", "no-store,max-age=0,no-cache");
connection.setRequestProperty("Expires", "0");
connection.setRequestProperty("Pragma", "no-cache");
connection.connect();
if (this.connection.getResponseCode() / 100 != 2) { throw new IOException(getDownloadURL() + " returned response code " + this.connection.getResponseCode()
+ (this.connection.getResponseMessage() != null ? " with message of " + this.connection.getResponseMessage() : "")); }
LogManager.debug("Connection opened to " + getDownloadURL(), 3);
} catch (IOException e) {
LogManager.debug("Exception when opening connection to " + getDownloadURL(), 3);
}
}
return this.connection;
}
public Runnable loadFileSize(final Server server, final ProgressPanel panel) {
return new Runnable() {
public void run() {
if (_rawDownloadURL != null && !_rawDownloadURL.isEmpty()) {
try {
_fileSize = getFilesize();
server.addValidatedFile(panel, getFilename(), _fileSize, _extract);
} catch (IOException e) {
LogManager.error(e.getMessage());
}
}
}
};
}
public int getFilesize() {
if (_fileSize == -1) {
int size = getConnection().getContentLength();
if (size == -1) {
_fileSize = 0;
} else {
_fileSize = size;
}
}
return _fileSize;
}
protected String getFilename() throws MalformedURLException {
if (_rawDownloadURL != null && !_rawDownloadURL.isEmpty()) {
if (_rawDownloadURL.toLowerCase().contains("forge-")) { return "MinecraftForge.zip"; }
if (overrideName != null && !overrideName.isEmpty()) { return overrideName; }
String string = getDownloadURL().getFile();
if (string.contains("?")) {
string = string.substring(0, string.indexOf('?'));
}
return URLDecoder.decode(string.substring(string.lastIndexOf('/') + 1));
}
return "";
}
protected final URL getDownloadURL() {
if (_rawDownloadURL != null && !_rawDownloadURL.isEmpty()) {
if (_downloadURL == null) {
try {
_downloadURL = new URL(_rawDownloadURL);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
return _downloadURL;
}
return null;
}
public Runnable download(final Server server, final ProgressPanel panel) throws IOException {
return new Runnable() {
public void run() {
if (_rawDownloadURL != null && !_rawDownloadURL.isEmpty()) {
downloadFile(server, panel);
}
}
};
}
protected String getFileExtension() {
try {
String[] filename = getFilename().split(".");
return filename[filename.length - 1];
} catch (MalformedURLException e) {
e.printStackTrace();
}
return "jar";
}
private boolean downloadFile(Server server, ProgressPanel panel) {
HttpURLConnection dlConnection = null;
int currentDLSize = 0;
String jarFileName = null;
try {
jarFileName = getFilename();
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
File downloadedFile = new File(_baseDir, jarFileName);
try {
LogManager.info("Downloading " + jarFileName + " to \"" + _baseDir + "\"");
if (!new File(_baseDir).exists()) {
new File(_baseDir).mkdir();
}
dlConnection = getConnection();
if (downloadedFile.exists()) {
FileUtils.deleteDirectory(downloadedFile);
}
InputStream dlStream = dlConnection.getInputStream();
FileOutputStream outStream = new FileOutputStream(downloadedFile);
byte[] buffer = new byte[24000];
int readLen;
while ((readLen = dlStream.read(buffer, 0, buffer.length)) != -1) {
outStream.write(buffer, 0, readLen);
currentDLSize += readLen;
server.addDownloadSize(panel, "Downloading", jarFileName, readLen);
}
dlStream.close();
outStream.close();
} catch (IOException ex) {
LogManager.error("There was an exception while downloading " + jarFileName + "");
LogManager.error("Exception: " + ex.getMessage());
StackTraceElement[] arrOfSTE;
int max = (arrOfSTE = ex.getStackTrace()).length;
for (int i = 0; i < max; i++) {
StackTraceElement trace = arrOfSTE[i];
LogManager.error(trace.toString());
}
return false;
}
if (dlConnection != null && dlConnection instanceof HttpURLConnection && (currentDLSize == _fileSize || _fileSize <= 0)) {
LogManager.info("Finished downloading " + jarFileName);
_downloadedFile = downloadedFile;
if (shouldExtract()) {
extract(server, panel);
}
server.addLoadedDownload();
return true;
}
LogManager.info("Could not finish downloading " + jarFileName);
return false;
}
public void extract(Server server, ProgressPanel panel) {
if (_downloadedFile == null) { return; }
LogManager.info("Extracting " + _downloadedFile.getName() + " to \"" + _baseDir + "\"");
if (_downloadedFile.getName().contains("minecraft.jar")) {
extractJar(server, panel, true);
} else {
extractZip(server, panel, true);
}
LogManager.info("Extracting " + _downloadedFile.getName() + " to \"" + _baseDir + "\"");
}
protected void extractZip(Server server, ProgressPanel panel, boolean overwrite) {
ZipInputStream zipinputstream = null;
try {
byte[] buf = new byte[1024];
zipinputstream = new ZipInputStream(new FileInputStream(_downloadedFile));
ZipEntry zipentry = zipinputstream.getNextEntry();
while (zipentry != null) {
String entryName = zipentry.getName();
if (entryName.startsWith("config/") || entryName.startsWith("minecraft/")) {
entryName = entryName.substring(entryName.indexOf("/"));
}
int n;
if (!zipentry.isDirectory() && !entryName.contains("META-INF") && !entryName.contains("__MACOSX") && !entryName.contains(".DS_Store") && !entryName.equalsIgnoreCase("minecraft") && !entryName.equalsIgnoreCase(".minecraft")
&& !entryName.equalsIgnoreCase("instMods")) {
new File(_baseDir + File.separator + entryName).getParentFile().mkdirs();
FileOutputStream fileoutputstream = new FileOutputStream(_baseDir + File.separator + entryName);
while ((n = zipinputstream.read(buf, 0, 1024)) > -1) {
fileoutputstream.write(buf, 0, n);
server.addDownloadSize(panel, "Extracting", getFilename(), n);
}
fileoutputstream.close();
}
zipinputstream.closeEntry();
zipentry = zipinputstream.getNextEntry();
}
} catch (Exception e) {
LogManager.error("Error while extracting zip");
} finally {
try {
zipinputstream.close();
} catch (IOException e) {}
}
LogManager.info("Finished Extracting " + _downloadedFile.getName() + " to \"" + _baseDir + "\"");
_downloadedFile.delete();
}
protected boolean extractJar(Server server, ProgressPanel panel, boolean overwrite) {
File tmpFile = new File(_downloadedFile.getAbsolutePath() + ".tmp");
try {
JarInputStream input = new JarInputStream(new FileInputStream(_downloadedFile));
JarOutputStream output = new JarOutputStream(new FileOutputStream(tmpFile));
JarEntry entry;
while ((entry = input.getNextJarEntry()) != null) {
if (entry.getName().contains("META-INF") || entry.getName().contains("__MACOSX") || entry.getName().contains(".DS_Store")) {
continue;
}
output.putNextEntry(entry);
byte buffer[] = new byte[1024];
int readLen;
while ((readLen = input.read(buffer, 0, 1024)) != -1) {
output.write(buffer, 0, readLen);
server.addDownloadSize(panel, "Extracting", getFilename(), readLen);
}
output.closeEntry();
}
input.close();
output.close();
if (!_downloadedFile.delete()) {
LogManager.error("Failed to delete " + _downloadedFile.getName());
return false;
}
tmpFile.renameTo(_downloadedFile);
} catch (FileNotFoundException e) {
LogManager.error(e.getMessage());
return false;
} catch (IOException e) {
LogManager.error(e.getMessage());
return false;
}
LogManager.info("Finished Extracting " + _downloadedFile.getName() + " to \"" + _baseDir + "\"");
return true;
}
public boolean delete() throws MalformedURLException {
return FileUtils.deleteDirectory(new File(_baseDir, getFilename()));
}
}