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