committed Doug's Rocksim loader
[debian/openrocket] / src / net / sf / openrocket / file / GeneralRocketLoader.java
1 package net.sf.openrocket.file;
2
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.zip.GZIPInputStream;
8 import java.util.Arrays;
9
10 import net.sf.openrocket.document.OpenRocketDocument;
11 import net.sf.openrocket.file.openrocket.OpenRocketLoader;
12 import net.sf.openrocket.file.rocksim.RocksimLoader;
13
14
15 /**
16  * A rocket loader that auto-detects the document type and uses the appropriate
17  * loading.  Supports loading of GZIPed files as well with transparent
18  * uncompression.
19  * 
20  * @author Sampo Niskanen <sampo.niskanen@iki.fi>
21  */
22 public class GeneralRocketLoader extends RocketLoader {
23
24         private static final int READ_BYTES = 300;
25         
26         private static final byte[] GZIP_SIGNATURE = { 31, -117 };  // 0x1f, 0x8b
27         private static final byte[] OPENROCKET_SIGNATURE = 
28                 "<openrocket".getBytes(Charset.forName("US-ASCII"));
29     private static final byte[] ROCKSIM_SIGNATURE = 
30         "<RockSimDoc".getBytes(Charset.forName("US-ASCII"));
31         
32         private final OpenRocketLoader openRocketLoader = new OpenRocketLoader();
33     
34     private final RocksimLoader rocksimLoader = new RocksimLoader();
35         
36         @Override
37         protected OpenRocketDocument loadFromStream(InputStream source) throws IOException,
38                         RocketLoadException {
39
40                 // Check for mark() support
41                 if (!source.markSupported()) {
42                         source = new BufferedInputStream(source);
43                 }
44                 
45                 // Read using mark()
46                 byte[] buffer = new byte[READ_BYTES];
47                 int count;
48                 source.mark(READ_BYTES + 10);
49                 count = source.read(buffer);
50                 source.reset();
51                 
52                 if (count < 10) {
53                         throw new RocketLoadException("Unsupported or corrupt file.");
54                 }
55                 
56                 // Detect the appropriate loader
57
58                 // Check for GZIP
59                 if (buffer[0] == GZIP_SIGNATURE[0]  &&  buffer[1] == GZIP_SIGNATURE[1]) {
60                         OpenRocketDocument doc = loadFromStream(new GZIPInputStream(source));
61                         doc.getDefaultStorageOptions().setCompressionEnabled(true);
62                         return doc;
63                 }
64                 
65                 // Check for OpenRocket
66                 int match = 0;
67                 for (int i=0; i < count; i++) {
68                         if (buffer[i] == OPENROCKET_SIGNATURE[match]) {
69                                 match++;
70                                 if (match == OPENROCKET_SIGNATURE.length) {
71                                         return loadUsing(source, openRocketLoader);
72                                 }
73                         } else {
74                                 match = 0;
75                         }
76                 }
77
78         byte[] typeIdentifier = Arrays.copyOf(buffer, ROCKSIM_SIGNATURE.length);
79         if (Arrays.equals(ROCKSIM_SIGNATURE, typeIdentifier)) {
80             return loadUsing(source, rocksimLoader);            
81         }
82                 throw new RocketLoadException("Unsupported or corrupt file.");
83         }
84         
85         private OpenRocketDocument loadUsing(InputStream source, RocketLoader loader) 
86         throws RocketLoadException {
87                 warnings.clear();
88                 OpenRocketDocument doc = loader.load(source);
89                 warnings.addAll(loader.getWarnings());
90                 return doc;
91         }
92 }