1 package uk.ac.vamsas.client.simpleclient;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.io.BufferedInputStream;
7 import java.io.FileInputStream;
8 import java.io.RandomAccessFile;
9 import java.util.Enumeration;
10 import java.util.Hashtable;
11 import java.util.Iterator;
12 import java.util.Vector;
13 import org.apache.tools.zip.*;
14 import org.apache.commons.logging.Log;
15 import org.apache.commons.logging.LogFactory;
17 import uk.ac.vamsas.client.AppDataInputStream;
18 import uk.ac.vamsas.objects.utils.document.VersionEntries;
20 * Basic methods for accessing an existing Vamsas Archive,
21 * and Jar entry names for creating new vamsas archives.
26 public class VamsasArchiveReader {
27 private static final int JARFILE_OPEN_RETRIES = 50;
28 private static final int JARFILE_OPEN_RETRYWAIT = 1;
29 private static Log log = LogFactory.getLog(VamsasArchiveReader.class);
31 String jfileName="randomAccessFile";
32 boolean stream=false; // true if we are seeking on the stream.
33 RandomAccessFile rfile;
34 // ZipInputStream jstream=null;
35 Hashtable strmentries = null;
36 private void streamInit() {
37 //throw new Error("VamsasArchiveReader(Stream) Not implemented!");
39 log.debug("Skipping init for Jar Stream input.");
42 throw new Error("Implementation error - we don't do streams - only files or RA files");
44 /*strmentries = new Hashtable();
45 log.debug("Jar Stream input Initialisation");
48 // no buffering - we need to be able to move around the random access stream.
49 jstream = new ZipInputStream(new FileInputStream(rfile.getFD())); // no manifest (probably)
50 if (jstream.available()==0)
51 log.warn("Can't read from JarInputStream (Locked stream!)");
55 if ((entry=jstream.getNextEntry())!=null) {
56 if (strmentries.containsKey(entry.getName())) {
57 log.info("Only recording last of duplicate entries '"+entry.getName()+"'");
59 strmentries.put(entry.getName(), new Long(pos++));
62 } while (entry!=null);
65 log.warn("Exceptions during init!",e);
70 public VamsasArchiveReader(File vamsasfile) {
72 int retries=JARFILE_OPEN_RETRIES;
74 if (vamsasfile.exists()) {
75 while (jfile==null && --retries>0)
78 jfile=new ZipFile(vamsasfile);
79 jfileName = vamsasfile.toString();
85 Thread.sleep(JARFILE_OPEN_RETRYWAIT);
86 } catch (Exception w) {};
89 if (jfile==null && ex!=null)
91 log.debug("non-serious? Exceptions when opening JarFile at "+vamsasfile,ex);
96 * in an ideal world - this constructor will create a reader object
97 * for the locked file's random access stream.
101 public VamsasArchiveReader(Lock vamsaslock) {
103 if (vamsaslock==null || !vamsaslock.isLocked())
104 throw new Error("IMPLEMENTATION ERROR: Cannot create a VamsasArchiveReader without a valid lock.");
105 // throw new Error("VamsasArchiveReading from locked IO stream not yet implemented.");
107 rfile = vamsaslock.getRaFile();
108 jfile = new ZipFile(rfile);
109 if (vamsaslock.target!=null)
110 jfileName = vamsaslock.target.toString();
111 } catch (Exception e) {
114 log.warn("Unexpected IO Exception when accessing locked vamsas archive stream "+vamsaslock.target,e);
119 throw new Error("Failed to open archive from Locked random access stream.");
124 * the vamsas document version(s) handled by this Reader
126 final public static String DOCUMENT_VERSION=VersionEntries.BETA_VERSION;
128 * name of the jarEntry containing a well formatted vamsas XML Document
131 final public static String VAMSASDOC="vamsasDocument.xml";
134 * name of the jarEntry containing a root VAMSAS element, and containing a
135 * random sequence of VAMSAS DataSet elements
138 final public static String VAMSASXML="vamsas.xml";
140 * seeks jstream to the given entry name and reads it.
143 private JarEntry seekEntry(String entryname) {
146 if (!strmentries.containsKey(entryname))
148 Long entrypos = (Long) strmentries.get(entryname);
149 if (entrypos==null) {
150 log.error("Null entry position for "+entryname);
156 jstream = new ZipInputStream(new FileInputStream(rfile.getFD()));
157 ZipEntry entry = null;
158 long epos = entrypos.longValue();
160 entry = jstream.getNextEntry();
161 } while (entry!=null && --epos>=0);
162 // rfile.seek(entrypos.longValue());
163 // make a Jar entry from a zip entry.
164 return new JarEntry(entry);
166 catch (Exception e) {
167 log.warn("Whilst seeking for "+entryname, e);
174 * @return JarEntry for VamsasArchiveReader.VAMSASDOC
176 protected ZipEntry getVamsasDocumentEntry() {
177 return getJarEntry(VAMSASDOC);
181 * @return JarEntry for VamsasArchiveReader.VAMSASXML
183 protected ZipEntry getVamsasXmlEntry() {
184 return getJarEntry(VAMSASXML);
187 * Test for valid vamsas document archive
188 * @return true if getVamsasDocumentStream will return a stream likely to contain valid XML
190 public boolean isValid() {
191 // 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
192 if (jfile!=null) // || jstream!=null)
193 return (getVamsasDocumentEntry()!=null);
198 protected ZipEntry getAppdataEntry(String AppdataRef) {
200 if (jfile==null || !isValid() || (entry=getJarEntry(AppdataRef))==null)
206 public InputStream getAppdataStream(String AppdataRef) {
207 ZipEntry entry=getAppdataEntry(AppdataRef);
210 return getInputStream(entry);
211 } catch (IOException e) {
212 log.error("Failed when opening AppdataStream for "+AppdataRef, e);
217 * get the VamsasDocument input stream, if it exists.
218 * @return null or valid input stream
220 public InputStream getVamsasDocumentStream() {
222 if (jfile==null || !isValid())
225 vdoc = getInputStream(getVamsasDocumentEntry());
226 } catch (IOException e) {
227 log.error("Whilst geting document stream",e);
234 * get the VamsasXML input stream, if it exists.
235 * Note: Deprecated beyond our prealpha testing.
236 * @return null or valid input stream.
239 public InputStream getVamsasXmlStream() {
240 // log.warn("Deprecated call");
241 ZipEntry xmle=getVamsasXmlEntry();
246 vdoc = getInputStream(xmle);
247 } catch (IOException e) {
248 log.error("Whilst getting VamsasXmlStream",e);
255 * silently close the jar file.
258 public void close() {
264 catch (Exception e) {
265 log.error("Whilst closing JarFile "+jfileName, e);
271 * returns all entries not matching the filespec of a vamsas xml entry
272 * @return array of entries.
274 public Vector getExtraEntries() {
275 if (jfile==null || !isValid())
277 Vector e = new Vector();
278 /*if (jstream!=null) {
279 Enumeration entries = strmentries.keys();
280 if (entries!=null && entries.hasMoreElements()) {
282 JarEntry el = (JarEntry) entries.nextElement();
283 if (!el.getName().equals(VAMSASDOC) && !el.getName().equals(VAMSASXML))
284 e.add(new String(el.getName())); // avoid references
285 } while (entries.hasMoreElements());
288 Enumeration entries = jfile.getEntries();
289 if (entries!=null && entries.hasMoreElements()) {
291 ZipEntry el = (ZipEntry) entries.nextElement();
292 if (!el.getName().equals(VAMSASDOC) && !el.getName().equals(VAMSASXML))
293 e.add(new String(el.getName())); // avoid references
294 } while (entries.hasMoreElements());
300 * @see java.util.jar.JarFile#getInputStream(java.util.zip.ZipEntry)
302 private InputStream getInputStream(ZipEntry ze) throws IOException {
304 return jfile.getInputStream(ze);
309 * @see java.util.jar.JarFile#getJarEntry(java.lang.String)
311 private ZipEntry getJarEntry(String name) {
313 return jfile.getEntry(name);