updates for 0.9.3
[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
16
17 /**
18  * A SwingWorker thread that opens a rocket design file.
19  * 
20  * @author Sampo Niskanen <sampo.niskanen@iki.fi>
21  */
22 public class OpenFileWorker extends SwingWorker<OpenRocketDocument, Void> {
23
24         private final File file;
25         private final InputStream stream;
26         private final RocketLoader loader;
27         
28         public OpenFileWorker(File file, RocketLoader loader) {
29                 this.file = file;
30                 this.stream = null;
31                 this.loader = loader;
32         }
33         
34         
35         public OpenFileWorker(InputStream stream, RocketLoader loader) {
36                 this.stream = stream;
37                 this.file = null;
38                 this.loader = loader;
39         }
40         
41         public RocketLoader getRocketLoader() {
42                 return loader;
43         }
44         
45         @Override
46         protected OpenRocketDocument doInBackground() throws Exception {
47                 InputStream is;
48                 
49                 // Get the correct input stream
50                 if (file != null) {
51                         is = new FileInputStream(file);
52                 } else {
53                         is = stream;
54                 }
55                 
56                 // Buffer stream unless already buffered
57                 if (!(is instanceof BufferedInputStream)) {
58                         is = new BufferedInputStream(is);
59                 }
60                 
61                 // Encapsulate in a ProgressInputStream
62                 is = new ProgressInputStream(is);
63                 
64                 try {
65                         return loader.load(is);
66                 } finally {
67                         try {
68                                 is.close();
69                         } catch (Exception e) {
70                                 System.err.println("Error closing file: ");
71                                 e.printStackTrace();
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 }