updates for 0.9.4
[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.RocketLoader;
15 import net.sf.openrocket.gui.main.ExceptionHandler;
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 final File file;
26         private final InputStream stream;
27         private final RocketLoader loader;
28         
29         public OpenFileWorker(File file, RocketLoader loader) {
30                 this.file = file;
31                 this.stream = null;
32                 this.loader = loader;
33         }
34         
35         
36         public OpenFileWorker(InputStream stream, RocketLoader loader) {
37                 this.stream = stream;
38                 this.file = null;
39                 this.loader = loader;
40         }
41         
42         public RocketLoader getRocketLoader() {
43                 return loader;
44         }
45         
46         @Override
47         protected OpenRocketDocument doInBackground() throws Exception {
48                 InputStream is;
49                 
50                 // Get the correct input stream
51                 if (file != null) {
52                         is = new FileInputStream(file);
53                 } else {
54                         is = stream;
55                 }
56                 
57                 // Buffer stream unless already buffered
58                 if (!(is instanceof BufferedInputStream)) {
59                         is = new BufferedInputStream(is);
60                 }
61                 
62                 // Encapsulate in a ProgressInputStream
63                 is = new ProgressInputStream(is);
64                 
65                 try {
66                         return loader.load(is);
67                 } finally {
68                         try {
69                                 is.close();
70                         } catch (Exception e) {
71                                 ExceptionHandler.handleErrorCondition("Error closing file", e);
72                         }
73                 }
74         }
75
76         
77         
78
79         private class ProgressInputStream extends FilterInputStream {
80
81                 private final int size;
82                 private int readBytes = 0;
83                 private int progress = -1;
84                 
85                 protected ProgressInputStream(InputStream in) {
86                         super(in);
87                         int s;
88                         try {
89                                 s = in.available();
90                         } catch (IOException e) {
91                                 System.err.println("ERROR estimating available bytes!");
92                                 s = 0;
93                         }
94                         size = Math.max(s, 1);
95                 }
96
97                 
98                 
99                 @Override
100                 public int read() throws IOException {
101                         int c = in.read();
102                         if (c >= 0) {
103                                 readBytes++;
104                                 setProgress();
105                         }
106                         if (isCancelled()) {
107                                 throw new InterruptedIOException("OpenFileWorker was cancelled");
108                         }
109                         return c;
110                 }
111
112                 @Override
113                 public int read(byte[] b, int off, int len) throws IOException {
114                         int n = in.read(b, off, len);
115                         if (n > 0) {
116                                 readBytes += n;
117                                 setProgress();
118                         }
119                         if (isCancelled()) {
120                                 throw new InterruptedIOException("OpenFileWorker was cancelled");
121                         }
122                         return n;
123                 }
124
125                 @Override
126                 public int read(byte[] b) throws IOException {
127                         int n = in.read(b);
128                         if (n > 0) {
129                                 readBytes += n;
130                                 setProgress();
131                         }
132                         if (isCancelled()) {
133                                 throw new InterruptedIOException("OpenFileWorker was cancelled");
134                         }
135                         return n;
136                 }
137
138                 @Override
139                 public long skip(long n) throws IOException {
140                         long nr = in.skip(n);
141                         if (nr > 0) {
142                                 readBytes += nr;
143                                 setProgress();
144                         }
145                         if (isCancelled()) {
146                                 throw new InterruptedIOException("OpenFileWorker was cancelled");
147                         }
148                         return nr;
149                 }
150                 
151                 @Override
152                 public synchronized void reset() throws IOException {
153                         in.reset();
154                         readBytes = size - in.available();
155                         setProgress();
156                         if (isCancelled()) {
157                                 throw new InterruptedIOException("OpenFileWorker was cancelled");
158                         }
159                 }
160
161                 
162                 
163                 private void setProgress() {
164                         int p = MathUtil.clamp(readBytes * 100 / size, 0, 100);
165                         if (progress != p) {
166                                 progress = p;
167                                 OpenFileWorker.this.setProgress(progress);
168                         }
169                 }
170         }
171 }