Clover icon

jalviewX

  1. Project Clover database Wed Oct 31 2018 15:13:58 GMT
  2. Package jalview.io

File FileParse.java

 
testFileParser: Problem opening 1GAQ.txt : FILE CANNOT BE OPENED FOR READING
 

Coverage histogram

../../img/srcFileCovDistChart6.png
35% of files have more coverage

Code metrics

72
166
31
1
683
446
77
0.46
5.35
31
2.48

Classes

Class Line # Actions
FileParse 47 166 77 113
0.5799256658%
 

Contributing tests

This file is covered by 203 tests. .

Source view

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 jalview.api.AlignExportSettingsI;
24    import jalview.api.AlignViewportI;
25    import jalview.api.AlignmentViewPanel;
26    import jalview.api.FeatureSettingsModelI;
27    import jalview.util.MessageManager;
28   
29    import java.io.BufferedReader;
30    import java.io.ByteArrayInputStream;
31    import java.io.File;
32    import java.io.FileInputStream;
33    import java.io.FileReader;
34    import java.io.IOException;
35    import java.io.InputStream;
36    import java.io.InputStreamReader;
37    import java.io.Reader;
38    import java.io.StringReader;
39    import java.net.MalformedURLException;
40    import java.net.URL;
41    import java.util.zip.GZIPInputStream;
42   
43    /**
44    * implements a random access wrapper around a particular datasource, for
45    * passing to identifyFile and AlignFile objects.
46    */
 
47    public class FileParse
48    {
49    protected static final String SPACE = " ";
50   
51    protected static final String TAB = "\t";
52   
53    /**
54    * text specifying source of data. usually filename or url.
55    */
56    private String dataName = "unknown source";
57   
58    public File inFile = null;
59   
60    private byte[] bytes; // from JavaScript
61   
 
62  0 toggle public byte[] getBytes()
63    {
64  0 return bytes;
65    }
66    /**
67    * a viewport associated with the current file operation. May be null. May
68    * move to different object.
69    */
70    private AlignViewportI viewport;
71   
72    /**
73    * specific settings for exporting data from the current context
74    */
75    private AlignExportSettingsI exportSettings;
76   
77    /**
78    * sequence counter for FileParse object created from same data source
79    */
80    public int index = 1;
81   
82    /**
83    * separator for extracting specific 'frame' of a datasource for formats that
84    * support multiple records (e.g. BLC, Stockholm, etc)
85    */
86    protected char suffixSeparator = '#';
87   
88    /**
89    * character used to write newlines
90    */
91    protected String newline = System.getProperty("line.separator");
92   
 
93  51 toggle public void setNewlineString(String nl)
94    {
95  51 newline = nl;
96    }
97   
 
98  0 toggle public String getNewlineString()
99    {
100  0 return newline;
101    }
102   
103    /**
104    * '#' separated string tagged on to end of filename or url that was clipped
105    * off to resolve to valid filename
106    */
107    protected String suffix = null;
108   
109    protected DataSourceType dataSourceType = null;
110   
111    protected BufferedReader dataIn = null;
112   
113    protected String errormessage = "UNINITIALISED SOURCE";
114   
115    protected boolean error = true;
116   
117    protected String warningMessage = null;
118   
119    /**
120    * size of readahead buffer used for when initial stream position is marked.
121    */
122    final int READAHEAD_LIMIT = 2048;
123   
 
124  93 toggle public FileParse()
125    {
126    }
127   
128    /**
129    * Create a new FileParse instance reading from the same datasource starting
130    * at the current position. WARNING! Subsequent reads from either object will
131    * affect the read position of the other, but not the error state.
132    *
133    * @param from
134    */
 
135  249 toggle public FileParse(FileParse from) throws IOException
136    {
137  249 if (from == null)
138    {
139  0 throw new Error(MessageManager
140    .getString("error.implementation_error_null_fileparse"));
141    }
142  249 if (from == this)
143    {
144  0 return;
145    }
146  249 index = ++from.index;
147  249 inFile = from.inFile;
148  249 suffixSeparator = from.suffixSeparator;
149  249 suffix = from.suffix;
150  249 errormessage = from.errormessage; // inherit potential error messages
151  249 error = false; // reset any error condition.
152  249 dataSourceType = from.dataSourceType;
153  249 dataIn = from.dataIn;
154  249 if (dataIn != null)
155    {
156  249 mark();
157    }
158  249 dataName = from.dataName;
159    }
160   
161    /**
162    * Attempt to open a file as a datasource. Sets error and errormessage if
163    * fileStr was invalid.
164    *
165    * @param fileStr
166    * @return this.error (true if the source was invalid)
167    */
 
168  263 toggle private boolean checkFileSource(String fileStr) throws IOException
169    {
170  263 error = false;
171  263 this.inFile = new File(fileStr);
172    // check to see if it's a Jar file in disguise.
173  260 if (!inFile.exists())
174    {
175  0 errormessage = "FILE NOT FOUND";
176  0 error = true;
177    }
178  260 if (!inFile.canRead())
179    {
180  0 errormessage = "FILE CANNOT BE OPENED FOR READING";
181  0 error = true;
182    }
183  263 if (inFile.isDirectory())
184    {
185    // this is really a 'complex' filetype - but we don't handle directory
186    // reads yet.
187  0 errormessage = "FILE IS A DIRECTORY";
188  0 error = true;
189    }
190  260 if (!error)
191    {
192  260 if (fileStr.toLowerCase().endsWith(".gz"))
193    {
194  2 try
195    {
196  2 dataIn = tryAsGzipSource(new FileInputStream(fileStr));
197  1 dataName = fileStr;
198  1 return error;
199    } catch (Exception x)
200    {
201  1 warningMessage = "Failed to resolve as a GZ stream ("
202    + x.getMessage() + ")";
203    // x.printStackTrace();
204    }
205  1 ;
206    }
207   
208  259 dataIn = new BufferedReader(new FileReader(fileStr));
209  259 dataName = fileStr;
210    }
211  262 return error;
212    }
213   
 
214  4 toggle private BufferedReader tryAsGzipSource(InputStream inputStream)
215    throws Exception
216    {
217  4 BufferedReader inData = new BufferedReader(
218    new InputStreamReader(new GZIPInputStream(inputStream)));
219  2 inData.mark(2048);
220  2 inData.read();
221  2 inData.reset();
222  2 return inData;
223    }
224   
 
225  2 toggle private boolean checkURLSource(String fileStr)
226    throws IOException, MalformedURLException
227    {
228  2 errormessage = "URL NOT FOUND";
229  2 URL url = new URL(fileStr);
230    //
231    // GZIPInputStream code borrowed from Aquaria (soon to be open sourced) via
232    // Kenny Sabir
233  2 Exception e = null;
234  2 if (fileStr.toLowerCase().endsWith(".gz"))
235    {
236  2 try
237    {
238  2 InputStream inputStream = url.openStream();
239  2 dataIn = tryAsGzipSource(inputStream);
240  1 dataName = fileStr;
241  1 return false;
242    } catch (Exception ex)
243    {
244  1 e = ex;
245    }
246    }
247   
248  1 try
249    {
250  1 dataIn = new BufferedReader(new InputStreamReader(url.openStream()));
251    } catch (IOException q)
252    {
253  0 if (e != null)
254    {
255  0 throw new IOException(MessageManager
256    .getString("exception.failed_to_resolve_gzip_stream"), e);
257    }
258  0 throw q;
259    }
260    // record URL as name of datasource.
261  1 dataName = fileStr;
262  1 return false;
263    }
264   
265    /**
266    * sets the suffix string (if any) and returns remainder (if suffix was
267    * detected)
268    *
269    * @param fileStr
270    * @return truncated fileStr or null
271    */
 
272  5 toggle private String extractSuffix(String fileStr)
273    {
274    // first check that there wasn't a suffix string tagged on.
275  5 int sfpos = fileStr.lastIndexOf(suffixSeparator);
276  5 if (sfpos > -1 && sfpos < fileStr.length() - 1)
277    {
278  0 suffix = fileStr.substring(sfpos + 1);
279    // System.err.println("DEBUG: Found Suffix:"+suffix);
280  0 return fileStr.substring(0, sfpos);
281    }
282  5 return null;
283    }
284   
285    /**
286    * not for general use, creates a fileParse object for an existing reader with
287    * configurable values for the origin and the type of the source
288    */
 
289  0 toggle public FileParse(BufferedReader source, String originString,
290    DataSourceType sourceType)
291    {
292  0 dataSourceType = sourceType;
293  0 error = false;
294  0 inFile = null;
295  0 dataName = originString;
296  0 dataIn = source;
297  0 try
298    {
299  0 if (dataIn.markSupported())
300    {
301  0 dataIn.mark(READAHEAD_LIMIT);
302    }
303    } catch (IOException q)
304    {
305   
306    }
307    }
308   
309    /**
310    * Create a datasource for input to Jalview. See AppletFormatAdapter for the
311    * types of sources that are handled.
312    *
313    * @param file
314    * - datasource locator/content as File or String
315    * @param sourceType
316    * - protocol of source
317    * @throws MalformedURLException
318    * @throws IOException
319    */
 
320  523 toggle public FileParse(Object file, DataSourceType sourceType)
321    throws MalformedURLException, IOException
322    {
323  523 if (file instanceof File)
324    {
325  0 parse((File) file, ((File) file).getPath(), sourceType, true);
326    }
327    else
328    {
329  523 Test failure here parse(null, file.toString(), sourceType, false);
330    }
331    }
332   
 
333  523 toggle private void parse(File file, String fileStr, DataSourceType sourceType,
334    boolean isFileObject) throws MalformedURLException, IOException
335    {
336    /**
337    * @j2sNative
338    *
339    * this.bytes = file && file._bytes;
340    *
341    */
342  523 this.dataSourceType = sourceType;
343  523 error = false;
344   
345  523 if (sourceType == DataSourceType.FILE)
346    {
347   
348  263 if (bytes != null)
349    {
350    // this will be from JavaScript
351  0 inFile = file;
352  0 dataIn = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(bytes)));
353  0 dataName = fileStr;
354    }
355  260 else if (checkFileSource(fileStr))
356    {
357  0 String suffixLess = extractSuffix(fileStr);
358  0 if (suffixLess != null)
359    {
360  0 if (checkFileSource(suffixLess))
361    {
362  0 throw new IOException(MessageManager.formatMessage(
363    "exception.problem_opening_file_also_tried",
364    new String[]
365    { inFile.getName(), suffixLess, errormessage }));
366    }
367    }
368    else
369    {
370  0 Test failure here throw new IOException(MessageManager.formatMessage(
371    "exception.problem_opening_file", new String[]
372    { inFile.getName(), errormessage }));
373    }
374    }
375    }
376  260 else if (sourceType == DataSourceType.RELATIVE_URL)
377    {
378    /**
379    * BH 2018 hack for no support for access-origin
380    *
381    * @j2sNative
382    *
383    * this.bytes = swingjs.JSUtil.getFileAsBytes$O(fileStr);
384    *
385    */
386   
387  0 dataIn = new BufferedReader(new java.io.InputStreamReader(new ByteArrayInputStream(bytes)));
388  0 dataName = fileStr;
389   
390    }
391  260 else if (sourceType == DataSourceType.URL)
392    {
393  2 try
394    {
395  2 try
396    {
397  2 checkURLSource(fileStr);
398  2 if (suffixSeparator == '#')
399    {
400  2 extractSuffix(fileStr); // URL lref is stored for later reference.
401    }
402    } catch (IOException e)
403    {
404  0 String suffixLess = extractSuffix(fileStr);
405  0 if (suffixLess == null)
406    {
407  0 throw (e);
408    }
409    else
410    {
411  0 try
412    {
413  0 checkURLSource(suffixLess);
414    } catch (IOException e2)
415    {
416  0 errormessage = "BAD URL WITH OR WITHOUT SUFFIX";
417  0 throw (e); // just pass back original - everything was wrong.
418    }
419    }
420    }
421    } catch (Exception e)
422    {
423  0 errormessage = "CANNOT ACCESS DATA AT URL '" + fileStr + "' ("
424    + e.getMessage() + ")";
425  0 error = true;
426    }
427    }
428  258 else if (sourceType == DataSourceType.PASTE)
429    {
430  255 errormessage = "PASTE INACCESSIBLE!";
431  255 dataIn = new BufferedReader(new StringReader(fileStr));
432  255 dataName = "Paste";
433    }
434  3 else if (sourceType == DataSourceType.CLASSLOADER)
435    {
436  3 errormessage = "RESOURCE CANNOT BE LOCATED";
437  3 java.io.InputStream is = getClass()
438    .getResourceAsStream("/" + fileStr);
439  3 if (is == null)
440    {
441  0 String suffixLess = extractSuffix(fileStr);
442  0 if (suffixLess != null)
443    {
444  0 is = getClass().getResourceAsStream("/" + suffixLess);
445    }
446    }
447  3 if (is != null)
448    {
449  3 dataIn = new BufferedReader(new java.io.InputStreamReader(is));
450  3 dataName = fileStr;
451    }
452    else
453    {
454  0 error = true;
455    }
456    }
457    else
458    {
459  0 errormessage = "PROBABLE IMPLEMENTATION ERROR : Datasource Type given as '"
460  0 + (sourceType != null ? sourceType : "null") + "'";
461  0 error = true;
462    }
463  520 if (dataIn == null || error)
464    {
465    // pass up the reason why we have no source to read from
466  0 throw new IOException(MessageManager.formatMessage(
467    "exception.failed_to_read_data_from_source",
468    new String[]
469    { errormessage }));
470    }
471  520 error = false;
472  520 dataIn.mark(READAHEAD_LIMIT);
473    }
474   
475    /**
476    * mark the current position in the source as start for the purposes of it
477    * being analysed by IdentifyFile().identify
478    *
479    * @throws IOException
480    */
 
481  253 toggle public void mark() throws IOException
482    {
483  253 if (dataIn != null)
484    {
485  253 dataIn.mark(READAHEAD_LIMIT);
486    }
487    else
488    {
489  0 throw new IOException(
490    MessageManager.getString("exception.no_init_source_stream"));
491    }
492    }
493   
 
494  39088 toggle public String nextLine() throws IOException
495    {
496  39088 if (!error)
497    {
498  39088 return dataIn.readLine();
499    }
500  0 throw new IOException(MessageManager
501    .formatMessage("exception.invalid_source_stream", new String[]
502    { errormessage }));
503    }
504   
505    /**
506    *
507    * @return true if this FileParse is configured for Export only
508    */
 
509  0 toggle public boolean isExporting()
510    {
511  0 return !error && dataIn == null;
512    }
513   
514    /**
515    *
516    * @return true if the data source is valid
517    */
 
518  151 toggle public boolean isValid()
519    {
520  151 return !error;
521    }
522   
523    /**
524    * closes the datasource and tidies up. source will be left in an error state
525    */
 
526  136 toggle public void close() throws IOException
527    {
528  136 errormessage = "EXCEPTION ON CLOSE";
529  136 error = true;
530  136 dataIn.close();
531  136 dataIn = null;
532  136 errormessage = "SOURCE IS CLOSED";
533    }
534   
535    /**
536    * Rewinds the datasource to the marked point if possible
537    *
538    * @param bytesRead
539    *
540    */
 
541  0 toggle public void reset(int bytesRead) throws IOException
542    {
543  0 if (bytesRead >= READAHEAD_LIMIT)
544    {
545  0 System.err.println(String.format(
546    "File reset error: read %d bytes but reset limit is %d",
547    bytesRead, READAHEAD_LIMIT));
548    }
549  0 if (dataIn != null && !error)
550    {
551  0 dataIn.reset();
552    }
553    else
554    {
555  0 throw new IOException(MessageManager.getString(
556    "error.implementation_error_reset_called_for_invalid_source"));
557    }
558    }
559   
560    /**
561    *
562    * @return true if there is a warning for the user
563    */
 
564  51 toggle public boolean hasWarningMessage()
565    {
566  51 return (warningMessage != null && warningMessage.length() > 0);
567    }
568   
569    /**
570    *
571    * @return empty string or warning message about file that was just parsed.
572    */
 
573  9 toggle public String getWarningMessage()
574    {
575  9 return warningMessage;
576    }
577   
 
578  0 toggle public String getInFile()
579    {
580  0 if (inFile != null)
581    {
582  0 return inFile.getAbsolutePath() + " (" + index + ")";
583    }
584    else
585    {
586  0 return "From Paste + (" + index + ")";
587    }
588    }
589   
590    /**
591    * @return the dataName
592    */
 
593  308 toggle public String getDataName()
594    {
595  308 return dataName;
596    }
597   
598    /**
599    * set the (human readable) name or URI for this datasource
600    *
601    * @param dataname
602    */
 
603  0 toggle protected void setDataName(String dataname)
604    {
605  0 dataName = dataname;
606    }
607   
608    /**
609    * get the underlying bufferedReader for this data source.
610    *
611    * @return null if no reader available
612    * @throws IOException
613    */
 
614  99 toggle public Reader getReader()
615    {
616  99 if (dataIn != null) // Probably don't need to test for readiness &&
617    // dataIn.ready())
618    {
619  99 return dataIn;
620    }
621  0 return null;
622    }
623   
 
624  14 toggle public AlignViewportI getViewport()
625    {
626  14 return viewport;
627    }
628   
 
629  4 toggle public void setViewport(AlignViewportI viewport)
630    {
631  4 this.viewport = viewport;
632    }
633   
634    /**
635    * @return the currently configured exportSettings for writing data.
636    */
 
637  4 toggle public AlignExportSettingsI getExportSettings()
638    {
639  4 return exportSettings;
640    }
641   
642    /**
643    * Set configuration for export of data.
644    *
645    * @param exportSettings
646    * the exportSettings to set
647    */
 
648  51 toggle public void setExportSettings(AlignExportSettingsI exportSettings)
649    {
650  51 this.exportSettings = exportSettings;
651    }
652   
653    /**
654    * method overridden by complex file exporter/importers which support
655    * exporting visualisation and layout settings for a view
656    *
657    * @param avpanel
658    */
 
659  50 toggle public void configureForView(AlignmentViewPanel avpanel)
660    {
661  50 if (avpanel != null)
662    {
663  4 setViewport(avpanel.getAlignViewport());
664    }
665    // could also set export/import settings
666    }
667   
668    /**
669    * Returns the preferred feature colour configuration if there is one, else
670    * null
671    *
672    * @return
673    */
 
674  59 toggle public FeatureSettingsModelI getFeatureColourScheme()
675    {
676  59 return null;
677    }
678   
 
679  0 toggle public DataSourceType getDataSourceType()
680    {
681  0 return dataSourceType;
682    }
683    }