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