2 * This file is part of the Vamsas Client version 0.1.
\r
3 * Copyright 2009 by Jim Procter, Iain Milne, Pierre Marguerite,
\r
4 * Andrew Waterhouse and Dominik Lindner.
\r
6 * Earlier versions have also been incorporated into Jalview version 2.4
\r
7 * since 2008, and TOPALi version 2 since 2007.
\r
9 * The Vamsas Client is free software: you can redistribute it and/or modify
\r
10 * it under the terms of the GNU Lesser General Public License as published by
\r
11 * the Free Software Foundation, either version 3 of the License, or
\r
12 * (at your option) any later version.
\r
14 * The Vamsas Client is distributed in the hope that it will be useful,
\r
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
17 * GNU Lesser General Public License for more details.
\r
19 * You should have received a copy of the GNU Lesser General Public License
\r
20 * along with the Vamsas Client. If not, see <http://www.gnu.org/licenses/>.
\r
22 package uk.ac.vamsas.client.simpleclient;
\r
24 import java.io.File;
\r
25 import java.io.IOException;
\r
26 import java.io.InputStream;
\r
27 import java.io.BufferedInputStream;
\r
28 import java.io.FileInputStream;
\r
29 import java.io.RandomAccessFile;
\r
30 import java.util.Enumeration;
\r
31 import java.util.Hashtable;
\r
32 import java.util.Iterator;
\r
33 import java.util.Vector;
\r
34 import org.apache.tools.zip.*;
\r
35 import org.apache.commons.logging.Log;
\r
36 import org.apache.commons.logging.LogFactory;
\r
38 import uk.ac.vamsas.client.AppDataInputStream;
\r
39 import uk.ac.vamsas.objects.utils.document.VersionEntries;
\r
42 * Basic methods for accessing an existing Vamsas Archive, and Jar entry names
\r
43 * for creating new vamsas archives.
\r
48 public class VamsasArchiveReader {
\r
49 private static final int JARFILE_OPEN_RETRIES = 50;
\r
51 private static final int JARFILE_OPEN_RETRYWAIT = 1;
\r
53 private static Log log = LogFactory.getLog(VamsasArchiveReader.class);
\r
55 ZipFile jfile = null;
\r
57 String jfileName = "randomAccessFile";
\r
59 boolean stream = false; // true if we are seeking on the stream.
\r
61 RandomAccessFile rfile;
\r
63 // ZipInputStream jstream=null;
\r
64 Hashtable strmentries = null;
\r
66 private void streamInit() {
\r
67 // throw new Error("VamsasArchiveReader(Stream) Not implemented!");
\r
69 log.debug("Skipping init for Jar Stream input.");
\r
73 "Implementation error - we don't do streams - only files or RA files");
\r
76 * strmentries = new Hashtable();
\r
77 * log.debug("Jar Stream input Initialisation"); try { rfile.seek(0); // no
\r
78 * buffering - we need to be able to move around the random access stream.
\r
79 * jstream = new ZipInputStream(new FileInputStream(rfile.getFD())); // no
\r
80 * manifest (probably) if (jstream.available()==0)
\r
81 * log.warn("Can't read from JarInputStream (Locked stream!)"); ZipEntry
\r
82 * entry=null; long pos=0; do { if ((entry=jstream.getNextEntry())!=null) {
\r
83 * if (strmentries.containsKey(entry.getName())) {
\r
84 * log.info("Only recording last of duplicate entries '"
\r
85 * +entry.getName()+"'"); } strmentries.put(entry.getName(), new
\r
86 * Long(pos++)); jstream.closeEntry(); } } while (entry!=null); } catch
\r
87 * (Exception e) { log.warn("Exceptions during init!",e); jstream=null; }
\r
91 public VamsasArchiveReader(File vamsasfile) {
\r
93 int retries = JARFILE_OPEN_RETRIES;
\r
94 Exception ex = null;
\r
95 if (vamsasfile.exists()) {
\r
96 while (jfile == null && --retries > 0) {
\r
98 jfile = new ZipFile(vamsasfile);
\r
99 jfileName = vamsasfile.toString();
\r
100 } catch (Exception e) {
\r
104 Thread.sleep(JARFILE_OPEN_RETRYWAIT);
\r
105 } catch (Exception w) {
\r
110 if (jfile == null && ex != null) {
\r
111 log.debug("non-serious? Exceptions when opening JarFile at "
\r
118 * in an ideal world - this constructor will create a reader object for the
\r
119 * locked file's random access stream.
\r
121 * @param vamsaslock
\r
123 public VamsasArchiveReader(Lock vamsaslock) {
\r
125 if (vamsaslock == null || !vamsaslock.isLocked())
\r
127 "IMPLEMENTATION ERROR: Cannot create a VamsasArchiveReader without a valid lock.");
\r
129 // Error("VamsasArchiveReading from locked IO stream not yet implemented.");
\r
131 rfile = vamsaslock.getRaFile();
\r
132 jfile = new ZipFile(rfile);
\r
133 if (vamsaslock.target != null)
\r
134 jfileName = vamsaslock.target.toString();
\r
135 } catch (Exception e) {
\r
139 "Unexpected IO Exception when accessing locked vamsas archive stream "
\r
140 + vamsaslock.target, e);
\r
143 * stream = true; streamInit(); if (jstream==null) throw new
\r
144 * Error("Failed to open archive from Locked random access stream.");
\r
149 * the vamsas document version(s) handled by this Reader
\r
151 final public static String DOCUMENT_VERSION = VersionEntries.BETA_VERSION;
\r
154 * name of the jarEntry containing a well formatted vamsas XML Document
\r
157 final public static String VAMSASDOC = "vamsasDocument.xml";
\r
160 * name of the jarEntry containing a root VAMSAS element, and containing a
\r
161 * random sequence of VAMSAS DataSet elements
\r
164 final public static String VAMSASXML = "vamsas.xml";
\r
167 * seeks jstream to the given entry name and reads it.
\r
170 * @return private JarEntry seekEntry(String entryname) { if (jstream==null)
\r
171 * return null; if (!strmentries.containsKey(entryname)) return null;
\r
172 * Long entrypos = (Long) strmentries.get(entryname); if
\r
173 * (entrypos==null) { log.error("Null entry position for "+entryname);
\r
174 * return null; } try { jstream=null; rfile.seek(0); jstream = new
\r
175 * ZipInputStream(new FileInputStream(rfile.getFD())); ZipEntry entry
\r
176 * = null; long epos = entrypos.longValue(); do { entry =
\r
177 * jstream.getNextEntry(); } while (entry!=null && --epos>=0); //
\r
178 * rfile.seek(entrypos.longValue()); // make a Jar entry from a zip
\r
179 * entry. return new JarEntry(entry); } catch (Exception e) {
\r
180 * log.warn("Whilst seeking for "+entryname, e); } return null; }
\r
184 * @return JarEntry for VamsasArchiveReader.VAMSASDOC
\r
186 protected ZipEntry getVamsasDocumentEntry() {
\r
187 return getJarEntry(VAMSASDOC);
\r
192 * @return JarEntry for VamsasArchiveReader.VAMSASXML
\r
194 protected ZipEntry getVamsasXmlEntry() {
\r
195 return getJarEntry(VAMSASXML);
\r
199 * Test for valid vamsas document archive
\r
201 * @return true if getVamsasDocumentStream will return a stream likely to
\r
202 * contain valid XML
\r
204 public boolean isValid() {
\r
205 // TODO: check if VAMSASDOC is well formed (follows
\r
206 // www.vamsas.ac.uk/schemas/vamsasDocument.xsd) and all appData references
\r
207 // are resolvable - preferably as jar entries
\r
208 if (jfile != null) // || jstream!=null)
\r
209 return (getVamsasDocumentEntry() != null);
\r
213 protected ZipEntry getAppdataEntry(String AppdataRef) {
\r
215 if (jfile == null || !isValid()
\r
216 || (entry = getJarEntry(AppdataRef)) == null)
\r
222 public InputStream getAppdataStream(String AppdataRef) {
\r
223 ZipEntry entry = getAppdataEntry(AppdataRef);
\r
226 return getInputStream(entry);
\r
227 } catch (IOException e) {
\r
228 log.error("Failed when opening AppdataStream for " + AppdataRef, e);
\r
234 * get the VamsasDocument input stream, if it exists.
\r
236 * @return null or valid input stream
\r
238 public InputStream getVamsasDocumentStream() {
\r
240 if (jfile == null || !isValid())
\r
243 vdoc = getInputStream(getVamsasDocumentEntry());
\r
244 } catch (IOException e) {
\r
245 log.error("Whilst geting document stream", e);
\r
252 * get the VamsasXML input stream, if it exists. Note: Deprecated beyond our
\r
253 * prealpha testing.
\r
255 * @return null or valid input stream.
\r
258 public InputStream getVamsasXmlStream() {
\r
259 // log.warn("Deprecated call");
\r
260 ZipEntry xmle = getVamsasXmlEntry();
\r
265 vdoc = getInputStream(xmle);
\r
266 } catch (IOException e) {
\r
267 log.error("Whilst getting VamsasXmlStream", e);
\r
274 * silently close the jar file.
\r
277 public void close() {
\r
278 if (jfile != null) {
\r
282 } catch (Exception e) {
\r
283 log.error("Whilst closing JarFile " + jfileName, e);
\r
289 * returns all entries not matching the filespec of a vamsas xml entry
\r
291 * @return array of entries.
\r
293 public Vector getExtraEntries() {
\r
294 if (jfile == null || !isValid())
\r
296 Vector e = new Vector();
\r
298 * if (jstream!=null) { Enumeration entries = strmentries.keys(); if
\r
299 * (entries!=null && entries.hasMoreElements()) { do { JarEntry el =
\r
300 * (JarEntry) entries.nextElement(); if (!el.getName().equals(VAMSASDOC) &&
\r
301 * !el.getName().equals(VAMSASXML)) e.add(new String(el.getName())); //
\r
302 * avoid references } while (entries.hasMoreElements()); } } else
\r
304 Enumeration entries = jfile.getEntries();
\r
305 if (entries != null && entries.hasMoreElements()) {
\r
307 ZipEntry el = (ZipEntry) entries.nextElement();
\r
308 if (!el.getName().equals(VAMSASDOC) && !el.getName().equals(VAMSASXML))
\r
309 e.add(new String(el.getName())); // avoid references
\r
310 } while (entries.hasMoreElements());
\r
318 * @see java.util.jar.JarFile#getInputStream(java.util.zip.ZipEntry)
\r
320 private InputStream getInputStream(ZipEntry ze) throws IOException {
\r
322 return jfile.getInputStream(ze);
\r
329 * @see java.util.jar.JarFile#getJarEntry(java.lang.String)
\r
331 private ZipEntry getJarEntry(String name) {
\r
333 return jfile.getEntry(name);
\r