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 java.util.jar.JarEntry;
14 import java.util.jar.JarFile;
15 import java.util.jar.JarInputStream;
16 import java.util.jar.JarOutputStream;
17 import java.util.zip.ZipEntry;
18 import java.util.zip.ZipInputStream;
20 import org.apache.commons.logging.Log;
21 import org.apache.commons.logging.LogFactory;
23 import uk.ac.vamsas.objects.utils.document.VersionEntries;
25 * Basic methods for accessing an existing Vamsas Archive,
26 * and Jar entry names for creating new vamsas archives.
31 public class VamsasArchiveReader {
32 private static Log log = LogFactory.getLog(VamsasArchiveReader.class);
34 boolean stream=false; // true if we are seeking on the stream.
35 RandomAccessFile rfile;
36 ZipInputStream jstream=null;
37 Hashtable strmentries = null;
38 private void streamInit() {
39 //throw new Error("VamsasArchiveReader(Stream) Not implemented!");
41 log.debug("Skipping init for Jar Stream input.");
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 if (vamsasfile.exists()) {
74 jfile=new JarFile(vamsasfile);
77 log.debug("non-serious? couldn't open new JarFile on "+vamsasfile,e);
84 * in an ideal world - this constructor will create a reader object
85 * for the locked file's random access stream.
89 public VamsasArchiveReader(Lock vamsaslock) {
90 // LATER: implement or remove
91 if (vamsaslock==null || !vamsaslock.isLocked())
92 throw new Error("IMPLEMENTATION ERROR: Cannot create a VamsasArchiveReader without a valid lock.");
93 // throw new Error("VamsasArchiveReading from locked IO stream not yet implemented.");
95 rfile = vamsaslock.getRaFile();
96 } catch (Exception e) {
97 log.warn("Unexpected IO Exception when accessing locked vamsas archive stream "+vamsaslock.target,e);
102 throw new Error("Failed to open archive from Locked random access stream.");
106 * the vamsas document version(s) handled by this Reader
108 final public static String DOCUMENT_VERSION=VersionEntries.BETA_VERSION;
110 * name of the jarEntry containing a well formatted vamsas XML Document
113 final public static String VAMSASDOC="vamsasDocument.xml";
116 * name of the jarEntry containing a root VAMSAS element, and containing a
117 * random sequence of VAMSAS DataSet elements
120 final public static String VAMSASXML="vamsas.xml";
122 * seeks jstream to the given entry name and reads it.
126 private JarEntry seekEntry(String entryname) {
129 if (!strmentries.containsKey(entryname))
131 Long entrypos = (Long) strmentries.get(entryname);
132 if (entrypos==null) {
133 log.error("Null entry position for "+entryname);
139 jstream = new ZipInputStream(new FileInputStream(rfile.getFD()));
140 ZipEntry entry = null;
141 long epos = entrypos.longValue();
143 entry = jstream.getNextEntry();
144 } while (entry!=null && --epos>=0);
145 // rfile.seek(entrypos.longValue());
146 // make a Jar entry from a zip entry.
147 return new JarEntry(entry);
149 catch (Exception e) {
150 log.warn("Whilst seeking for "+entryname, e);
156 * @return JarEntry for VamsasArchiveReader.VAMSASDOC
158 protected JarEntry getVamsasDocumentEntry() {
159 return getJarEntry(VAMSASDOC);
163 * @return JarEntry for VamsasArchiveReader.VAMSASXML
165 protected JarEntry getVamsasXmlEntry() {
166 return getJarEntry(VAMSASXML);
169 * Test for valid vamsas document archive
170 * @return true if getVamsasDocumentStream will return a stream likely to contain valid XML
172 public boolean isValid() {
173 // 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
174 if (jfile!=null || jstream!=null)
175 return (getVamsasDocumentEntry()!=null);
180 protected JarEntry getAppdataEntry(String AppdataRef) {
182 if ((jfile==null && jstream==null) || !isValid() || (entry=getJarEntry(AppdataRef))==null)
188 public InputStream getAppdataStream(String AppdataRef) {
189 JarEntry entry=getAppdataEntry(AppdataRef);
192 return getInputStream(entry);
193 } catch (IOException e) {
194 log.error("Failed when opening AppdataStream for "+AppdataRef, e);
199 * get the VamsasDocument input stream, if it exists.
200 * @return null or valid input stream
202 public InputStream getVamsasDocumentStream() {
204 if ((jfile==null && jstream==null) || !isValid())
207 vdoc = getInputStream(getVamsasDocumentEntry());
208 } catch (IOException e) {
209 log.error("Whilst geting document stream",e);
216 * get the VamsasXML input stream, if it exists.
217 * Note: Deprecated beyond our prealpha testing.
218 * @return null or valid input stream.
221 public InputStream getVamsasXmlStream() {
222 // log.warn("Deprecated call");
223 JarEntry xmle=getVamsasXmlEntry();
228 vdoc = getInputStream(xmle);
229 } catch (IOException e) {
230 log.error("Whilst getting VamsasXmlStream",e);
237 * silently close the jar file.
240 public void close() {
244 } catch (IOException e) {
245 log.error("Whilst closing JarFile "+jfile.getName(), e);
250 jstream.closeEntry();
252 // LATER: reference counting for random access file instances is necessary.
254 catch (Exception e) {
255 log.error("Whilst finishing reading from jar input stream",e);
261 * returns all entries not matching the filespec of a vamsas xml entry
262 * @return array of entries.
264 public Vector getExtraEntries() {
265 if ((jfile==null && jstream==null)|| !isValid())
267 Vector e = new Vector();
269 Enumeration entries = strmentries.keys();
270 if (entries!=null && entries.hasMoreElements()) {
272 JarEntry el = (JarEntry) entries.nextElement();
273 if (!el.getName().equals(VAMSASDOC) && !el.getName().equals(VAMSASXML))
274 e.add(new String(el.getName())); // avoid references
275 } while (entries.hasMoreElements());
278 Enumeration entries = jfile.entries();
279 if (entries!=null && entries.hasMoreElements()) {
281 JarEntry el = (JarEntry) entries.nextElement();
282 if (!el.getName().equals(VAMSASDOC) && !el.getName().equals(VAMSASXML))
283 e.add(new String(el.getName())); // avoid references
284 } while (entries.hasMoreElements());
292 * @see java.util.jar.JarFile#getInputStream(java.util.zip.ZipEntry)
294 private InputStream getInputStream(ZipEntry ze) throws IOException {
296 return jfile.getInputStream(ze);
298 seekEntry(ze.getName());
299 return new AppDataInputStream(jstream);
305 * @see java.util.jar.JarFile#getJarEntry(java.lang.String)
307 private JarEntry getJarEntry(String name) {
309 return jfile.getJarEntry(name);
311 return seekEntry(name);