Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
FileParse | 56 | 231 | 101 |
1 | /* | |
2 | * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) | |
3 | * Copyright (C) $$Year-Rel$$ The Jalview Authors | |
4 | * | |
5 | * This file is part of Jalview. | |
6 | * | |
7 | * Jalview is free software: you can redistribute it and/or | |
8 | * modify it under the terms of the GNU General Public License | |
9 | * as published by the Free Software Foundation, either version 3 | |
10 | * of the License, or (at your option) any later version. | |
11 | * | |
12 | * Jalview is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty | |
14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |
15 | * PURPOSE. See the GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with Jalview. If not, see <http://www.gnu.org/licenses/>. | |
19 | * The Jalview Authors are detailed in the 'AUTHORS' file. | |
20 | */ | |
21 | package jalview.io; | |
22 | ||
23 | import java.io.BufferedInputStream; | |
24 | import java.io.BufferedReader; | |
25 | import java.io.ByteArrayInputStream; | |
26 | import java.io.File; | |
27 | import java.io.FileInputStream; | |
28 | import java.io.FileNotFoundException; | |
29 | import java.io.FileReader; | |
30 | import java.io.IOException; | |
31 | import java.io.InputStream; | |
32 | import java.io.InputStreamReader; | |
33 | import java.io.Reader; | |
34 | import java.io.StringReader; | |
35 | import java.net.HttpURLConnection; | |
36 | import java.net.MalformedURLException; | |
37 | import java.net.SocketTimeoutException; | |
38 | import java.net.URL; | |
39 | import java.net.URLConnection; | |
40 | import java.net.UnknownHostException; | |
41 | import java.util.zip.GZIPInputStream; | |
42 | ||
43 | import jalview.api.AlignExportSettingsI; | |
44 | import jalview.api.AlignViewportI; | |
45 | import jalview.api.AlignmentViewPanel; | |
46 | import jalview.api.FeatureSettingsModelI; | |
47 | import jalview.bin.Console; | |
48 | import jalview.util.HttpUtils; | |
49 | import jalview.util.MessageManager; | |
50 | import jalview.util.Platform; | |
51 | ||
52 | /** | |
53 | * implements a random access wrapper around a particular datasource, for | |
54 | * passing to identifyFile and AlignFile objects. | |
55 | */ | |
56 | public class FileParse | |
57 | { | |
58 | protected static final String SPACE = " "; | |
59 | ||
60 | protected static final String TAB = "\t"; | |
61 | ||
62 | /** | |
63 | * text specifying source of data. usually filename or url. | |
64 | */ | |
65 | private String dataName = "unknown source"; | |
66 | ||
67 | public File inFile = null; | |
68 | ||
69 | private byte[] bytes; // from JavaScript | |
70 | ||
71 | 0 | public byte[] getBytes() |
72 | { | |
73 | 0 | return bytes; |
74 | } | |
75 | ||
76 | /** | |
77 | * a viewport associated with the current file operation. May be null. May | |
78 | * move to different object. | |
79 | */ | |
80 | private AlignViewportI viewport; | |
81 | ||
82 | /** | |
83 | * specific settings for exporting data from the current context | |
84 | */ | |
85 | private AlignExportSettingsI exportSettings; | |
86 | ||
87 | /** | |
88 | * sequence counter for FileParse object created from same data source | |
89 | */ | |
90 | public int index = 1; | |
91 | ||
92 | /** | |
93 | * separator for extracting specific 'frame' of a datasource for formats that | |
94 | * support multiple records (e.g. BLC, Stockholm, etc) | |
95 | */ | |
96 | protected char suffixSeparator = '#'; | |
97 | ||
98 | /** | |
99 | * character used to write newlines | |
100 | */ | |
101 | protected String newline = System.getProperty("line.separator"); | |
102 | ||
103 | 177 | public void setNewlineString(String nl) |
104 | { | |
105 | 177 | newline = nl; |
106 | } | |
107 | ||
108 | 0 | public String getNewlineString() |
109 | { | |
110 | 0 | return newline; |
111 | } | |
112 | ||
113 | /** | |
114 | * '#' separated string tagged on to end of filename or url that was clipped | |
115 | * off to resolve to valid filename | |
116 | */ | |
117 | protected String suffix = null; | |
118 | ||
119 | protected DataSourceType dataSourceType = null; | |
120 | ||
121 | protected BufferedReader dataIn = null; | |
122 | ||
123 | protected String errormessage = "UNINITIALISED SOURCE"; | |
124 | ||
125 | protected boolean error = true; | |
126 | ||
127 | protected String warningMessage = null; | |
128 | ||
129 | /** | |
130 | * size of readahead buffer used for when initial stream position is marked. | |
131 | */ | |
132 | final int READAHEAD_LIMIT = 2048; | |
133 | ||
134 | 262 | public FileParse() |
135 | { | |
136 | } | |
137 | ||
138 | /** | |
139 | * Create a new FileParse instance reading from the same datasource starting | |
140 | * at the current position. WARNING! Subsequent reads from either object will | |
141 | * affect the read position of the other, but not the error state. | |
142 | * | |
143 | * @param from | |
144 | */ | |
145 | 840 | public FileParse(FileParse from) throws IOException |
146 | { | |
147 | 840 | if (from == null) |
148 | { | |
149 | 0 | throw new Error(MessageManager |
150 | .getString("error.implementation_error_null_fileparse")); | |
151 | } | |
152 | 840 | if (from == this) |
153 | { | |
154 | 0 | return; |
155 | } | |
156 | 840 | index = ++from.index; |
157 | 840 | inFile = from.inFile; |
158 | 840 | suffixSeparator = from.suffixSeparator; |
159 | 840 | suffix = from.suffix; |
160 | 840 | errormessage = from.errormessage; // inherit potential error messages |
161 | 840 | error = false; // reset any error condition. |
162 | 840 | dataSourceType = from.dataSourceType; |
163 | 840 | dataIn = from.dataIn; |
164 | 840 | if (dataIn != null) |
165 | { | |
166 | 840 | mark(); |
167 | } | |
168 | 840 | dataName = from.dataName; |
169 | } | |
170 | ||
171 | /** | |
172 | * Attempt to open a file as a datasource. Sets error and errormessage if | |
173 | * fileStr was invalid. | |
174 | * | |
175 | * @param fileStr | |
176 | * @return this.error (true if the source was invalid) | |
177 | */ | |
178 | 860 | private boolean checkFileSource(String fileStr) throws IOException |
179 | { | |
180 | 860 | error = false; |
181 | 860 | this.inFile = new File(fileStr); |
182 | // check to see if it's a Jar file in disguise. | |
183 | 860 | if (!inFile.exists()) |
184 | { | |
185 | 0 | errormessage = "FILE NOT FOUND"; |
186 | 0 | error = true; |
187 | } | |
188 | 860 | if (!inFile.canRead()) |
189 | { | |
190 | 0 | errormessage = "FILE CANNOT BE OPENED FOR READING"; |
191 | 0 | error = true; |
192 | } | |
193 | 860 | if (inFile.isDirectory()) |
194 | { | |
195 | // this is really a 'complex' filetype - but we don't handle directory | |
196 | // reads yet. | |
197 | 0 | errormessage = "FILE IS A DIRECTORY"; |
198 | 0 | error = true; |
199 | } | |
200 | 860 | if (!error) |
201 | { | |
202 | 860 | try |
203 | { | |
204 | 860 | dataIn = checkForGzipStream(new FileInputStream(fileStr)); |
205 | 860 | dataName = fileStr; |
206 | } catch (Exception x) | |
207 | { | |
208 | 0 | warningMessage = "Failed to resolve " + fileStr |
209 | + " as a data source. (" + x.getMessage() + ")"; | |
210 | // x.printStackTrace(); | |
211 | 0 | error = true; |
212 | } | |
213 | 860 | ; |
214 | } | |
215 | 860 | return error; |
216 | } | |
217 | ||
218 | /** | |
219 | * Recognise the 2-byte magic header for gzip streams | |
220 | * | |
221 | * https://recalll.co/ask/v/topic/java-How-to-check-if-InputStream-is-Gzipped/555aadd62bd27354438b90f6 | |
222 | * | |
223 | * @param bytes | |
224 | * - at least two bytes | |
225 | * @return | |
226 | * @throws IOException | |
227 | */ | |
228 | 865 | public static boolean isGzipStream(InputStream input) throws IOException |
229 | { | |
230 | 865 | if (!input.markSupported()) |
231 | { | |
232 | 1 | Console.error( |
233 | "FileParse.izGzipStream: input stream must support mark/reset"); | |
234 | 1 | return false; |
235 | } | |
236 | 864 | input.mark(4); |
237 | ||
238 | // get first 2 bytes or return false | |
239 | 864 | byte[] bytes = new byte[2]; |
240 | 864 | int read = input.read(bytes); |
241 | 864 | input.reset(); |
242 | 864 | if (read != bytes.length) |
243 | { | |
244 | 0 | return false; |
245 | } | |
246 | ||
247 | 864 | int header = (bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00); |
248 | 864 | return (GZIPInputStream.GZIP_MAGIC == header); |
249 | } | |
250 | ||
251 | /** | |
252 | * Returns a Reader for the given input after wrapping it in a buffered input | |
253 | * stream, and then checking if it needs to be wrapped by a GZipInputStream | |
254 | * | |
255 | * @param input | |
256 | * @return | |
257 | */ | |
258 | 862 | private BufferedReader checkForGzipStream(InputStream input) |
259 | throws Exception | |
260 | { | |
261 | // NB: stackoverflow | |
262 | // https://stackoverflow.com/questions/4818468/how-to-check-if-inputstream-is-gzipped | |
263 | // could use a PushBackInputStream rather than a BufferedInputStream | |
264 | 862 | if (!input.markSupported()) |
265 | { | |
266 | 860 | input = new BufferedInputStream(input, 16); |
267 | } | |
268 | 862 | if (isGzipStream(input)) |
269 | { | |
270 | 2 | return getGzipReader(input); |
271 | } | |
272 | // return a buffered reader for the stream. | |
273 | 860 | InputStreamReader isReader = new InputStreamReader(input); |
274 | 860 | BufferedReader toReadFrom = new BufferedReader(isReader); |
275 | 860 | return toReadFrom; |
276 | } | |
277 | ||
278 | /** | |
279 | * Returns a {@code BufferedReader} which wraps the input stream with a | |
280 | * GZIPInputStream. Throws a {@code ZipException} if a GZIP format error | |
281 | * occurs or the compression method used is unsupported. | |
282 | * | |
283 | * @param inputStream | |
284 | * @return | |
285 | * @throws Exception | |
286 | */ | |
287 | 2 | private BufferedReader getGzipReader(InputStream inputStream) |
288 | throws Exception | |
289 | { | |
290 | 2 | BufferedReader inData = new BufferedReader( |
291 | new InputStreamReader(new GZIPInputStream(inputStream))); | |
292 | 2 | inData.mark(2048); |
293 | 2 | inData.read(); |
294 | 2 | inData.reset(); |
295 | 2 | return inData; |
296 | } | |
297 | ||
298 | /** | |
299 | * Tries to read from the given URL. If successful, saves a reader to the | |
300 | * response in field {@code dataIn}, otherwise (on exception, or HTTP response | |
301 | * status not 200), throws an exception. | |
302 | * <p> | |
303 | * If the response status includes | |
304 | * | |
305 | * <pre> | |
306 | * Content-Type : application/x-gzip | |
307 | * </pre> | |
308 | * | |
309 | * then tries to read as gzipped content. | |
310 | * | |
311 | * @param urlStr | |
312 | * @throws IOException | |
313 | * @throws MalformedURLException | |
314 | */ | |
315 | 2 | private void checkURLSource(String urlStr) |
316 | throws IOException, MalformedURLException | |
317 | { | |
318 | 2 | errormessage = "URL NOT FOUND"; |
319 | 2 | URL url = new URL(urlStr); |
320 | 2 | URLConnection _conn = HttpUtils.openConnection(url); |
321 | 2 | if (_conn instanceof HttpURLConnection) |
322 | { | |
323 | 0 | HttpURLConnection conn = HttpUtils |
324 | .followConnection((HttpURLConnection) _conn); | |
325 | 0 | int rc = conn.getResponseCode(); |
326 | 0 | if (rc != HttpURLConnection.HTTP_OK) |
327 | { | |
328 | 0 | throw new FileNotFoundException("Response status from " + urlStr |
329 | + " was " + conn.getResponseCode()); | |
330 | } | |
331 | 0 | _conn = conn; |
332 | } | |
333 | else | |
334 | { | |
335 | 2 | try |
336 | { | |
337 | 2 | dataIn = checkForGzipStream(_conn.getInputStream()); |
338 | 2 | dataName = urlStr; |
339 | } catch (IOException ex) | |
340 | { | |
341 | 0 | throw new IOException("Failed to handle non-HTTP URI stream", ex); |
342 | } catch (Exception ex) | |
343 | { | |
344 | 0 | throw new IOException( |
345 | "Failed to determine type of input stream for given URI", | |
346 | ex); | |
347 | } | |
348 | 2 | return; |
349 | } | |
350 | 0 | String encoding = _conn.getContentEncoding(); |
351 | 0 | String contentType = _conn.getContentType(); |
352 | 0 | boolean isgzipped = "application/x-gzip".equalsIgnoreCase(contentType) |
353 | || contentType.endsWith("gzip") || "gzip".equals(encoding); | |
354 | 0 | Exception e = null; |
355 | 0 | InputStream inputStream = _conn.getInputStream(); |
356 | 0 | if (isgzipped) |
357 | { | |
358 | 0 | try |
359 | { | |
360 | 0 | dataIn = getGzipReader(inputStream); |
361 | 0 | dataName = urlStr; |
362 | } catch (Exception e1) | |
363 | { | |
364 | 0 | throw new IOException(MessageManager |
365 | .getString("exception.failed_to_resolve_gzip_stream"), e); | |
366 | } | |
367 | 0 | return; |
368 | } | |
369 | ||
370 | 0 | dataIn = new BufferedReader(new InputStreamReader(inputStream)); |
371 | 0 | dataName = urlStr; |
372 | 0 | return; |
373 | } | |
374 | ||
375 | /** | |
376 | * sets the suffix string (if any) and returns remainder (if suffix was | |
377 | * detected) | |
378 | * | |
379 | * @param fileStr | |
380 | * @return truncated fileStr or null | |
381 | */ | |
382 | 2 | private String extractSuffix(String fileStr) |
383 | { | |
384 | // first check that there wasn't a suffix string tagged on. | |
385 | 2 | int sfpos = fileStr.lastIndexOf(suffixSeparator); |
386 | 2 | if (sfpos > -1 && sfpos < fileStr.length() - 1) |
387 | { | |
388 | 0 | suffix = fileStr.substring(sfpos + 1); |
389 | // jalview.bin.Console.errPrintln("DEBUG: Found Suffix:"+suffix); | |
390 | 0 | return fileStr.substring(0, sfpos); |
391 | } | |
392 | 2 | return null; |
393 | } | |
394 | ||
395 | /** | |
396 | * not for general use, creates a fileParse object for an existing reader with | |
397 | * configurable values for the origin and the type of the source | |
398 | */ | |
399 | 0 | public FileParse(BufferedReader source, String originString, |
400 | DataSourceType sourceType) | |
401 | { | |
402 | 0 | dataSourceType = sourceType; |
403 | 0 | error = false; |
404 | 0 | inFile = null; |
405 | 0 | dataName = originString; |
406 | 0 | dataIn = source; |
407 | 0 | try |
408 | { | |
409 | 0 | if (dataIn.markSupported()) |
410 | { | |
411 | 0 | dataIn.mark(READAHEAD_LIMIT); |
412 | } | |
413 | } catch (IOException q) | |
414 | { | |
415 | ||
416 | } | |
417 | } | |
418 | ||
419 | /** | |
420 | * Create a datasource for input to Jalview. See AppletFormatAdapter for the | |
421 | * types of sources that are handled. | |
422 | * | |
423 | * @param file | |
424 | * - datasource locator/content as File or String | |
425 | * @param sourceType | |
426 | * - protocol of source | |
427 | * @throws MalformedURLException | |
428 | * @throws IOException | |
429 | */ | |
430 | 1492 | public FileParse(Object file, DataSourceType sourceType) |
431 | throws MalformedURLException, FileNotFoundException, IOException | |
432 | { | |
433 | 1492 | if (file instanceof File) |
434 | { | |
435 | 16 | parse((File) file, ((File) file).getPath(), sourceType, true); |
436 | } | |
437 | else | |
438 | { | |
439 | 1476 | parse(null, file.toString(), sourceType, false); |
440 | } | |
441 | } | |
442 | ||
443 | 1492 | private void parse(File file, String fileStr, DataSourceType sourceType, |
444 | boolean isFileObject) throws FileNotFoundException, IOException | |
445 | { | |
446 | 1492 | bytes = Platform.getFileBytes(file); |
447 | 1492 | dataSourceType = sourceType; |
448 | 1492 | error = false; |
449 | 1492 | boolean filenotfound = false; |
450 | ||
451 | 1492 | if (sourceType == DataSourceType.FILE) |
452 | { | |
453 | ||
454 | 860 | if (bytes != null) |
455 | { | |
456 | // this will be from JavaScript | |
457 | 0 | inFile = file; |
458 | 0 | dataIn = new BufferedReader( |
459 | new InputStreamReader(new ByteArrayInputStream(bytes))); | |
460 | 0 | dataName = fileStr; |
461 | } | |
462 | 860 | else if (checkFileSource(fileStr)) |
463 | { | |
464 | 0 | String suffixLess = extractSuffix(fileStr); |
465 | 0 | if (suffixLess != null) |
466 | { | |
467 | 0 | if (checkFileSource(suffixLess)) |
468 | { | |
469 | 0 | throw new IOException(MessageManager.formatMessage( |
470 | "exception.problem_opening_file_also_tried", | |
471 | new String[] | |
472 | { inFile.getName(), suffixLess, errormessage })); | |
473 | } | |
474 | } | |
475 | else | |
476 | { | |
477 | 0 | throw new IOException(MessageManager.formatMessage( |
478 | "exception.problem_opening_file", new String[] | |
479 | { inFile.getName(), errormessage })); | |
480 | } | |
481 | } | |
482 | } | |
483 | 632 | else if (sourceType == DataSourceType.RELATIVE_URL) |
484 | { | |
485 | // BH 2018 hack for no support for access-origin | |
486 | 0 | bytes = Platform.getFileAsBytes(fileStr); |
487 | 0 | dataIn = new BufferedReader( |
488 | new InputStreamReader(new ByteArrayInputStream(bytes))); | |
489 | 0 | dataName = fileStr; |
490 | ||
491 | } | |
492 | 632 | else if (sourceType == DataSourceType.URL) |
493 | { | |
494 | 2 | try |
495 | { | |
496 | 2 | try |
497 | { | |
498 | 2 | checkURLSource(fileStr); |
499 | 2 | if (suffixSeparator == '#') |
500 | { | |
501 | 2 | extractSuffix(fileStr); // URL lref is stored for later reference. |
502 | } | |
503 | } catch (IOException e) | |
504 | { | |
505 | 0 | String suffixLess = extractSuffix(fileStr); |
506 | 0 | if (suffixLess == null) |
507 | { | |
508 | 0 | if (e instanceof FileNotFoundException |
509 | || e instanceof UnknownHostException | |
510 | || e instanceof SocketTimeoutException) | |
511 | { | |
512 | 0 | errormessage = "File at URL '" + fileStr + "' not found"; |
513 | 0 | filenotfound = true; |
514 | } | |
515 | 0 | throw (e); |
516 | } | |
517 | else | |
518 | { | |
519 | 0 | try |
520 | { | |
521 | 0 | checkURLSource(suffixLess); |
522 | } catch (IOException e2) | |
523 | { | |
524 | 0 | errormessage = "BAD URL WITH OR WITHOUT SUFFIX '" + fileStr |
525 | + "'"; | |
526 | 0 | if (e instanceof FileNotFoundException |
527 | || e instanceof UnknownHostException | |
528 | || e instanceof SocketTimeoutException) | |
529 | { | |
530 | 0 | filenotfound = true; |
531 | } | |
532 | 0 | throw (e); // just pass back original - everything was wrong. |
533 | } | |
534 | } | |
535 | } | |
536 | } catch (Exception e) | |
537 | { | |
538 | 0 | errormessage = "CANNOT ACCESS DATA AT URL '" + fileStr + "' (" |
539 | + e.getMessage() + ")"; | |
540 | 0 | error = true; |
541 | } | |
542 | } | |
543 | 630 | else if (sourceType == DataSourceType.PASTE) |
544 | { | |
545 | 310 | errormessage = "PASTE INACCESSIBLE!"; |
546 | 310 | dataIn = new BufferedReader(new StringReader(fileStr)); |
547 | 310 | dataName = "Paste"; |
548 | } | |
549 | 320 | else if (sourceType == DataSourceType.CLASSLOADER) |
550 | { | |
551 | 320 | errormessage = "RESOURCE CANNOT BE LOCATED"; |
552 | 320 | InputStream is = getClass().getResourceAsStream("/" + fileStr); |
553 | 320 | if (is == null) |
554 | { | |
555 | 0 | String suffixLess = extractSuffix(fileStr); |
556 | 0 | if (suffixLess != null) |
557 | { | |
558 | 0 | is = getClass().getResourceAsStream("/" + suffixLess); |
559 | } | |
560 | } | |
561 | 320 | if (is != null) |
562 | { | |
563 | 320 | dataIn = new BufferedReader(new InputStreamReader(is)); |
564 | 320 | dataName = fileStr; |
565 | } | |
566 | else | |
567 | { | |
568 | 0 | error = true; |
569 | } | |
570 | } | |
571 | else | |
572 | { | |
573 | 0 | errormessage = "PROBABLE IMPLEMENTATION ERROR : Datasource Type given as '" |
574 | 0 | + (sourceType != null ? sourceType : "null") + "'"; |
575 | 0 | error = true; |
576 | } | |
577 | 1492 | if (dataIn == null || error) |
578 | { | |
579 | // pass up the reason why we have no source to read from | |
580 | 0 | if (filenotfound) |
581 | { | |
582 | 0 | throw new FileNotFoundException(MessageManager |
583 | .formatMessage("label.url_not_found", new String[] | |
584 | { errormessage })); | |
585 | } | |
586 | 0 | throw new IOException(MessageManager.formatMessage( |
587 | "exception.failed_to_read_data_from_source", new String[] | |
588 | { errormessage })); | |
589 | } | |
590 | 1492 | error = false; |
591 | 1492 | dataIn.mark(READAHEAD_LIMIT); |
592 | } | |
593 | ||
594 | /** | |
595 | * mark the current position in the source as start for the purposes of it | |
596 | * being analysed by IdentifyFile().identify | |
597 | * | |
598 | * @throws IOException | |
599 | */ | |
600 | 844 | public void mark() throws IOException |
601 | { | |
602 | 844 | if (dataIn != null) |
603 | { | |
604 | 844 | dataIn.mark(READAHEAD_LIMIT); |
605 | } | |
606 | else | |
607 | { | |
608 | 0 | throw new IOException( |
609 | MessageManager.getString("exception.no_init_source_stream")); | |
610 | } | |
611 | } | |
612 | ||
613 | 84077 | public String nextLine() throws IOException |
614 | { | |
615 | 84078 | if (!error) |
616 | { | |
617 | 84079 | return dataIn.readLine(); |
618 | } | |
619 | 0 | throw new IOException(MessageManager |
620 | .formatMessage("exception.invalid_source_stream", new String[] | |
621 | { errormessage })); | |
622 | } | |
623 | ||
624 | /** | |
625 | * | |
626 | * @return true if this FileParse is configured for Export only | |
627 | */ | |
628 | 0 | public boolean isExporting() |
629 | { | |
630 | 0 | return !error && dataIn == null; |
631 | } | |
632 | ||
633 | /** | |
634 | * | |
635 | * @return true if the data source is valid | |
636 | */ | |
637 | 437 | public boolean isValid() |
638 | { | |
639 | 437 | return !error; |
640 | } | |
641 | ||
642 | /** | |
643 | * closes the datasource and tidies up. source will be left in an error state | |
644 | */ | |
645 | 422 | public void close() throws IOException |
646 | { | |
647 | 422 | errormessage = "EXCEPTION ON CLOSE"; |
648 | 422 | error = true; |
649 | 422 | dataIn.close(); |
650 | 422 | dataIn = null; |
651 | 422 | errormessage = "SOURCE IS CLOSED"; |
652 | } | |
653 | ||
654 | /** | |
655 | * Rewinds the datasource to the marked point if possible | |
656 | * | |
657 | * @param bytesRead | |
658 | * | |
659 | */ | |
660 | 0 | public void reset(int bytesRead) throws IOException |
661 | { | |
662 | 0 | if (bytesRead >= READAHEAD_LIMIT) |
663 | { | |
664 | 0 | jalview.bin.Console.errPrintln(String.format( |
665 | "File reset error: read %d bytes but reset limit is %d", | |
666 | bytesRead, READAHEAD_LIMIT)); | |
667 | } | |
668 | 0 | if (dataIn != null && !error) |
669 | { | |
670 | 0 | dataIn.reset(); |
671 | } | |
672 | else | |
673 | { | |
674 | 0 | throw new IOException(MessageManager.getString( |
675 | "error.implementation_error_reset_called_for_invalid_source")); | |
676 | } | |
677 | } | |
678 | ||
679 | /** | |
680 | * | |
681 | * @return true if there is a warning for the user | |
682 | */ | |
683 | 180 | public boolean hasWarningMessage() |
684 | { | |
685 | 180 | return (warningMessage != null && warningMessage.length() > 0); |
686 | } | |
687 | ||
688 | /** | |
689 | * | |
690 | * @return empty string or warning message about file that was just parsed. | |
691 | */ | |
692 | 9 | public String getWarningMessage() |
693 | { | |
694 | 9 | return warningMessage; |
695 | } | |
696 | ||
697 | 193 | public String getInFile() |
698 | { | |
699 | 193 | if (inFile != null) |
700 | { | |
701 | 177 | return inFile.getAbsolutePath() + " (" + index + ")"; |
702 | } | |
703 | else | |
704 | { | |
705 | 16 | return "From Paste + (" + index + ")"; |
706 | } | |
707 | } | |
708 | ||
709 | /** | |
710 | * @return the dataName | |
711 | */ | |
712 | 633 | public String getDataName() |
713 | { | |
714 | 633 | return dataName; |
715 | } | |
716 | ||
717 | /** | |
718 | * set the (human readable) name or URI for this datasource | |
719 | * | |
720 | * @param dataname | |
721 | */ | |
722 | 0 | protected void setDataName(String dataname) |
723 | { | |
724 | 0 | dataName = dataname; |
725 | } | |
726 | ||
727 | /** | |
728 | * get the underlying bufferedReader for this data source. | |
729 | * | |
730 | * @return null if no reader available | |
731 | * @throws IOException | |
732 | */ | |
733 | 190 | public Reader getReader() |
734 | { | |
735 | 190 | if (dataIn != null) // Probably don't need to test for readiness && |
736 | // dataIn.ready()) | |
737 | { | |
738 | 190 | return dataIn; |
739 | } | |
740 | 0 | return null; |
741 | } | |
742 | ||
743 | 29 | public AlignViewportI getViewport() |
744 | { | |
745 | 29 | return viewport; |
746 | } | |
747 | ||
748 | 128 | public void setViewport(AlignViewportI viewport) |
749 | { | |
750 | 128 | this.viewport = viewport; |
751 | } | |
752 | ||
753 | /** | |
754 | * @return the currently configured exportSettings for writing data. | |
755 | */ | |
756 | 8 | public AlignExportSettingsI getExportSettings() |
757 | { | |
758 | 8 | return exportSettings; |
759 | } | |
760 | ||
761 | /** | |
762 | * Set configuration for export of data. | |
763 | * | |
764 | * @param exportSettings | |
765 | * the exportSettings to set | |
766 | */ | |
767 | 177 | public void setExportSettings(AlignExportSettingsI exportSettings) |
768 | { | |
769 | 177 | this.exportSettings = exportSettings; |
770 | } | |
771 | ||
772 | /** | |
773 | * method overridden by complex file exporter/importers which support | |
774 | * exporting visualisation and layout settings for a view | |
775 | * | |
776 | * @param avpanel | |
777 | */ | |
778 | 176 | public void configureForView(AlignmentViewPanel avpanel) |
779 | { | |
780 | 176 | if (avpanel != null) |
781 | { | |
782 | 128 | setViewport(avpanel.getAlignViewport()); |
783 | } | |
784 | // could also set export/import settings | |
785 | } | |
786 | ||
787 | /** | |
788 | * Returns the preferred feature colour configuration if there is one, else | |
789 | * null | |
790 | * | |
791 | * @return | |
792 | */ | |
793 | 297 | public FeatureSettingsModelI getFeatureColourScheme() |
794 | { | |
795 | 297 | return null; |
796 | } | |
797 | ||
798 | 0 | public DataSourceType getDataSourceType() |
799 | { | |
800 | 0 | return dataSourceType; |
801 | } | |
802 | ||
803 | /** | |
804 | * Returns a buffered reader for the input object. Returns null, or throws | |
805 | * IOException, on failure. | |
806 | * | |
807 | * @param file | |
808 | * a File, or a String which is a name of a file | |
809 | * @param sourceType | |
810 | * @return | |
811 | * @throws IOException | |
812 | */ | |
813 | 26 | public BufferedReader getBufferedReader(Object file, |
814 | DataSourceType sourceType) throws IOException | |
815 | { | |
816 | 26 | BufferedReader in = null; |
817 | 26 | byte[] bytes; |
818 | ||
819 | 26 | switch (sourceType) |
820 | { | |
821 | 11 | case FILE: |
822 | 11 | if (file instanceof String) |
823 | { | |
824 | 11 | return new BufferedReader(new FileReader((String) file)); |
825 | } | |
826 | 0 | bytes = Platform.getFileBytes((File) file); |
827 | 0 | if (bytes != null) |
828 | { | |
829 | 0 | return new BufferedReader( |
830 | new InputStreamReader(new ByteArrayInputStream(bytes))); | |
831 | } | |
832 | 0 | return new BufferedReader(new FileReader((File) file)); |
833 | 0 | case URL: |
834 | 0 | URL url = new URL(file.toString()); |
835 | 0 | in = new BufferedReader( |
836 | new InputStreamReader(HttpUtils.openStream(url))); | |
837 | 0 | break; |
838 | 0 | case RELATIVE_URL: // JalviewJS only |
839 | 0 | bytes = Platform.getFileAsBytes(file.toString()); |
840 | 0 | if (bytes != null) |
841 | { | |
842 | 0 | in = new BufferedReader( |
843 | new InputStreamReader(new ByteArrayInputStream(bytes))); | |
844 | } | |
845 | 0 | break; |
846 | 15 | case PASTE: |
847 | 15 | in = new BufferedReader(new StringReader(file.toString())); |
848 | 15 | break; |
849 | 0 | case CLASSLOADER: |
850 | 0 | InputStream is = getClass().getResourceAsStream("/" + file); |
851 | 0 | if (is != null) |
852 | { | |
853 | 0 | in = new BufferedReader(new InputStreamReader(is)); |
854 | } | |
855 | 0 | break; |
856 | } | |
857 | ||
858 | 15 | return in; |
859 | } | |
860 | } |