Numerous bug fixes and updates
[debian/openrocket] / src / net / sf / openrocket / util / OpenFileWorker.java
1 package net.sf.openrocket.util;
2
3 import java.io.BufferedInputStream;
4 import java.io.File;
5 import java.io.FileInputStream;
6 import java.io.FilterInputStream;
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.io.InterruptedIOException;
10
11 import javax.swing.SwingWorker;
12
13 import net.sf.openrocket.document.OpenRocketDocument;
14 import net.sf.openrocket.file.GeneralRocketLoader;
15 import net.sf.openrocket.file.RocketLoader;
16
17
18 /**
19  * A SwingWorker thread that opens a rocket design file.
20  * 
21  * @author Sampo Niskanen <sampo.niskanen@iki.fi>
22  */
23 public class OpenFileWorker extends SwingWorker<OpenRocketDocument, Void> {
24
25         private static final RocketLoader ROCKET_LOADER = new GeneralRocketLoader();
26
27         private final File file;
28         private final InputStream stream;
29         
30         public OpenFileWorker(File file) {
31                 this.file = file;
32                 this.stream = null;
33         }
34         
35         
36         public OpenFileWorker(InputStream stream) {
37                 this.stream = stream;
38                 this.file = null;
39         }
40         
41         
42         @Override
43         protected OpenRocketDocument doInBackground() throws Exception {
44                 InputStream is;
45                 
46                 // Get the correct input stream
47                 if (file != null) {
48                         is = new FileInputStream(file);
49                 } else {
50                         is = stream;
51                 }
52                 
53                 // Buffer stream unless already buffered
54                 if (!(is instanceof BufferedInputStream)) {
55                         is = new BufferedInputStream(is);
56                 }
57                 
58                 // Encapsulate in a ProgressInputStream
59                 is = new ProgressInputStream(is);
60                 
61                 try {
62                         return ROCKET_LOADER.load(is);
63                 } finally {
64                         try {
65                                 is.close();
66                         } catch (Exception e) {
67                                 System.err.println("Error closing file: ");
68                                 e.printStackTrace();
69                         }
70                 }
71         }
72
73         
74         
75
76         private class ProgressInputStream extends FilterInputStream {
77
78                 private final int size;
79                 private int readBytes = 0;
80                 private int progress = -1;
81                 
82                 protected ProgressInputStream(InputStream in) {
83                         super(in);
84                         int s;
85                         try {
86                                 s = in.available();
87                         } catch (IOException e) {
88                                 System.err.println("ERROR estimating available bytes!");
89                                 s = 0;
90                         }
91                         size = Math.max(s, 1);
92                 }
93
94                 
95                 
96                 @Override
97                 public int read() throws IOException {
98                         int c = in.read();
99                         if (c >= 0) {
100                                 readBytes++;
101                                 setProgress();
102                         }
103                         if (isCancelled()) {
104                                 throw new InterruptedIOException("OpenFileWorker was cancelled");
105                         }
106                         return c;
107                 }
108
109                 @Override
110                 public int read(byte[] b, int off, int len) throws IOException {
111                         int n = in.read(b, off, len);
112                         if (n > 0) {
113                                 readBytes += n;
114                                 setProgress();
115                         }
116                         if (isCancelled()) {
117                                 throw new InterruptedIOException("OpenFileWorker was cancelled");
118                         }
119                         return n;
120                 }
121
122                 @Override
123                 public int read(byte[] b) throws IOException {
124                         int n = in.read(b);
125                         if (n > 0) {
126                                 readBytes += n;
127                                 setProgress();
128                         }
129                         if (isCancelled()) {
130                                 throw new InterruptedIOException("OpenFileWorker was cancelled");
131                         }
132                         return n;
133                 }
134
135                 @Override
136                 public long skip(long n) throws IOException {
137                         long nr = in.skip(n);
138                         if (nr > 0) {
139                                 readBytes += nr;
140                                 setProgress();
141                         }
142                         if (isCancelled()) {
143                                 throw new InterruptedIOException("OpenFileWorker was cancelled");
144                         }
145                         return nr;
146                 }
147                 
148                 @Override
149                 public synchronized void reset() throws IOException {
150                         in.reset();
151                         readBytes = size - in.available();
152                         setProgress();
153                         if (isCancelled()) {
154                                 throw new InterruptedIOException("OpenFileWorker was cancelled");
155                         }
156                 }
157
158                 
159                 
160                 private void setProgress() {
161                         int p = MathUtil.clamp(readBytes * 100 / size, 0, 100);
162                         if (progress != p) {
163                                 progress = p;
164                                 OpenFileWorker.this.setProgress(progress);
165                         }
166                 }
167         }
168 }