diff --git a/build.gradle b/build.gradle index 77cead8..dcb9389 100644 --- a/build.gradle +++ b/build.gradle @@ -51,13 +51,18 @@ tasks.withType(Jar) { doFirst { // Jar files with an appendix are standalone applications and need to have ShrinkIt included. if (appendix) { - from { configurations.runtime.collect { it.name.startsWith('ShrinkItArchive') ? zipTree(it) : 'fake' } } + from { + configurations.runtime.collect { + it.name.startsWith('ShrinkItArchive') || it.name.startsWith('applesingle-api') ? zipTree(it) : 'fake' + } + } } } } dependencies { compile "net.sf.applecommander:ShrinkItArchive:$shkVersion" + compile "net.sf.applecommander:applesingle-api:$asVersion" compileOnly "org.apache.ant:ant:$antVersion" testCompile "junit:junit:$junitVersion" diff --git a/gradle.properties b/gradle.properties index 8beae86..03f8f28 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,6 +5,7 @@ version=1.5.0-BETA # Dependency versions shkVersion=1.2.2 +asVersion=1.0.0 swtVersion=4.6.1 junitVersion=4.12 antVersion=1.8.2 diff --git a/src/main/java/com/webcodepro/applecommander/ui/ac.java b/src/main/java/com/webcodepro/applecommander/ui/ac.java index 5e26b2f..e842dc0 100644 --- a/src/main/java/com/webcodepro/applecommander/ui/ac.java +++ b/src/main/java/com/webcodepro/applecommander/ui/ac.java @@ -50,8 +50,6 @@ import com.webcodepro.applecommander.storage.physical.ByteArrayImageLayout; import com.webcodepro.applecommander.storage.physical.DosOrder; import com.webcodepro.applecommander.storage.physical.ImageOrder; import com.webcodepro.applecommander.storage.physical.ProdosOrder; -import com.webcodepro.applecommander.util.AppleSingle; -import com.webcodepro.applecommander.util.AppleSingle.ProdosFileInfo; import com.webcodepro.applecommander.util.AppleUtil; import com.webcodepro.applecommander.util.StreamUtil; import com.webcodepro.applecommander.util.TextBundle; @@ -60,6 +58,9 @@ import com.webcodepro.applecommander.util.applesoft.Program; import com.webcodepro.applecommander.util.applesoft.Token; import com.webcodepro.applecommander.util.applesoft.TokenReader; +import io.github.applecommander.applesingle.AppleSingle; +import io.github.applecommander.applesingle.ProdosFileInfo; + /** * ac provides a command line interface to key AppleCommander functions. Text * similar to this is produced in response to the -h option. @@ -331,7 +332,7 @@ public class ac { public static void putAppleSingle(String imageName, String fileName, InputStream inputStream) throws IOException, DiskException { - AppleSingle as = new AppleSingle(inputStream); + AppleSingle as = AppleSingle.read(inputStream); if (fileName == null) { fileName = as.getRealName(); } diff --git a/src/main/java/com/webcodepro/applecommander/util/AppleSingle.java b/src/main/java/com/webcodepro/applecommander/util/AppleSingle.java deleted file mode 100644 index edc4acb..0000000 --- a/src/main/java/com/webcodepro/applecommander/util/AppleSingle.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.webcodepro.applecommander.util; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.file.Files; -import java.nio.file.Paths; - -/** - * Support reading of data from and AppleSingle source. - * Does not implement all components at this time, extend as required. - * - * @see AppleCommander issue #20 - */ -public class AppleSingle { - public static final int MAGIC_NUMBER = 0x0051600; - public static final int VERSION_NUMBER = 0x00020000; - - private byte[] dataFork; - private byte[] resourceFork; - private String realName; - private ProdosFileInfo prodosFileInfo; - - public AppleSingle(String filename) throws IOException { - byte[] fileData = Files.readAllBytes(Paths.get(filename)); - load(fileData); - } - public AppleSingle(InputStream stream) throws IOException { - ByteArrayOutputStream os = new ByteArrayOutputStream(); - StreamUtil.copy(stream, os); - os.flush(); - load(os.toByteArray()); - } - - private void load(byte[] fileData) throws IOException { - ByteBuffer buffer = ByteBuffer.wrap(fileData) - .order(ByteOrder.BIG_ENDIAN) - .asReadOnlyBuffer(); - required(buffer, MAGIC_NUMBER, "Not an AppleSingle file - magic number does not match."); - required(buffer, VERSION_NUMBER, "Only AppleSingle version 2 supported."); - buffer.position(buffer.position() + 16); // Skip filler - int entries = buffer.getShort(); - for (int i = 0; i < entries; i++) { - int entryId = buffer.getInt(); - int offset = buffer.getInt(); - int length = buffer.getInt(); - buffer.mark(); - buffer.position(offset); - byte[] entryData = new byte[length]; - buffer.get(entryData); - if (entryId == 1) { - dataFork = entryData; - } else if (entryId == 2) { - resourceFork = entryData; - } else if (entryId == 11) { - ByteBuffer infoData = ByteBuffer.wrap(entryData) - .order(ByteOrder.BIG_ENDIAN) - .asReadOnlyBuffer(); - int access = infoData.getShort(); - int fileType = infoData.getShort(); - int auxType = infoData.getInt(); - prodosFileInfo = new ProdosFileInfo(access, fileType, auxType); - } else { - throw new IOException(String.format("Unknown entry type of %04x", entryId)); - } - buffer.reset(); - } - } - private void required(ByteBuffer buffer, int expected, String message) throws IOException { - int actual = buffer.getInt(); - if (actual != expected) { - throw new IOException(String.format("%s Expected 0x%08x but read 0x%08x.", message, expected, actual)); - } - } - - public byte[] getDataFork() { - return dataFork; - } - public byte[] getResourceFork() { - return resourceFork; - } - public String getRealName() { - return realName; - } - public ProdosFileInfo getProdosFileInfo() { - return prodosFileInfo; - } - - public class ProdosFileInfo { - private int access; - private int fileType; - private int auxType; - - public ProdosFileInfo(int access, int fileType, int auxType) { - this.access = access; - this.fileType = fileType; - this.auxType = auxType; - } - - public int getAccess() { - return access; - } - public int getFileType() { - return fileType; - } - public int getAuxType() { - return auxType; - } - } -} diff --git a/src/test/java/com/webcodepro/applecommander/util/AppleSingleTest.java b/src/test/java/com/webcodepro/applecommander/util/AppleSingleTest.java index ae802b6..df64eb6 100644 --- a/src/test/java/com/webcodepro/applecommander/util/AppleSingleTest.java +++ b/src/test/java/com/webcodepro/applecommander/util/AppleSingleTest.java @@ -2,7 +2,6 @@ package com.webcodepro.applecommander.util; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; import java.io.File; import java.io.IOException; @@ -16,26 +15,10 @@ import com.webcodepro.applecommander.storage.FileEntry; import com.webcodepro.applecommander.storage.FormattedDisk; import com.webcodepro.applecommander.storage.os.prodos.ProdosFileEntry; import com.webcodepro.applecommander.ui.ac; -import com.webcodepro.applecommander.util.AppleSingle.ProdosFileInfo; public class AppleSingleTest { private static final String AS_HELLO_BIN = "/hello.applesingle.bin"; - - @Test - public void testSampleFromCc65() throws IOException { - AppleSingle as = new AppleSingle(getClass().getResourceAsStream(AS_HELLO_BIN)); - - assertNull(as.getRealName()); - assertNull(as.getResourceFork()); - assertNotNull(as.getDataFork()); - assertNotNull(as.getProdosFileInfo()); - - ProdosFileInfo info = as.getProdosFileInfo(); - assertEquals(0xc3, info.getAccess()); - assertEquals(0x06, info.getFileType()); - assertEquals(0x0803, info.getAuxType()); - } - + @Test public void testViaAcTool() throws IOException, DiskException { // Create a file that the JVM *should* delete for us.