/* * This file is part of the Vamsas Client version 0.1. * Copyright 2009 by Jim Procter, Iain Milne, Pierre Marguerite, * Andrew Waterhouse and Dominik Lindner. * * Earlier versions have also been incorporated into Jalview version 2.4 * since 2008, and TOPALi version 2 since 2007. * * The Vamsas Client is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The Vamsas Client 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the Vamsas Client. If not, see . */ package uk.ac.vamsas.client.simpleclient; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.RandomAccessFile; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.Vector; import org.apache.tools.zip.*; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import uk.ac.vamsas.client.AppDataInputStream; import uk.ac.vamsas.objects.utils.document.VersionEntries; /** * Basic methods for accessing an existing Vamsas Archive, and Jar entry names * for creating new vamsas archives. * * @author jimp * */ public class VamsasArchiveReader { private static final int JARFILE_OPEN_RETRIES = 50; private static final int JARFILE_OPEN_RETRYWAIT = 1; private static Log log = LogFactory.getLog(VamsasArchiveReader.class); ZipFile jfile = null; String jfileName = "randomAccessFile"; boolean stream = false; // true if we are seeking on the stream. RandomAccessFile rfile; // ZipInputStream jstream=null; Hashtable strmentries = null; private void streamInit() { // throw new Error("VamsasArchiveReader(Stream) Not implemented!"); if (!stream) { log.debug("Skipping init for Jar Stream input."); return; } else { throw new Error( "Implementation error - we don't do streams - only files or RA files"); } /* * strmentries = new Hashtable(); * log.debug("Jar Stream input Initialisation"); try { rfile.seek(0); // no * buffering - we need to be able to move around the random access stream. * jstream = new ZipInputStream(new FileInputStream(rfile.getFD())); // no * manifest (probably) if (jstream.available()==0) * log.warn("Can't read from JarInputStream (Locked stream!)"); ZipEntry * entry=null; long pos=0; do { if ((entry=jstream.getNextEntry())!=null) { * if (strmentries.containsKey(entry.getName())) { * log.info("Only recording last of duplicate entries '" * +entry.getName()+"'"); } strmentries.put(entry.getName(), new * Long(pos++)); jstream.closeEntry(); } } while (entry!=null); } catch * (Exception e) { log.warn("Exceptions during init!",e); jstream=null; } */ } public VamsasArchiveReader(File vamsasfile) { jfile = null; int retries = JARFILE_OPEN_RETRIES; Exception ex = null; if (vamsasfile.exists()) { while (jfile == null && --retries > 0) { try { jfile = new ZipFile(vamsasfile); jfileName = vamsasfile.toString(); } catch (Exception e) { ex = e; jfile = null; try { Thread.sleep(JARFILE_OPEN_RETRYWAIT); } catch (Exception w) { } ; } } if (jfile == null && ex != null) { log.debug("non-serious? Exceptions when opening JarFile at " + vamsasfile, ex); } } } /** * in an ideal world - this constructor will create a reader object for the * locked file's random access stream. * * @param vamsaslock */ public VamsasArchiveReader(Lock vamsaslock) { jfile = null; if (vamsaslock == null || !vamsaslock.isLocked()) throw new Error( "IMPLEMENTATION ERROR: Cannot create a VamsasArchiveReader without a valid lock."); // throw new // Error("VamsasArchiveReading from locked IO stream not yet implemented."); try { rfile = vamsaslock.getRaFile(); jfile = new ZipFile(rfile); if (vamsaslock.target != null) jfileName = vamsaslock.target.toString(); } catch (Exception e) { rfile = null; jfile = null; log.warn( "Unexpected IO Exception when accessing locked vamsas archive stream " + vamsaslock.target, e); } /* * stream = true; streamInit(); if (jstream==null) throw new * Error("Failed to open archive from Locked random access stream."); */ } /** * the vamsas document version(s) handled by this Reader */ final public static String DOCUMENT_VERSION = VersionEntries.BETA_VERSION; /** * name of the jarEntry containing a well formatted vamsas XML Document */ final public static String VAMSASDOC = "vamsasDocument.xml"; /** * name of the jarEntry containing a root VAMSAS element, and containing a * random sequence of VAMSAS DataSet elements */ final public static String VAMSASXML = "vamsas.xml"; /** * seeks jstream to the given entry name and reads it. * * @param entryname * @return private JarEntry seekEntry(String entryname) { if (jstream==null) * return null; if (!strmentries.containsKey(entryname)) return null; * Long entrypos = (Long) strmentries.get(entryname); if * (entrypos==null) { log.error("Null entry position for "+entryname); * return null; } try { jstream=null; rfile.seek(0); jstream = new * ZipInputStream(new FileInputStream(rfile.getFD())); ZipEntry entry * = null; long epos = entrypos.longValue(); do { entry = * jstream.getNextEntry(); } while (entry!=null && --epos>=0); // * rfile.seek(entrypos.longValue()); // make a Jar entry from a zip * entry. return new JarEntry(entry); } catch (Exception e) { * log.warn("Whilst seeking for "+entryname, e); } return null; } */ /** * * @return JarEntry for VamsasArchiveReader.VAMSASDOC */ protected ZipEntry getVamsasDocumentEntry() { return getJarEntry(VAMSASDOC); } /** * * @return JarEntry for VamsasArchiveReader.VAMSASXML */ protected ZipEntry getVamsasXmlEntry() { return getJarEntry(VAMSASXML); } /** * Test for valid vamsas document archive * * @return true if getVamsasDocumentStream will return a stream likely to * contain valid XML */ public boolean isValid() { // TODO: check if VAMSASDOC is well formed (follows // www.vamsas.ac.uk/schemas/vamsasDocument.xsd) and all appData references // are resolvable - preferably as jar entries if (jfile != null) // || jstream!=null) return (getVamsasDocumentEntry() != null); return false; } protected ZipEntry getAppdataEntry(String AppdataRef) { ZipEntry entry; if (jfile == null || !isValid() || (entry = getJarEntry(AppdataRef)) == null) return null; return entry; } public InputStream getAppdataStream(String AppdataRef) { ZipEntry entry = getAppdataEntry(AppdataRef); try { if (entry != null) return getInputStream(entry); } catch (IOException e) { log.error("Failed when opening AppdataStream for " + AppdataRef, e); } return null; } /** * get the VamsasDocument input stream, if it exists. * * @return null or valid input stream */ public InputStream getVamsasDocumentStream() { InputStream vdoc; if (jfile == null || !isValid()) return null; try { vdoc = getInputStream(getVamsasDocumentEntry()); } catch (IOException e) { log.error("Whilst geting document stream", e); vdoc = null; } return vdoc; } /** * get the VamsasXML input stream, if it exists. Note: Deprecated beyond our * prealpha testing. * * @return null or valid input stream. */ public InputStream getVamsasXmlStream() { // log.warn("Deprecated call"); ZipEntry xmle = getVamsasXmlEntry(); InputStream vdoc; if (xmle == null) return null; try { vdoc = getInputStream(xmle); } catch (IOException e) { log.error("Whilst getting VamsasXmlStream", e); vdoc = null; } return vdoc; } /** * silently close the jar file. * */ public void close() { if (jfile != null) { try { jfile.close(); rfile = null; } catch (Exception e) { log.error("Whilst closing JarFile " + jfileName, e); } } } /** * returns all entries not matching the filespec of a vamsas xml entry * * @return array of entries. */ public Vector getExtraEntries() { if (jfile == null || !isValid()) return null; Vector e = new Vector(); /* * if (jstream!=null) { Enumeration entries = strmentries.keys(); if * (entries!=null && entries.hasMoreElements()) { do { JarEntry el = * (JarEntry) entries.nextElement(); if (!el.getName().equals(VAMSASDOC) && * !el.getName().equals(VAMSASXML)) e.add(new String(el.getName())); // * avoid references } while (entries.hasMoreElements()); } } else */ Enumeration entries = jfile.getEntries(); if (entries != null && entries.hasMoreElements()) { do { ZipEntry el = (ZipEntry) entries.nextElement(); if (!el.getName().equals(VAMSASDOC) && !el.getName().equals(VAMSASXML)) e.add(new String(el.getName())); // avoid references } while (entries.hasMoreElements()); } return e; } /* * (non-Javadoc) * * @see java.util.jar.JarFile#getInputStream(java.util.zip.ZipEntry) */ private InputStream getInputStream(ZipEntry ze) throws IOException { if (jfile != null) return jfile.getInputStream(ze); return null; } /* * (non-Javadoc) * * @see java.util.jar.JarFile#getJarEntry(java.lang.String) */ private ZipEntry getJarEntry(String name) { if (jfile != null) return jfile.getEntry(name); return null; } }