1 package net.sf.openrocket.file;
3 import java.io.BufferedInputStream;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.nio.charset.Charset;
7 import java.util.Arrays;
8 import java.util.zip.GZIPInputStream;
9 import java.util.zip.ZipEntry;
10 import java.util.zip.ZipInputStream;
12 import net.sf.openrocket.document.OpenRocketDocument;
13 import net.sf.openrocket.file.openrocket.importt.OpenRocketLoader;
14 import net.sf.openrocket.file.rocksim.importt.RocksimLoader;
15 import net.sf.openrocket.util.ArrayUtils;
16 import net.sf.openrocket.util.TextUtil;
20 * A rocket loader that auto-detects the document type and uses the appropriate
21 * loading. Supports loading of GZIPed files as well with transparent
24 * @author Sampo Niskanen <sampo.niskanen@iki.fi>
26 public class GeneralRocketLoader extends AbstractRocketLoader {
28 private static final int READ_BYTES = 300;
30 private static final byte[] GZIP_SIGNATURE = { 31, -117 }; // 0x1f, 0x8b
31 private static final byte[] ZIP_SIGNATURE = TextUtil.convertStringToBytes("PK",Charset.forName("US-ASCII"));
32 private static final byte[] OPENROCKET_SIGNATURE = TextUtil.convertStringToBytes("<openrocket",Charset.forName("US-ASCII"));
33 private static final byte[] ROCKSIM_SIGNATURE = TextUtil.convertStringToBytes("<RockSimDoc",Charset.forName("US-ASCII"));
35 private final OpenRocketLoader openRocketLoader = new OpenRocketLoader();
37 private final RocksimLoader rocksimLoader = new RocksimLoader();
40 protected OpenRocketDocument loadFromStream(InputStream source, MotorFinder motorFinder) throws IOException,
43 // Check for mark() support
44 if (!source.markSupported()) {
45 source = new BufferedInputStream(source);
49 byte[] buffer = new byte[READ_BYTES];
51 source.mark(READ_BYTES + 10);
52 count = source.read(buffer);
56 throw new RocketLoadException("Unsupported or corrupt file.");
59 // Detect the appropriate loader
62 if (buffer[0] == GZIP_SIGNATURE[0] && buffer[1] == GZIP_SIGNATURE[1]) {
63 OpenRocketDocument doc = loadFromStream(new GZIPInputStream(source), motorFinder);
64 doc.getDefaultStorageOptions().setCompressionEnabled(true);
68 // Check for ZIP (for future compatibility)
69 if (buffer[0] == ZIP_SIGNATURE[0] && buffer[1] == ZIP_SIGNATURE[1]) {
70 // Search for entry with name *.ork
71 ZipInputStream in = new ZipInputStream(source);
73 ZipEntry entry = in.getNextEntry();
75 throw new RocketLoadException("Unsupported or corrupt file.");
77 if (entry.getName().matches(".*\\.[oO][rR][kK]$")) {
78 OpenRocketDocument doc = loadFromStream(in, motorFinder);
79 doc.getDefaultStorageOptions().setCompressionEnabled(true);
81 } else if ( entry.getName().matches(".*\\.[rR][kK][tT]$")) {
82 OpenRocketDocument doc = loadFromStream(in, motorFinder);
88 // Check for OpenRocket
90 for (int i = 0; i < count; i++) {
91 if (buffer[i] == OPENROCKET_SIGNATURE[match]) {
93 if (match == OPENROCKET_SIGNATURE.length) {
94 return loadUsing(source, openRocketLoader, motorFinder);
101 byte[] typeIdentifier = ArrayUtils.copyOf(buffer, ROCKSIM_SIGNATURE.length);
102 if (Arrays.equals(ROCKSIM_SIGNATURE, typeIdentifier)) {
103 return loadUsing(source, rocksimLoader, motorFinder);
105 throw new RocketLoadException("Unsupported or corrupt file.");
108 private OpenRocketDocument loadUsing(InputStream source, RocketLoader loader, MotorFinder motorFinder)
109 throws RocketLoadException {
111 OpenRocketDocument doc = loader.load(source, motorFinder);
112 warnings.addAll(loader.getWarnings());