4 package org.vamsas.client.simpleclient;
6 import java.io.ByteArrayInputStream;
7 import java.io.ByteArrayOutputStream;
8 import java.io.DataInput;
9 import java.io.DataInputStream;
10 import java.io.DataOutput;
11 import java.io.InputStream;
12 import java.util.Vector;
13 import java.util.jar.JarInputStream;
15 import org.apache.commons.logging.Log;
16 import org.apache.commons.logging.LogFactory;
17 import org.vamsas.client.IClientAppdata;
18 import org.vamsas.objects.core.AppData;
19 import org.vamsas.objects.core.ApplicationData;
20 import org.vamsas.objects.core.User;
21 import org.vamsas.objects.utils.AppDataReference;
25 * Access interface to data chunks read from a VamsasArchiveReader stream
26 * (or byte buffer input stream) or written to a VamsasArchive stream.
27 * // TODO: get VamsasArchiveReader from sclient
29 public class SimpleClientAppdata implements IClientAppdata {
30 private static Log log = LogFactory.getLog(SimpleClientAppdata.class);
32 * has the session's document been accessed to get the AppData entrys?
34 protected boolean accessedDocument = false;
36 * has the user datablock been modified ?
38 protected boolean modifiedUserData = false;
40 * has the apps global datablock been modified ?
42 protected boolean modifiedAppData = false;
44 ClientDocument clientdoc;
47 * - accessed ClientAppdata
48 * - accessed UserAppdata
49 * => inputStream from embedded xml or jar entry of backup has been created
52 * => an output stream has been created and written to - or a data chunk has been written.
53 * - need flag for switching between embedded and jar entry mode ? - always write a jar entry for a stream.
54 * - need code for rewind and overwriting if the set*Appdata methods are called more than once.
55 * - need flags for streams to except a call to set*Appdata when an output stream exists and is open.
57 * @param clientdoc The ClientDocument instance that this IClientAppData is accessing
59 protected SimpleClientAppdata(ClientDocument clientdoc) {
60 if (clientdoc==null) {
61 log.fatal("Implementation error - Null ClientDocument for SimpleClientAppdata construction.");
62 throw new Error("Implementation error - Null ClientDocument for SimpleClientAppdata construction.");
64 this.clientdoc = clientdoc;
67 * set by extractAppData
69 protected ApplicationData appsGlobal = null;
71 * set by extractAppData
73 protected User usersData = null;
75 * gets appropriate app data for the application, if it exists in this dataset
76 * Called by every accessor to ensure data has been retrieved from document.
78 private void extractAppData(org.vamsas.objects.core.VamsasDocument doc) {
80 log.debug("extractAppData called for null document object");
83 if (accessedDocument) {
86 Vector apldataset = AppDataReference.getUserandApplicationsData(
87 doc, clientdoc.sclient.getUserHandle(), clientdoc.sclient.getClientHandle());
88 accessedDocument = true;
89 if (apldataset!=null) {
90 if (apldataset.size()>0) {
91 AppData clientdat = (AppData) apldataset.get(0);
92 if (clientdat instanceof ApplicationData) {
93 appsGlobal = (ApplicationData) clientdat;
94 modifiedAppData = false;
95 if (apldataset.size()>1) {
96 clientdat = (AppData) apldataset.get(1);
97 if (clientdat instanceof User) {
98 usersData = (User) clientdat;
99 modifiedUserData = false;
101 if (apldataset.size()>2)
102 log.info("Ignoring additional ("+(apldataset.size()-2)+") AppDatas returned by document appdata query.");
105 log.warn("Unexpected entry in AppDataReference query: id="+clientdat.getVorbaId()+" type="+clientdat.getClass().getName());
107 apldataset.removeAllElements(); // destroy references.
112 * LATER: generalize this for different low-level session implementations (it may not always be a Jar)
117 private JarInputStream getAppDataStream(AppData appdata, VamsasArchiveReader docreader) {
118 String entryRef = appdata.getDataReference();
119 if (entryRef!=null) {
120 log.debug("Resolving appData reference +"+entryRef);
121 InputStream entry = docreader.getAppdataStream(entryRef);
123 if (entry instanceof JarInputStream) {
124 return (JarInputStream) entry;
126 log.warn("Implementation problem - docreader didn't return a JarInputStream entry.");
129 log.debug("GetAppDataStream called for an AppData without a data reference.");
134 * yuk - size of buffer used for slurping appData JarEntry into a byte array.
136 private final int _TRANSFER_BUFFER=4096*4;
139 * Resolve AppData object to a byte array.
141 * @param archiveReader
142 * @return null or the application data as a byte array
144 private byte[] getAppDataAsByteArray(AppData appdata, VamsasArchiveReader docreader) {
145 if (appdata.getData()==null) {
146 // resolve and load data
147 JarInputStream entry = getAppDataStream(appdata, docreader);
148 ByteArrayOutputStream bytes = new ByteArrayOutputStream();
150 byte buff[] = new byte[_TRANSFER_BUFFER];
152 while (entry.available()>0) {
153 int len = entry.read(buff, olen, _TRANSFER_BUFFER);
154 bytes.write(buff, 0, len);
158 } catch (Exception e) {
159 log.warn("Unexpected exception - probable truncation when accessing VamsasDocument entry "+appdata.getDataReference(), e);
161 if (bytes.size()>0) {
162 // LATER: deal with probable OutOfMemoryErrors here
163 log.debug("Got "+bytes.size()+" bytes from AppDataReference "+appdata.getDataReference());
164 byte data[] = bytes.toByteArray();
170 log.debug("Returning inline AppData block for "+appdata.getVorbaId());
171 return appdata.getData();
175 * internal method for getting a DataInputStream from an AppData object.
178 * @return data in object or null if no data is accessible
180 private DataInput getAppDataAsDataInputStream(AppData appdata, VamsasArchiveReader docreader) {
182 String entryRef = appdata.getDataReference();
183 if (entryRef!=null) {
184 log.debug("Resolving AppData reference for "+entryRef);
185 InputStream jstrm = docreader.getAppdataStream(entryRef);
187 return new AppDataInputStream(jstrm);
189 log.debug("Returning null input stream for unresolved reference ("+entryRef+") id="+appdata.getVorbaId());
193 // return a byteArray input stream
194 byte[] data=appdata.getData();
196 ByteArrayInputStream stream = new ByteArrayInputStream(data);
197 return new DataInputStream(stream);
199 log.debug("Returning null input stream for empty Appdata data block in id="+appdata.getVorbaId());
204 log.debug("Returning null DataInputStream for appdata entry:"+appdata.getVorbaId());
210 * internal method for getting ByteArray from AppData object
211 * @param clientOrUser - true for returning userData, otherwise return Client AppData.
212 * @return null or byte array
214 private byte[] _getappdataByteArray(boolean clientOrUser) {
216 throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
220 appdName = "Client's Appdata";
222 appdName = "User's Appdata";
224 log.debug("getting "+appdName+" as a byte array");
225 extractAppData(clientdoc.getVamsasDocument());// TODO: get VamsasArchiveReader from sclient
233 log.debug("Trying to resolve "+appdName+" object to byte array.");
234 data = getAppDataAsByteArray(object, clientdoc.getVamsasArchiveReader());
237 log.debug("Returning null for "+appdName+"ClientAppdata byte[] array");
243 * common method for Client and User AppData->InputStream accessor
244 * @param clientOrUser - the appData to resolve - false for client, true for user appdata.
245 * @return null or the DataInputStream desired.
247 private DataInput _getappdataInputStream(boolean clientOrUser) {
249 throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
252 appdName = "Client's Appdata";
254 appdName = "User's Appdata";
256 if (log.isDebugEnabled())
257 log.debug("getting "+appdName+" as an input stream.");
258 extractAppData(clientdoc.getVamsasDocument());
266 log.debug("Trying to resolve ClientAppdata object to an input stream.");
267 return getAppDataAsDataInputStream(object, clientdoc.getVamsasArchiveReader());
269 log.debug("getClientInputStream returning null.");
273 * @see org.vamsas.client.IClientAppdata#getClientAppdata()
275 public byte[] getClientAppdata() {
276 return _getappdataByteArray(false);
279 * @see org.vamsas.client.IClientAppdata#getClientInputStream()
281 public DataInput getClientInputStream() {
282 return _getappdataInputStream(false);
286 * @see org.vamsas.client.IClientAppdata#getUserAppdata()
288 public byte[] getUserAppdata() {
289 return _getappdataByteArray(true);
293 * @see org.vamsas.client.IClientAppdata#getUserInputStream()
295 public DataInput getUserInputStream() {
296 return _getappdataInputStream(true);
299 * methods for writing new AppData entries.
303 * @see org.vamsas.client.IClientAppdata#getClientOutputStream()
305 public DataOutput getClientOutputStream() {
307 throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
308 // TODO Auto-generated method stub
313 * @see org.vamsas.client.IClientAppdata#getUserOutputStream()
315 public DataOutput getUserOutputStream() {
317 throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
318 // TODO Auto-generated method stub
323 * @see org.vamsas.client.IClientAppdata#hasClientAppdata()
325 public boolean hasClientAppdata() {
327 throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
328 // TODO Auto-generated method stub
333 * @see org.vamsas.client.IClientAppdata#hasUserAppdata()
335 public boolean hasUserAppdata() {
337 throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
338 // TODO Auto-generated method stub
343 * @see org.vamsas.client.IClientAppdata#setClientAppdata(byte[])
345 public void setClientAppdata(byte[] data) {
347 throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
348 // TODO Auto-generated method stub
353 * @see org.vamsas.client.IClientAppdata#setUserAppdata(byte[])
355 public void setUserAppdata(byte[] data) {
357 throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
358 // TODO Auto-generated method stub
362 * @see java.lang.Object#finalize()
364 protected void finalize() throws Throwable {
365 // TODO Auto-generated method stub