*/
package org.vamsas.client.simpleclient;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.DataInput;
+import java.io.DataInputStream;
import java.io.DataOutput;
+import java.io.InputStream;
import java.util.Vector;
+import java.util.jar.JarInputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
* @author jimp
* Access interface to data chunks read from a VamsasArchiveReader stream
* (or byte buffer input stream) or written to a VamsasArchive stream.
+ * // TODO: get VamsasArchiveReader from sclient
*/
public class SimpleClientAppdata implements IClientAppdata {
private static Log log = LogFactory.getLog(SimpleClientAppdata.class);
-
+ /**
+ * has the session's document been accessed to get the AppData entrys?
+ */
+ protected boolean accessedDocument = false;
+ /**
+ * has the user datablock been modified ?
+ */
+ protected boolean modifiedUserData = false;
+ /**
+ * has the apps global datablock been modified ?
+ */
+ protected boolean modifiedAppData = false;
+
ClientDocument clientdoc;
/**
* state flags
this.clientdoc = clientdoc;
}
/**
+ * set by extractAppData
+ */
+ protected ApplicationData appsGlobal = null;
+ /**
+ * set by extractAppData
+ */
+ protected User usersData = null;
+ /**
* gets appropriate app data for the application, if it exists in this dataset
- *
+ * Called by every accessor to ensure data has been retrieved from document.
*/
- private void extractAppData() {
- org.vamsas.objects.core.VamsasDocument doc = null;
+ private void extractAppData(org.vamsas.objects.core.VamsasDocument doc) {
+ if (doc==null) {
+ log.debug("extractAppData called for null document object");
+ return;
+ }
+ if (accessedDocument) {
+ return;
+ }
Vector apldataset = AppDataReference.getUserandApplicationsData(
doc, clientdoc.sclient.getUserHandle(), clientdoc.sclient.getClientHandle());
- ApplicationData appsglobal=null;
- User usersdata = null;
+ accessedDocument = true;
if (apldataset!=null) {
if (apldataset.size()>0) {
AppData clientdat = (AppData) apldataset.get(0);
if (clientdat instanceof ApplicationData) {
- appsglobal = (ApplicationData) clientdat;
+ appsGlobal = (ApplicationData) clientdat;
+ modifiedAppData = false;
if (apldataset.size()>1) {
clientdat = (AppData) apldataset.get(1);
- if (clientdat instanceof User)
- usersdata = (User) clientdat;
+ if (clientdat instanceof User) {
+ usersData = (User) clientdat;
+ modifiedUserData = false;
+ }
if (apldataset.size()>2)
log.info("Ignoring additional ("+(apldataset.size()-2)+") AppDatas returned by document appdata query.");
}
} else {
log.warn("Unexpected entry in AppDataReference query: id="+clientdat.getVorbaId()+" type="+clientdat.getClass().getName());
}
+ apldataset.removeAllElements(); // destroy references.
}
}
}
-
- /* (non-Javadoc)
- * @see org.vamsas.client.IClientAppdata#getClientAppdata()
+ /**
+ * LATER: generalize this for different low-level session implementations (it may not always be a Jar)
+ * @param appdata
+ * @param docreader
+ * @return
*/
- public byte[] getClientAppdata() {
- // TODO Auto-generated method stub
+ private JarInputStream getAppDataStream(AppData appdata, VamsasArchiveReader docreader) {
+ String entryRef = appdata.getDataReference();
+ if (entryRef!=null) {
+ log.debug("Resolving appData reference +"+entryRef);
+ InputStream entry = docreader.getAppdataStream(entryRef);
+ if (entry!=null) {
+ if (entry instanceof JarInputStream) {
+ return (JarInputStream) entry;
+ }
+ log.warn("Implementation problem - docreader didn't return a JarInputStream entry.");
+ }
+ } else {
+ log.debug("GetAppDataStream called for an AppData without a data reference.");
+ }
return null;
}
+ /**
+ * yuk - size of buffer used for slurping appData JarEntry into a byte array.
+ */
+ private final int _TRANSFER_BUFFER=4096*4;
- /* (non-Javadoc)
- * @see org.vamsas.client.IClientAppdata#getClientInputStream()
+ /**
+ * Resolve AppData object to a byte array.
+ * @param appdata
+ * @param archiveReader
+ * @return null or the application data as a byte array
*/
- public DataInput getClientInputStream() {
- // TODO Auto-generated method stub
+ private byte[] getAppDataAsByteArray(AppData appdata, VamsasArchiveReader docreader) {
+ if (appdata.getData()==null) {
+ // resolve and load data
+ JarInputStream entry = getAppDataStream(appdata, docreader);
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ try {
+ byte buff[] = new byte[_TRANSFER_BUFFER];
+ int olen=0;
+ while (entry.available()>0) {
+ int len = entry.read(buff, olen, _TRANSFER_BUFFER);
+ bytes.write(buff, 0, len);
+ olen+=len;
+ }
+ buff=null;
+ } catch (Exception e) {
+ log.warn("Unexpected exception - probable truncation when accessing VamsasDocument entry "+appdata.getDataReference(), e);
+ }
+ if (bytes.size()>0) {
+ // LATER: deal with probable OutOfMemoryErrors here
+ log.debug("Got "+bytes.size()+" bytes from AppDataReference "+appdata.getDataReference());
+ byte data[] = bytes.toByteArray();
+ bytes = null;
+ return data;
+ }
+ return null;
+ } else {
+ log.debug("Returning inline AppData block for "+appdata.getVorbaId());
+ return appdata.getData();
+ }
+ }
+ /**
+ * internal method for getting a DataInputStream from an AppData object.
+ * @param appdata
+ * @param docreader
+ * @return data in object or null if no data is accessible
+ */
+ private DataInput getAppDataAsDataInputStream(AppData appdata, VamsasArchiveReader docreader) {
+ if (appdata!=null) {
+ String entryRef = appdata.getDataReference();
+ if (entryRef!=null) {
+ log.debug("Resolving AppData reference for "+entryRef);
+ InputStream jstrm = docreader.getAppdataStream(entryRef);
+ if (jstrm!=null)
+ return new AppDataInputStream(jstrm);
+ else {
+ log.debug("Returning null input stream for unresolved reference ("+entryRef+") id="+appdata.getVorbaId());
+ return null;
+ }
+ } else {
+ // return a byteArray input stream
+ byte[] data=appdata.getData();
+ if (data.length>0) {
+ ByteArrayInputStream stream = new ByteArrayInputStream(data);
+ return new DataInputStream(stream);
+ } else {
+ log.debug("Returning null input stream for empty Appdata data block in id="+appdata.getVorbaId());
+ return null;
+ }
+ }
+ } else {
+ log.debug("Returning null DataInputStream for appdata entry:"+appdata.getVorbaId());
+ }
return null;
}
- /* (non-Javadoc)
- * @see org.vamsas.client.IClientAppdata#getClientOutputStream()
+ /**
+ * internal method for getting ByteArray from AppData object
+ * @param clientOrUser - true for returning userData, otherwise return Client AppData.
+ * @return null or byte array
*/
- public DataOutput getClientOutputStream() {
- // TODO Auto-generated method stub
+ private byte[] _getappdataByteArray(boolean clientOrUser) {
+ if (clientdoc==null)
+ throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
+ byte[] data=null;
+ String appdName;
+ if (!clientOrUser) {
+ appdName = "Client's Appdata";
+ } else {
+ appdName = "User's Appdata";
+ }
+ log.debug("getting "+appdName+" as a byte array");
+ extractAppData(clientdoc.getVamsasDocument());// TODO: get VamsasArchiveReader from sclient
+ AppData object;
+ if (!clientOrUser) {
+ object = appsGlobal;
+ } else {
+ object = usersData;
+ }
+ if (object!=null) {
+ log.debug("Trying to resolve "+appdName+" object to byte array.");
+ data = getAppDataAsByteArray(object, clientdoc.getVamsasArchiveReader());
+ }
+ if (data == null)
+ log.debug("Returning null for "+appdName+"ClientAppdata byte[] array");
+ return data;
+
+ }
+
+ /**
+ * common method for Client and User AppData->InputStream accessor
+ * @param clientOrUser - the appData to resolve - false for client, true for user appdata.
+ * @return null or the DataInputStream desired.
+ */
+ private DataInput _getappdataInputStream(boolean clientOrUser) {
+ if (clientdoc==null)
+ throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
+ String appdName;
+ if (!clientOrUser) {
+ appdName = "Client's Appdata";
+ } else {
+ appdName = "User's Appdata";
+ }
+ if (log.isDebugEnabled())
+ log.debug("getting "+appdName+" as an input stream.");
+ extractAppData(clientdoc.getVamsasDocument());
+ AppData object;
+ if (!clientOrUser) {
+ object = appsGlobal;
+ } else {
+ object = usersData;
+ }
+ if (object!=null) {
+ log.debug("Trying to resolve ClientAppdata object to an input stream.");
+ return getAppDataAsDataInputStream(object, clientdoc.getVamsasArchiveReader());
+ }
+ log.debug("getClientInputStream returning null.");
return null;
}
+ /* (non-Javadoc)
+ * @see org.vamsas.client.IClientAppdata#getClientAppdata()
+ */
+ public byte[] getClientAppdata() {
+ return _getappdataByteArray(false);
+ }
+ /* (non-Javadoc)
+ * @see org.vamsas.client.IClientAppdata#getClientInputStream()
+ */
+ public DataInput getClientInputStream() {
+ return _getappdataInputStream(false);
+ }
/* (non-Javadoc)
* @see org.vamsas.client.IClientAppdata#getUserAppdata()
*/
public byte[] getUserAppdata() {
- // TODO Auto-generated method stub
- return null;
+ return _getappdataByteArray(true);
}
/* (non-Javadoc)
* @see org.vamsas.client.IClientAppdata#getUserInputStream()
*/
public DataInput getUserInputStream() {
+ return _getappdataInputStream(true);
+ }
+ /**
+ * methods for writing new AppData entries.
+ */
+
+ /* (non-Javadoc)
+ * @see org.vamsas.client.IClientAppdata#getClientOutputStream()
+ */
+ public DataOutput getClientOutputStream() {
+ if (clientdoc==null)
+ throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
// TODO Auto-generated method stub
return null;
}
* @see org.vamsas.client.IClientAppdata#getUserOutputStream()
*/
public DataOutput getUserOutputStream() {
+ if (clientdoc==null)
+ throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
// TODO Auto-generated method stub
return null;
}
* @see org.vamsas.client.IClientAppdata#hasClientAppdata()
*/
public boolean hasClientAppdata() {
+ if (clientdoc==null)
+ throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
// TODO Auto-generated method stub
return false;
}
* @see org.vamsas.client.IClientAppdata#hasUserAppdata()
*/
public boolean hasUserAppdata() {
+ if (clientdoc==null)
+ throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
// TODO Auto-generated method stub
return false;
}
* @see org.vamsas.client.IClientAppdata#setClientAppdata(byte[])
*/
public void setClientAppdata(byte[] data) {
+ if (clientdoc==null)
+ throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
// TODO Auto-generated method stub
}
* @see org.vamsas.client.IClientAppdata#setUserAppdata(byte[])
*/
public void setUserAppdata(byte[] data) {
+ if (clientdoc==null)
+ throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
// TODO Auto-generated method stub
}