diff --git a/src/main/java/net/md_5/specialsource/AccessMap.java b/src/main/java/net/md_5/specialsource/AccessMap.java index e2cd280..ff16e9b 100644 --- a/src/main/java/net/md_5/specialsource/AccessMap.java +++ b/src/main/java/net/md_5/specialsource/AccessMap.java @@ -28,6 +28,7 @@ */ package net.md_5.specialsource; +import net.md_5.specialsource.util.FileLocator; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; @@ -98,7 +99,7 @@ public class AccessMap { if (filename.startsWith("pattern:")) { addAccessChange(filename.substring("pattern:".length())); } else { - loadAccessTransformer(URLDownloader.getLocalFile(filename)); + loadAccessTransformer(FileLocator.getFile(filename)); } } diff --git a/src/main/java/net/md_5/specialsource/JarComparer.java b/src/main/java/net/md_5/specialsource/JarComparer.java index 5ebd484..96446ff 100644 --- a/src/main/java/net/md_5/specialsource/JarComparer.java +++ b/src/main/java/net/md_5/specialsource/JarComparer.java @@ -28,6 +28,7 @@ */ package net.md_5.specialsource; +import net.md_5.specialsource.util.NoDupeList; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.MethodVisitor; diff --git a/src/main/java/net/md_5/specialsource/JarMapping.java b/src/main/java/net/md_5/specialsource/JarMapping.java index a62af8d..b201e50 100644 --- a/src/main/java/net/md_5/specialsource/JarMapping.java +++ b/src/main/java/net/md_5/specialsource/JarMapping.java @@ -28,6 +28,7 @@ */ package net.md_5.specialsource; +import net.md_5.specialsource.util.FileLocator; import net.md_5.specialsource.transformer.MavenShade; import net.md_5.specialsource.writer.CompactSearge; import net.md_5.specialsource.writer.Searge; @@ -108,7 +109,7 @@ public class JarMapping { */ private void loadMappingsDir(String dirname, boolean reverse, boolean ignoreCsv, boolean numericSrgNames) throws IOException { File dir = new File(dirname); - if (!URLDownloader.isHTTPURL(dirname) && !dir.isDirectory()) { + if (!FileLocator.isHTTPURL(dirname) && !dir.isDirectory()) { throw new IllegalArgumentException("loadMappingsDir(" + dir + "): not a directory"); } @@ -116,14 +117,14 @@ public class JarMapping { List srgFiles = new ArrayList(); - File joinedSrg = URLDownloader.getLocalFile(dirname + sep + "joined.srg"); + File joinedSrg = FileLocator.getFile(dirname + sep + "joined.srg"); if (joinedSrg.exists()) { // FML/MCP client/server joined srgFiles.add(joinedSrg); } else { // vanilla MCP separated sides - File serverSrg = URLDownloader.getLocalFile(dirname + sep + "server.srg"); - File clientSrg = URLDownloader.getLocalFile(dirname + sep + "client.srg"); + File serverSrg = FileLocator.getFile(dirname + sep + "server.srg"); + File clientSrg = FileLocator.getFile(dirname + sep + "client.srg"); if (serverSrg.exists()) { srgFiles.add(serverSrg); } @@ -137,9 +138,9 @@ public class JarMapping { } // Read output names through csv mappings, if available & enabled - File fieldsCsv = URLDownloader.getLocalFile(dirname + sep + "fields.csv"); - File methodsCsv = URLDownloader.getLocalFile(dirname + sep + "methods.csv"); - File packagesCsv = URLDownloader.getLocalFile(dirname + sep + "packages.csv"); // FML repackaging, optional + File fieldsCsv = FileLocator.getFile(dirname + sep + "fields.csv"); + File methodsCsv = FileLocator.getFile(dirname + sep + "methods.csv"); + File packagesCsv = FileLocator.getFile(dirname + sep + "packages.csv"); // FML repackaging, optional MinecraftCodersPack outputTransformer; MappingTransformer inputTransformer; @@ -211,7 +212,7 @@ public class JarMapping { throw new IllegalArgumentException("loadMappings(" + filename + "): numeric only supported on directories, not files"); } - loadMappings(new BufferedReader(new FileReader(URLDownloader.getLocalFile(filename))), inputTransformer, outputTransformer, reverse); + loadMappings(new BufferedReader(new FileReader(FileLocator.getFile(filename))), inputTransformer, outputTransformer, reverse); } } diff --git a/src/main/java/net/md_5/specialsource/SpecialSource.java b/src/main/java/net/md_5/specialsource/SpecialSource.java index 2e0cfc9..39fab20 100644 --- a/src/main/java/net/md_5/specialsource/SpecialSource.java +++ b/src/main/java/net/md_5/specialsource/SpecialSource.java @@ -28,6 +28,8 @@ */ package net.md_5.specialsource; +import net.md_5.specialsource.util.Pair; +import net.md_5.specialsource.util.FileLocator; import net.md_5.specialsource.provider.JointProvider; import net.md_5.specialsource.provider.JarProvider; import java.io.*; @@ -129,13 +131,13 @@ public class SpecialSource { JarMapping jarMapping; verbose = !options.has("quiet"); - URLDownloader.useCache = !options.has("force-redownload"); + FileLocator.useCache = !options.has("force-redownload"); if (options.has("first-jar") && options.has("second-jar")) { // Generate mappings from two otherwise-identical jars log("Reading jars"); - Jar jar1 = Jar.init(URLDownloader.getLocalFile((String) options.valueOf("first-jar"))); - Jar jar2 = Jar.init(URLDownloader.getLocalFile((String) options.valueOf("second-jar"))); + Jar jar1 = Jar.init(FileLocator.getFile((String) options.valueOf("first-jar"))); + Jar jar2 = Jar.init(FileLocator.getFile((String) options.valueOf("second-jar"))); log("Creating jar compare"); JarComparer visitor1 = new JarComparer(jar1); @@ -200,7 +202,7 @@ public class SpecialSource { List filenames = (List) options.valuesOf("in-jar"); List files = new ArrayList(); for (String filename : filenames) { - files.add(URLDownloader.getLocalFile(filename)); + files.add(FileLocator.getFile(filename)); } Jar jar3 = Jar.init(files); diff --git a/src/main/java/net/md_5/specialsource/URLDownloader.java b/src/main/java/net/md_5/specialsource/util/FileLocator.java similarity index 61% rename from src/main/java/net/md_5/specialsource/URLDownloader.java rename to src/main/java/net/md_5/specialsource/util/FileLocator.java index ceb1c91..5f1dce0 100644 --- a/src/main/java/net/md_5/specialsource/URLDownloader.java +++ b/src/main/java/net/md_5/specialsource/util/FileLocator.java @@ -26,31 +26,28 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -package net.md_5.specialsource; +package net.md_5.specialsource.util; import com.google.common.base.CharMatcher; import java.io.*; -import java.net.MalformedURLException; import java.net.URL; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import net.md_5.specialsource.SpecialSource; -public class URLDownloader { +public class FileLocator { - private static String CACHE_FOLDER = ".ss-cache"; - private URL url; public static boolean useCache = true; - public URLDownloader(String urlString) throws MalformedURLException { - urlString = urlString.replace('\\', '/'); // Windows paths to URLs - TODO: improve this in JarMapping directory loading - this.url = new URL(urlString); - } - - public File download() throws IOException { - // Cache to temporary directory - String sep = System.getProperty("file.separator"); + private static File download(String url) throws IOException { + // Create temporary dir in system location + File tempDir = File.createTempFile("ss-cache", null); + // Create our own cache file here, replacing potentially invalid characters + // TODO: Maybe just store the base name or something String id = CharMatcher.JAVA_LETTER_OR_DIGIT.or(CharMatcher.anyOf("-_.")).negate().replaceFrom(url.toString(), '_'); - String cacheFilename = System.getProperty("java.io.tmpdir") + sep + CACHE_FOLDER + sep + id; - File file = new File(cacheFilename); + File file = new File(tempDir, id); + // Check cache for a hit if (file.exists() && useCache) { if (SpecialSource.verbose()) { System.out.println("Using cached file " + file.getPath() + " for " + url); @@ -59,27 +56,28 @@ public class URLDownloader { return file; } - // Download - file.getParentFile().mkdirs(); + // Nope, we need to download it ourselves if (SpecialSource.verbose()) { System.out.println("Downloading " + url); } - url.openConnection(); - InputStream inputStream = url.openStream(); - - - FileOutputStream outputStream = new FileOutputStream(file); - - int n; - byte[] buffer = new byte[4096]; - while ((n = inputStream.read(buffer)) != -1) { - outputStream.write(buffer, 0, n); + ReadableByteChannel rbc = null; + FileOutputStream fos = null; + try { + // TODO: Better sollution for cleaning names + rbc = Channels.newChannel(new URL(url.replace('\\', '/')).openStream()); + fos = new FileOutputStream(file); + fos.getChannel().transferFrom(rbc, 0, 1 << 24); + } finally { + if (rbc != null) { + rbc.close(); + } + if (fos != null) { + fos.close(); + } } - inputStream.close(); - outputStream.close(); - + // Success! if (SpecialSource.verbose()) { System.out.println("Downloaded to " + file.getPath()); } @@ -87,13 +85,19 @@ public class URLDownloader { return file; } - public static File getLocalFile(String string) throws IOException { - if (isHTTPURL(string)) { - URLDownloader downloader = new URLDownloader(string); - return downloader.download(); - } else { - return new File(string); + /** + * Either download, or get a File object corresponding to the given URL / + * file name. + * + * @param path + * @return + * @throws IOException + */ + public static File getFile(String path) throws IOException { + if (isHTTPURL(path)) { + return download(path); } + return new File(path); } public static boolean isHTTPURL(String string) { diff --git a/src/main/java/net/md_5/specialsource/NoDupeList.java b/src/main/java/net/md_5/specialsource/util/NoDupeList.java similarity index 98% rename from src/main/java/net/md_5/specialsource/NoDupeList.java rename to src/main/java/net/md_5/specialsource/util/NoDupeList.java index e8939ca..e5cb744 100644 --- a/src/main/java/net/md_5/specialsource/NoDupeList.java +++ b/src/main/java/net/md_5/specialsource/util/NoDupeList.java @@ -26,7 +26,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -package net.md_5.specialsource; +package net.md_5.specialsource.util; import java.util.ArrayList; import java.util.HashSet; diff --git a/src/main/java/net/md_5/specialsource/Pair.java b/src/main/java/net/md_5/specialsource/util/Pair.java similarity index 98% rename from src/main/java/net/md_5/specialsource/Pair.java rename to src/main/java/net/md_5/specialsource/util/Pair.java index 83adefe..b1ffeae 100644 --- a/src/main/java/net/md_5/specialsource/Pair.java +++ b/src/main/java/net/md_5/specialsource/util/Pair.java @@ -26,7 +26,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -package net.md_5.specialsource; +package net.md_5.specialsource.util; import lombok.EqualsAndHashCode; import lombok.RequiredArgsConstructor;