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