2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.4)
3 * Copyright (C) 2008 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 * implements a random access wrapper around a particular datasource, for passing to
25 * identifyFile and AlignFile objects.
27 public class FileParse
29 public File inFile=null;
30 public int index = 1; // sequence counter for FileParse object created from same data source
31 protected char suffixSeparator = '#';
33 * '#' separated string tagged on to end of filename
34 * or url that was clipped off to resolve to valid filename
36 protected String suffix=null;
37 protected String type=null;
38 protected BufferedReader dataIn=null;
39 protected String errormessage="UNITIALISED SOURCE";
40 protected boolean error=true;
41 protected String warningMessage=null;
43 * size of readahead buffer used for when initial stream position is marked.
45 final int READAHEAD_LIMIT=2048;
50 * Create a new FileParse instance reading from the same datasource starting at the current position.
51 * WARNING! Subsequent reads from either object will affect the read position of the other, but not
56 public FileParse(FileParse from) throws IOException
60 throw new Error("Implementation error. Null FileParse in copy constructor");
66 suffixSeparator = from.suffixSeparator;
68 errormessage = from.errormessage; // inherit potential error messages
69 error = false; // reset any error condition.
78 * Attempt to open a file as a datasource.
79 * Sets error and errormessage if fileStr was invalid.
81 * @return this.error (true if the source was invalid)
83 private boolean checkFileSource(String fileStr) throws IOException {
85 this.inFile = new File(fileStr);
86 // check to see if it's a Jar file in disguise.
87 if (!inFile.exists()) {
88 errormessage = "FILE NOT FOUND";
91 if (!inFile.canRead()) {
92 errormessage = "FILE CANNOT BE OPENED FOR READING";
95 if (inFile.isDirectory()) {
96 // this is really a 'complex' filetype - but we don't handle directory reads yet.
97 errormessage = "FILE IS A DIRECTORY";
101 dataIn = new BufferedReader(new FileReader(fileStr));
105 private boolean checkURLSource(String fileStr) throws IOException, MalformedURLException
107 errormessage = "URL NOT FOUND";
108 URL url = new URL(fileStr);
109 dataIn = new BufferedReader(new InputStreamReader(url.openStream()));
113 * sets the suffix string (if any) and returns remainder (if suffix was detected)
115 * @return truncated fileStr or null
117 private String extractSuffix(String fileStr) {
118 // first check that there wasn't a suffix string tagged on.
119 int sfpos = fileStr.lastIndexOf(suffixSeparator);
120 if (sfpos>-1 && sfpos<fileStr.length()-1) {
121 suffix = fileStr.substring(sfpos+1);
122 // System.err.println("DEBUG: Found Suffix:"+suffix);
123 return fileStr.substring(0,sfpos);
128 * Create a datasource for input to Jalview.
129 * See AppletFormatAdapter for the types of sources that are handled.
130 * @param fileStr - datasource locator/content
131 * @param type - protocol of source
132 * @throws MalformedURLException
133 * @throws IOException
135 public FileParse(String fileStr, String type)
136 throws MalformedURLException, IOException
141 if (type.equals(AppletFormatAdapter.FILE))
143 if (checkFileSource(fileStr)) {
144 String suffixLess = extractSuffix(fileStr);
145 if (suffixLess!=null)
147 if (checkFileSource(suffixLess))
149 throw new IOException("Problem opening "+inFile+" (also tried "+suffixLess+") : "+errormessage);
153 throw new IOException("Problem opening "+inFile+" : "+errormessage);
157 else if (type.equals(AppletFormatAdapter.URL))
161 checkURLSource(fileStr);
162 if (suffixSeparator=='#')
163 extractSuffix(fileStr); // URL lref is stored for later reference.
164 } catch (IOException e) {
165 String suffixLess = extractSuffix(fileStr);
166 if (suffixLess==null)
171 checkURLSource(suffixLess);
173 catch (IOException e2) {
174 errormessage = "BAD URL WITH OR WITHOUT SUFFIX";
175 throw(e); // just pass back original - everything was wrong.
182 errormessage = "CANNOT ACCESS DATA AT URL '"+fileStr+"' ("+e.getMessage()+")";
186 else if (type.equals(AppletFormatAdapter.PASTE))
188 errormessage = "PASTE INACCESSIBLE!";
189 dataIn = new BufferedReader(new StringReader(fileStr));
191 else if (type.equals(AppletFormatAdapter.CLASSLOADER))
193 errormessage = "RESOURCE CANNOT BE LOCATED";
194 java.io.InputStream is = getClass().getResourceAsStream("/" + fileStr);
196 String suffixLess = extractSuffix(fileStr);
197 if (suffixLess!=null)
198 is = getClass().getResourceAsStream("/" + suffixLess);
202 dataIn = new BufferedReader(new java.io.InputStreamReader(is));
208 errormessage = "PROBABLE IMPLEMENTATION ERROR : Datasource Type given as '"+(type!=null ? type : "null")+"'";
211 if (dataIn==null || error)
213 // pass up the reason why we have no source to read from
214 throw new IOException("Failed to read data from source:\n"+errormessage);
217 dataIn.mark(READAHEAD_LIMIT);
220 * mark the current position in the source as start
221 * for the purposes of it being analysed by IdentifyFile().identify
222 * @throws IOException
224 public void mark() throws IOException
228 dataIn.mark(READAHEAD_LIMIT);
230 throw new IOException("Unitialised Source Stream");
233 public String nextLine()
237 return dataIn.readLine();
238 throw new IOException("Invalid Source Stream:"+errormessage);
241 public boolean isValid()
246 * closes the datasource and tidies up.
247 * source will be left in an error state
249 public void close() throws IOException
251 errormessage="EXCEPTION ON CLOSE";
255 errormessage="SOURCE IS CLOSED";
258 * rewinds the datasource the beginning.
261 public void reset() throws IOException
263 if (dataIn!=null && !error) {
266 throw new IOException("Implementation Error: Reset called for invalid source.");
271 * @return true if there is a warning for the user
273 public boolean hasWarningMessage() {
274 return (warningMessage!=null && warningMessage.length()>0);
278 * @return empty string or warning message about file that was just parsed.
280 public String getWarningMessage() {
281 return warningMessage;
283 public String getInFile()
287 return inFile.getAbsolutePath()+" ("+index+")";
291 return "From Paste + ("+index+")";
295 public Reader getReader() throws IOException
297 if (dataIn!=null && dataIn.ready())