1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kns.service.impl;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.kuali.rice.core.api.CoreApiServiceLocator;
20 import org.kuali.rice.core.api.encryption.EncryptionService;
21 import org.kuali.rice.kew.api.WorkflowDocument;
22 import org.kuali.rice.kew.exception.WorkflowException;
23 import org.kuali.rice.kew.util.KEWConstants;
24 import org.kuali.rice.kns.service.SessionDocumentService;
25 import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase;
26 import org.kuali.rice.krad.UserSession;
27 import org.kuali.rice.krad.bo.SessionDocument;
28 import org.kuali.rice.krad.dao.SessionDocumentDao;
29 import org.kuali.rice.krad.datadictionary.DocumentEntry;
30 import org.kuali.rice.krad.service.BusinessObjectService;
31 import org.kuali.rice.krad.service.DataDictionaryService;
32 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
33 import org.kuali.rice.krad.util.KualiLRUMap;
34 import org.springframework.beans.factory.InitializingBean;
35 import org.springframework.transaction.annotation.Transactional;
36
37 import java.io.ByteArrayInputStream;
38 import java.io.ByteArrayOutputStream;
39 import java.io.ObjectInputStream;
40 import java.io.ObjectOutputStream;
41 import java.sql.Timestamp;
42 import java.util.Collections;
43 import java.util.HashMap;
44 import java.util.Map;
45
46
47
48
49 @Deprecated
50 @Transactional
51 public class SessionDocumentServiceImpl implements SessionDocumentService, InitializingBean {
52 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(SessionDocumentServiceImpl.class);
53
54 protected static final String IP_ADDRESS = "ipAddress";
55 protected static final String PRINCIPAL_ID = "principalId";
56 protected static final String DOCUMENT_NUMBER = "documentNumber";
57 protected static final String SESSION_ID = "sessionId";
58
59 private Map<String, CachedObject> cachedObjects;
60 private EncryptionService encryptionService;
61 private int maxCacheSize;
62
63 private BusinessObjectService businessObjectService;
64 private DataDictionaryService dataDictionaryService;
65 private SessionDocumentDao sessionDocumentDao;
66
67 public static class CachedObject {
68 private UserSession userSession;
69 private String formKey;
70
71 CachedObject(UserSession userSession, String formKey) {
72 this.userSession = userSession;
73 this.formKey = formKey;
74 }
75
76 @Override
77 public String toString() {
78 return "CachedObject: principalId=" + userSession.getPrincipalId() + " / objectWithFormKey=" +
79 userSession.retrieveObject(formKey);
80 }
81
82 public UserSession getUserSession() {
83 return this.userSession;
84 }
85
86 public String getFormKey() {
87 return this.formKey;
88 }
89 }
90
91 @SuppressWarnings("unchecked")
92 public void afterPropertiesSet() throws Exception {
93 cachedObjects = Collections.synchronizedMap(new KualiLRUMap(maxCacheSize));
94 }
95
96
97
98
99
100
101 @Override
102 public KualiDocumentFormBase getDocumentForm(String documentNumber, String docFormKey, UserSession userSession,
103 String ipAddress) {
104 KualiDocumentFormBase documentForm = null;
105
106 LOG.debug("getDocumentForm KualiDocumentFormBase from db");
107 try {
108
109 documentForm = (KualiDocumentFormBase) retrieveDocumentForm(userSession, userSession.getKualiSessionId(),
110 documentNumber, ipAddress);
111
112
113 WorkflowDocument workflowDocument =
114 documentForm.getDocument().getDocumentHeader().getWorkflowDocument();
115 addDocumentToUserSession(userSession, workflowDocument);
116 } catch (Exception e) {
117 LOG.error("getDocumentForm failed for SessId/DocNum/PrinId/IP:" + userSession.getKualiSessionId() + "/" +
118 documentNumber + "/" + userSession.getPrincipalId() + "/" + ipAddress, e);
119 }
120
121 return documentForm;
122 }
123
124 protected Object retrieveDocumentForm(UserSession userSession, String sessionId, String documentNumber,
125 String ipAddress) throws Exception {
126 HashMap<String, String> primaryKeys = new HashMap<String, String>(4);
127 primaryKeys.put(SESSION_ID, sessionId);
128 if (documentNumber != null) {
129 primaryKeys.put(DOCUMENT_NUMBER, documentNumber);
130 }
131 primaryKeys.put(PRINCIPAL_ID, userSession.getPrincipalId());
132 primaryKeys.put(IP_ADDRESS, ipAddress);
133
134 SessionDocument sessionDoc = getBusinessObjectService().findByPrimaryKey(SessionDocument.class, primaryKeys);
135 if (sessionDoc != null) {
136 byte[] formAsBytes = sessionDoc.getSerializedDocumentForm();
137 if (sessionDoc.isEncrypted()) {
138 formAsBytes = getEncryptionService().decryptBytes(formAsBytes);
139 }
140 ByteArrayInputStream baip = new ByteArrayInputStream(formAsBytes);
141 ObjectInputStream ois = new ObjectInputStream(baip);
142
143 return ois.readObject();
144 }
145
146 return null;
147 }
148
149 @Override
150 public WorkflowDocument getDocumentFromSession(UserSession userSession, String docId) {
151 @SuppressWarnings("unchecked") Map<String, WorkflowDocument> workflowDocMap =
152 (Map<String, WorkflowDocument>) userSession
153 .retrieveObject(KEWConstants.WORKFLOW_DOCUMENT_MAP_ATTR_NAME);
154
155 if (workflowDocMap == null) {
156 workflowDocMap = new HashMap<String, WorkflowDocument>();
157 userSession.addObject(KEWConstants.WORKFLOW_DOCUMENT_MAP_ATTR_NAME, workflowDocMap);
158 return null;
159 }
160 return workflowDocMap.get(docId);
161 }
162
163
164
165
166
167 @Override
168 public void addDocumentToUserSession(UserSession userSession, WorkflowDocument document) {
169 @SuppressWarnings("unchecked") Map<String, WorkflowDocument> workflowDocMap =
170 (Map<String, WorkflowDocument>) userSession
171 .retrieveObject(KEWConstants.WORKFLOW_DOCUMENT_MAP_ATTR_NAME);
172 if (workflowDocMap == null) {
173 workflowDocMap = new HashMap<String, WorkflowDocument>();
174 }
175 workflowDocMap.put(document.getDocumentId(), document);
176 userSession.addObject(KEWConstants.WORKFLOW_DOCUMENT_MAP_ATTR_NAME, workflowDocMap);
177 }
178
179
180
181
182
183 @Override
184 public void purgeDocumentForm(String documentNumber, String docFormKey, UserSession userSession, String ipAddress) {
185 synchronized (userSession) {
186
187 LOG.debug("purge document form from session");
188 userSession.removeObject(docFormKey);
189 try {
190 LOG.debug("purge document form from database");
191 HashMap<String, String> primaryKeys = new HashMap<String, String>(4);
192 primaryKeys.put(SESSION_ID, userSession.getKualiSessionId());
193 primaryKeys.put(DOCUMENT_NUMBER, documentNumber);
194 primaryKeys.put(PRINCIPAL_ID, userSession.getPrincipalId());
195 primaryKeys.put(IP_ADDRESS, ipAddress);
196 getBusinessObjectService().deleteMatching(SessionDocument.class, primaryKeys);
197 } catch (Exception e) {
198 LOG.error("purgeDocumentForm failed for SessId/DocNum/PrinId/IP:" + userSession.getKualiSessionId() +
199 "/" + documentNumber + "/" + userSession.getPrincipalId() + "/" + ipAddress, e);
200 }
201 }
202 }
203
204
205
206
207
208 @Override
209 public void setDocumentForm(KualiDocumentFormBase form, UserSession userSession, String ipAddress) {
210 synchronized (userSession) {
211
212 String formKey = form.getFormKey();
213 String key = userSession.getKualiSessionId() + "-" + formKey;
214 cachedObjects.put(key, new CachedObject(userSession, formKey));
215
216 String documentNumber = form.getDocument().getDocumentNumber();
217
218 if (StringUtils.isNotBlank(documentNumber)) {
219 persistDocumentForm(form, userSession, ipAddress, userSession.getKualiSessionId(), documentNumber);
220 } else {
221 LOG.warn("documentNumber is null on form's document: " + form);
222 }
223 }
224 }
225
226 protected void persistDocumentForm(Object form, UserSession userSession, String ipAddress, String sessionId,
227 String documentNumber) {
228 try {
229 LOG.debug("set Document Form into database");
230 Timestamp currentTime = new Timestamp(System.currentTimeMillis());
231 ByteArrayOutputStream baos = new ByteArrayOutputStream();
232 ObjectOutputStream oos = new ObjectOutputStream(baos);
233 oos.writeObject(form);
234
235 byte[] formAsBytes = baos.toByteArray();
236 boolean encryptContent = false;
237
238 if ((form instanceof KualiDocumentFormBase) && ((KualiDocumentFormBase) form).getDocTypeName() != null) {
239 DocumentEntry documentEntry = getDataDictionaryService().getDataDictionary()
240 .getDocumentEntry(((KualiDocumentFormBase) form).getDocTypeName());
241 if (documentEntry != null) {
242 encryptContent = documentEntry.isEncryptDocumentDataInPersistentSessionStorage();
243 }
244 }
245 if (encryptContent) {
246 formAsBytes = getEncryptionService().encryptBytes(formAsBytes);
247 }
248
249
250
251 HashMap<String, String> primaryKeys = new HashMap<String, String>(4);
252 primaryKeys.put(SESSION_ID, sessionId);
253 primaryKeys.put(DOCUMENT_NUMBER, documentNumber);
254 primaryKeys.put(PRINCIPAL_ID, userSession.getPrincipalId());
255 primaryKeys.put(IP_ADDRESS, ipAddress);
256
257 SessionDocument sessionDocument =
258 getBusinessObjectService().findByPrimaryKey(SessionDocument.class, primaryKeys);
259 if (sessionDocument == null) {
260 sessionDocument = new SessionDocument();
261 sessionDocument.setSessionId(sessionId);
262 sessionDocument.setDocumentNumber(documentNumber);
263 sessionDocument.setPrincipalId(userSession.getPrincipalId());
264 sessionDocument.setIpAddress(ipAddress);
265 }
266 sessionDocument.setSerializedDocumentForm(formAsBytes);
267 sessionDocument.setEncrypted(encryptContent);
268 sessionDocument.setLastUpdatedDate(currentTime);
269
270 businessObjectService.save(sessionDocument);
271 } catch (Exception e) {
272 final String className = form != null ? form.getClass().getName() : "null";
273 LOG.error("setDocumentForm failed for SessId/DocNum/PrinId/IP/class:" + userSession.getKualiSessionId() +
274 "/" + documentNumber + "/" + userSession.getPrincipalId() + "/" + ipAddress + "/" + className, e);
275 }
276 }
277
278
279
280
281 @Override
282 public void purgeAllSessionDocuments(Timestamp expirationDate) {
283 sessionDocumentDao.purgeAllSessionDocuments(expirationDate);
284 }
285
286
287
288
289 protected SessionDocumentDao getSessionDocumentDao() {
290 return this.sessionDocumentDao;
291 }
292
293
294
295
296 public void setSessionDocumentDao(SessionDocumentDao sessionDocumentDao) {
297 this.sessionDocumentDao = sessionDocumentDao;
298 }
299
300
301
302
303 protected BusinessObjectService getBusinessObjectService() {
304 return this.businessObjectService;
305 }
306
307
308
309
310 public void setBusinessObjectService(BusinessObjectService businessObjectService) {
311 this.businessObjectService = businessObjectService;
312 }
313
314
315
316
317 public int getMaxCacheSize() {
318 return maxCacheSize;
319 }
320
321
322
323
324 public void setMaxCacheSize(int maxCacheSize) {
325 this.maxCacheSize = maxCacheSize;
326 }
327
328 protected EncryptionService getEncryptionService() {
329 if (encryptionService == null) {
330 encryptionService = CoreApiServiceLocator.getEncryptionService();
331 }
332 return encryptionService;
333 }
334
335 protected DataDictionaryService getDataDictionaryService() {
336 if (dataDictionaryService == null) {
337 dataDictionaryService = KRADServiceLocatorWeb.getDataDictionaryService();
338 }
339 return dataDictionaryService;
340 }
341 }