/*
* Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
* Copyright (C) $$Year-Rel$$ The Jalview Authors
*
* This file is part of Jalview.
*
* Jalview is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* Jalview is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jalview. If not, see
* If the response status includes * *
* Content-Type : application/x-gzip ** * then tries to read as gzipped content. * * @param urlStr * @throws IOException * @throws MalformedURLException */ private void checkURLSource(String urlStr) throws IOException, MalformedURLException { errormessage = "URL NOT FOUND"; URL url = new URL(urlStr); URLConnection _conn = url.openConnection(); if (_conn instanceof HttpURLConnection) { HttpURLConnection conn = (HttpURLConnection) _conn; int rc = conn.getResponseCode(); if (rc != HttpURLConnection.HTTP_OK) { throw new IOException( "Response status from " + urlStr + " was " + rc); } } else { try { dataIn = checkForGzipStream(_conn.getInputStream()); dataName = urlStr; } catch (IOException ex) { throw new IOException("Failed to handle non-HTTP URI stream", ex); } catch (Exception ex) { throw new IOException( "Failed to determine type of input stream for given URI", ex); } return; } String encoding = _conn.getContentEncoding(); String contentType = _conn.getContentType(); boolean isgzipped = "application/x-gzip".equalsIgnoreCase(contentType) || "gzip".equals(encoding); Exception e = null; InputStream inputStream = _conn.getInputStream(); if (isgzipped) { try { dataIn = getGzipReader(inputStream); dataName = urlStr; } catch (Exception e1) { throw new IOException(MessageManager .getString("exception.failed_to_resolve_gzip_stream"), e); } return; } dataIn = new BufferedReader(new InputStreamReader(inputStream)); dataName = urlStr; return; } /** * sets the suffix string (if any) and returns remainder (if suffix was * detected) * * @param fileStr * @return truncated fileStr or null */ private String extractSuffix(String fileStr) { // first check that there wasn't a suffix string tagged on. int sfpos = fileStr.lastIndexOf(suffixSeparator); if (sfpos > -1 && sfpos < fileStr.length() - 1) { suffix = fileStr.substring(sfpos + 1); // System.err.println("DEBUG: Found Suffix:"+suffix); return fileStr.substring(0, sfpos); } return null; } /** * not for general use, creates a fileParse object for an existing reader with * configurable values for the origin and the type of the source */ public FileParse(BufferedReader source, String originString, DataSourceType sourceType) { dataSourceType = sourceType; error = false; inFile = null; dataName = originString; dataIn = source; try { if (dataIn.markSupported()) { dataIn.mark(READAHEAD_LIMIT); } } catch (IOException q) { } } /** * Create a datasource for input to Jalview. See AppletFormatAdapter for the * types of sources that are handled. * * @param file * - datasource locator/content as File or String * @param sourceType * - protocol of source * @throws MalformedURLException * @throws IOException */ public FileParse(Object file, DataSourceType sourceType) throws MalformedURLException, IOException { if (file instanceof File) { parse((File) file, ((File) file).getPath(), sourceType, true); } else { parse(null, file.toString(), sourceType, false); } } private void parse(File file, String fileStr, DataSourceType sourceType, boolean isFileObject) throws IOException { bytes = Platform.getFileBytes(file); dataSourceType = sourceType; error = false; if (sourceType == DataSourceType.FILE) { if (bytes != null) { // this will be from JavaScript inFile = file; dataIn = new BufferedReader( new InputStreamReader(new ByteArrayInputStream(bytes))); dataName = fileStr; } else if (checkFileSource(fileStr)) { String suffixLess = extractSuffix(fileStr); if (suffixLess != null) { if (checkFileSource(suffixLess)) { throw new IOException(MessageManager.formatMessage( "exception.problem_opening_file_also_tried", new String[] { inFile.getName(), suffixLess, errormessage })); } } else { throw new IOException(MessageManager.formatMessage( "exception.problem_opening_file", new String[] { inFile.getName(), errormessage })); } } } else if (sourceType == DataSourceType.RELATIVE_URL) { // BH 2018 hack for no support for access-origin bytes = Platform.getFileAsBytes(fileStr); dataIn = new BufferedReader( new InputStreamReader(new ByteArrayInputStream(bytes))); dataName = fileStr; } else if (sourceType == DataSourceType.URL) { try { try { checkURLSource(fileStr); if (suffixSeparator == '#') { extractSuffix(fileStr); // URL lref is stored for later reference. } } catch (IOException e) { String suffixLess = extractSuffix(fileStr); if (suffixLess == null) { throw (e); } else { try { checkURLSource(suffixLess); } catch (IOException e2) { errormessage = "BAD URL WITH OR WITHOUT SUFFIX"; throw (e); // just pass back original - everything was wrong. } } } } catch (Exception e) { errormessage = "CANNOT ACCESS DATA AT URL '" + fileStr + "' (" + e.getMessage() + ")"; error = true; } } else if (sourceType == DataSourceType.PASTE) { errormessage = "PASTE INACCESSIBLE!"; dataIn = new BufferedReader(new StringReader(fileStr)); dataName = "Paste"; } else if (sourceType == DataSourceType.CLASSLOADER) { errormessage = "RESOURCE CANNOT BE LOCATED"; InputStream is = getClass().getResourceAsStream("/" + fileStr); if (is == null) { String suffixLess = extractSuffix(fileStr); if (suffixLess != null) { is = getClass().getResourceAsStream("/" + suffixLess); } } if (is != null) { dataIn = new BufferedReader(new InputStreamReader(is)); dataName = fileStr; } else { error = true; } } else { errormessage = "PROBABLE IMPLEMENTATION ERROR : Datasource Type given as '" + (sourceType != null ? sourceType : "null") + "'"; error = true; } if (dataIn == null || error) { // pass up the reason why we have no source to read from throw new IOException(MessageManager.formatMessage( "exception.failed_to_read_data_from_source", new String[] { errormessage })); } error = false; dataIn.mark(READAHEAD_LIMIT); } /** * mark the current position in the source as start for the purposes of it * being analysed by IdentifyFile().identify * * @throws IOException */ public void mark() throws IOException { if (dataIn != null) { dataIn.mark(READAHEAD_LIMIT); } else { throw new IOException( MessageManager.getString("exception.no_init_source_stream")); } } public String nextLine() throws IOException { if (!error) { return dataIn.readLine(); } throw new IOException(MessageManager .formatMessage("exception.invalid_source_stream", new String[] { errormessage })); } /** * * @return true if this FileParse is configured for Export only */ public boolean isExporting() { return !error && dataIn == null; } /** * * @return true if the data source is valid */ public boolean isValid() { return !error; } /** * closes the datasource and tidies up. source will be left in an error state */ public void close() throws IOException { errormessage = "EXCEPTION ON CLOSE"; error = true; dataIn.close(); dataIn = null; errormessage = "SOURCE IS CLOSED"; } /** * Rewinds the datasource to the marked point if possible * * @param bytesRead * */ public void reset(int bytesRead) throws IOException { if (bytesRead >= READAHEAD_LIMIT) { System.err.println(String.format( "File reset error: read %d bytes but reset limit is %d", bytesRead, READAHEAD_LIMIT)); } if (dataIn != null && !error) { dataIn.reset(); } else { throw new IOException(MessageManager.getString( "error.implementation_error_reset_called_for_invalid_source")); } } /** * * @return true if there is a warning for the user */ public boolean hasWarningMessage() { return (warningMessage != null && warningMessage.length() > 0); } /** * * @return empty string or warning message about file that was just parsed. */ public String getWarningMessage() { return warningMessage; } public String getInFile() { if (inFile != null) { return inFile.getAbsolutePath() + " (" + index + ")"; } else { return "From Paste + (" + index + ")"; } } /** * @return the dataName */ public String getDataName() { return dataName; } /** * set the (human readable) name or URI for this datasource * * @param dataname */ protected void setDataName(String dataname) { dataName = dataname; } /** * get the underlying bufferedReader for this data source. * * @return null if no reader available * @throws IOException */ public Reader getReader() { if (dataIn != null) // Probably don't need to test for readiness && // dataIn.ready()) { return dataIn; } return null; } public AlignViewportI getViewport() { return viewport; } public void setViewport(AlignViewportI viewport) { this.viewport = viewport; } /** * @return the currently configured exportSettings for writing data. */ public AlignExportSettingsI getExportSettings() { return exportSettings; } /** * Set configuration for export of data. * * @param exportSettings * the exportSettings to set */ public void setExportSettings(AlignExportSettingsI exportSettings) { this.exportSettings = exportSettings; } /** * method overridden by complex file exporter/importers which support * exporting visualisation and layout settings for a view * * @param avpanel */ public void configureForView(AlignmentViewPanel avpanel) { if (avpanel != null) { setViewport(avpanel.getAlignViewport()); } // could also set export/import settings } /** * Returns the preferred feature colour configuration if there is one, else * null * * @return */ public FeatureSettingsModelI getFeatureColourScheme() { return null; } public DataSourceType getDataSourceType() { return dataSourceType; } /** * Returns a buffered reader for the input object. Returns null, or throws * IOException, on failure. * * @param file * a File, or a String which is a name of a file * @param sourceType * @return * @throws IOException */ public BufferedReader getBufferedReader(Object file, DataSourceType sourceType) throws IOException { BufferedReader in = null; byte[] bytes; switch (sourceType) { case FILE: if (file instanceof String) { return new BufferedReader(new FileReader((String) file)); } bytes = Platform.getFileBytes((File) file); if (bytes != null) { return new BufferedReader( new InputStreamReader(new ByteArrayInputStream(bytes))); } return new BufferedReader(new FileReader((File) file)); case URL: URL url = new URL(file.toString()); in = new BufferedReader(new InputStreamReader(url.openStream())); break; case RELATIVE_URL: // JalviewJS only bytes = Platform.getFileAsBytes(file.toString()); if (bytes != null) { in = new BufferedReader( new InputStreamReader(new ByteArrayInputStream(bytes))); } break; case PASTE: in = new BufferedReader(new StringReader(file.toString())); break; case CLASSLOADER: InputStream is = getClass().getResourceAsStream("/" + file); if (is != null) { in = new BufferedReader(new InputStreamReader(is)); } break; } return in; } }