import java.util.Vector;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
this(archive, overwrite, vamsasdocument, null);
}
/**
+ * Constructor for accessing Files under file-lock management (ie a session file)
+ * @param archive
+ * @param vamsasdocument
+ * @param overwrite
+ * @throws IOException
+ */
+ public VamsasArchive(VamsasFile archive, boolean vamsasdocument, boolean overwrite) throws IOException {
+ this(archive.sessionFile, overwrite, vamsasdocument, archive);
+ }
+ /**
*
* @param archive file to write
* @param overwrite true if original contents should be deleted
this.vamsasdocument = vamsasdocument;
if (archive.exists() && !overwrite) {
this.original = archive;
- if (extantLock!=null)
+ if (extantLock!=null) {
this.odoclock = extantLock;
- else
- this.odoclock = new SessionFile(archive);
+ if (odoclock.fileLock==null || !odoclock.fileLock.isLocked())
+ odoclock.lockFile();
+ } else {
+ this.odoclock = new SessionFile(archive);
+ }
odoclock.lockFile(); // lock the file *immediatly*
this.archive = null; // archive will be a temp file when the open method is called
virginArchive=false;
else
rchive = new SessionFile(archive);
rchive.lockFile();
- if (rchive.fileLock==null || rchive.fileLock.rafile==null)
+ if (rchive.fileLock==null || rchive.fileLock.rafile==null || !rchive.fileLock.isLocked())
throw new IOException("Lock failed for new archive"+archive);
rchive.fileLock.rafile.setLength(0); // empty the archive.
virginArchive = true;
JarEntry je = new JarEntry(entry);
if (!addEntry(entry))
return false;
+ newarchive.flush();
newarchive.putNextEntry(je);
return true;
}
*/
public void closeArchive() throws IOException {
if (newarchive!=null) {
+ newarchive.flush();
newarchive.closeEntry();
if (!isDocumentWritten())
log.warn("Premature closure of archive '"+archive.getAbsolutePath()+"': No document has been written.");
- newarchive.close();
+ newarchive.finish();
updateOriginal();
closeAndReset();
} else {
rchive = new SessionFile(archive);
if (!rchive.lockFile())
throw new IOException("Failed to get lock on file "+archive);
- newarchive = new JarOutputStream(rchive.fileLock.getBufferedOutputStream(true));
+ Manifest newmanifest = new Manifest();
+ newarchive = new JarOutputStream(rchive.fileLock.getBufferedOutputStream(true), newmanifest);
entries = new Hashtable();
}
public void putVamsasDocument(VamsasDocument doc) throws IOException,
public void putVamsasDocument(VamsasDocument doc, VorbaIdFactory vorba) throws IOException,
org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException {
+ if (vamsasdocument)
+ doc.setVersion(VersionEntries.latestVersion()); // LATER: ensure this does the correct thing.
VorbaXmlBinder.putVamsasDocument(getDocumentOutputStream(), vorba, doc);
}
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 java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
import java.util.jar.JarOutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.vamsas.objects.utils.document.VersionEntries;
/**
* Basic methods for accessing an existing Vamsas Archive,
* and Jar entry names for creating new vamsas archives.
*/
public class VamsasArchiveReader {
private static Log log = LogFactory.getLog(VamsasArchiveReader.class);
- JarFile jfile;
+ JarFile jfile=null;
boolean stream=false; // true if we are seeking on the stream.
- RandomAccessFile rfile;
- JarInputStream jstream;
+ RandomAccessFile rfile;
+ ZipInputStream jstream=null;
+ Hashtable strmentries = null;
+ private void streamInit() {
+ if (!stream) {
+ log.debug("Skipping init for Jar Stream input.");
+ return;
+ }
+ 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;
+ do {
+ long pos = rfile.getFilePointer();
+ 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;
if (vamsasfile.exists()) {
public VamsasArchiveReader(Lock vamsaslock) {
rfile = vamsaslock.rafile;
stream = true;
- // TODO: Implement stream based JarFile access
- log.error("NOT IMPLEMENTED STREAM-BASED JAR ACCESS");
- throw new Error("Can't access a locked VamsasArchive file as a random access stream yet.");
- // rfile.seek(0);
-
+ 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="0.1";
+ final public static String DOCUMENT_VERSION=VersionEntries.BETA_VERSION;
/**
* name of the jarEntry containing a well formatted vamsas XML Document
*/
*/
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 {
+ rfile.seek(entrypos.longValue());
+ // make a Jar entry from a zip entry.
+
+ return new JarEntry(jstream.getNextEntry());
+ }
+ catch (Exception e) {
+ log.warn("Whilst seeking for "+entryname, e);
+ }
+ return null;
+ }
/**
*
* @return JarEntry for VamsasArchiveReader.VAMSASDOC
*/
protected JarEntry getVamsasDocumentEntry() {
- if (jfile!=null)
- return jfile.getJarEntry(VAMSASDOC);
- return null;
+ return getJarEntry(VAMSASDOC);
}
/**
*
* @return JarEntry for VamsasArchiveReader.VAMSASXML
*/
protected JarEntry getVamsasXmlEntry() {
- if (jfile!=null)
- return jfile.getJarEntry(VAMSASXML);
- return null;
+ 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() {
- if (jfile!=null)
- // 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
+ // 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 JarEntry getAppdataEntry(String AppdataRef) {
JarEntry entry;
- if (jfile==null || !isValid() || (entry=jfile.getJarEntry(AppdataRef))==null)
+ if ((jfile==null && jstream==null) || !isValid() || (entry=getJarEntry(AppdataRef))==null)
return null;
+
return entry;
}
JarEntry entry=getAppdataEntry(AppdataRef);
try {
if (entry!=null)
- return jfile.getInputStream(entry);
+ return getInputStream(entry);
} catch (IOException e) {
- System.err.println("Failed when opening AppdataStream for "+AppdataRef);
- e.printStackTrace(System.err);
+ log.error("Failed when opening AppdataStream for "+AppdataRef, e);
}
return null;
}
*/
public InputStream getVamsasDocumentStream() {
InputStream vdoc;
- if (jfile==null || !isValid())
+ if ((jfile==null && jstream==null) || !isValid())
return null;
try {
- vdoc = jfile.getInputStream(getVamsasDocumentEntry());
+ vdoc = getInputStream(getVamsasDocumentEntry());
} catch (IOException e) {
- e.printStackTrace(System.err);
+ log.error("Whilst geting document stream",e);
vdoc=null;
}
return vdoc;
if (xmle==null)
return null;
try {
- vdoc = jfile.getInputStream(xmle);
+ vdoc = getInputStream(xmle);
} catch (IOException e) {
- e.printStackTrace(System.err);
+ log.error("Whilst getting VamsasXmlStream",e);
vdoc=null;
}
return vdoc;
try {
jfile.close();
} catch (IOException e) {
- e.printStackTrace(System.err);
+ log.error("Whilst closing JarFile "+jfile.getName(), e);
+ }
+ }
+ if (jstream!=null) {
+ try {
+ jstream.closeEntry();
+ jstream=null;
+ // LATER: reference counting for random access file instances is necessary.
+ }
+ catch (Exception e) {
+ log.error("Whilst finishing reading from jar input stream",e);
}
}
}
* @return array of entries.
*/
public Vector getExtraEntries() {
- if (jfile==null || !isValid())
+ if ((jfile==null && jstream==null)|| !isValid())
return null;
- Enumeration entries = jfile.entries();
- if (entries!=null && entries.hasMoreElements()) {
- Vector e = new Vector();
- 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());
+ 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.entries();
+ 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());
+ }
return e;
}
return null;
}
-}
+
+ /* (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);
+ if (jstream!=null) {
+ seekEntry(ze.getName());
+ return new AppDataInputStream(jstream);
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.jar.JarFile#getJarEntry(java.lang.String)
+ */
+ private JarEntry getJarEntry(String name) {
+ if (jfile!=null)
+ return jfile.getJarEntry(name);
+ if (jstream!=null)
+ return seekEntry(name);
+ return null;
+ }
+ }