2 * Jalview - A Sequence Alignment Editor and Viewer
3 * Copyright (C) 2007 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));
209 // pass up the reason why we have no source to read from
210 throw new IOException("Failed to read data from source:\n"+errormessage);
213 dataIn.mark(READAHEAD_LIMIT);
216 * mark the current position in the source as start
217 * for the purposes of it being analysed by IdentifyFile().identify
218 * @throws IOException
220 public void mark() throws IOException
224 dataIn.mark(READAHEAD_LIMIT);
226 throw new IOException("Unitialised Source Stream");
229 public String nextLine()
233 return dataIn.readLine();
234 throw new IOException("Invalid Source Stream:"+errormessage);
237 public boolean isValid()
242 * closes the datasource and tidies up.
243 * source will be left in an error state
245 public void close() throws IOException
247 errormessage="EXCEPTION ON CLOSE";
251 errormessage="SOURCE IS CLOSED";
254 * rewinds the datasource the beginning.
257 public void reset() throws IOException
259 if (dataIn!=null && !error) {
262 throw new IOException("Implementation Error: Reset called for invalid source.");
267 * @return true if there is a warning for the user
269 public boolean hasWarningMessage() {
270 return (warningMessage!=null && warningMessage.length()>0);
274 * @return empty string or warning message about file that was just parsed.
276 public String getWarningMessage() {
277 return warningMessage;
279 public String getInFile()
283 return inFile.getAbsolutePath()+" ("+index+")";
287 return "From Paste + ("+index+")";
291 public Reader getReader() throws IOException
293 if (dataIn!=null && dataIn.ready())