1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.web.controller;
17
18 import org.apache.commons.lang.ArrayUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.kuali.rice.core.api.util.RiceKeyConstants;
21 import org.kuali.rice.core.framework.parameter.ParameterConstants;
22 import org.kuali.rice.core.framework.services.CoreFrameworkServiceLocator;
23 import org.kuali.rice.kew.api.WorkflowDocument;
24 import org.kuali.rice.kew.exception.WorkflowException;
25 import org.kuali.rice.kew.util.KEWConstants;
26 import org.kuali.rice.kim.api.identity.Person;
27 import org.kuali.rice.krad.bo.AdHocRouteRecipient;
28 import org.kuali.rice.krad.bo.Attachment;
29 import org.kuali.rice.krad.bo.DocumentHeader;
30 import org.kuali.rice.krad.bo.Note;
31 import org.kuali.rice.krad.document.Document;
32 import org.kuali.rice.krad.document.MaintenanceDocument;
33 import org.kuali.rice.krad.document.authorization.DocumentAuthorizer;
34 import org.kuali.rice.krad.exception.DocumentAuthorizationException;
35 import org.kuali.rice.krad.exception.UnknownDocumentIdException;
36 import org.kuali.rice.krad.exception.ValidationException;
37 import org.kuali.rice.krad.question.ConfirmationQuestion;
38 import org.kuali.rice.krad.rule.event.AddNoteEvent;
39 import org.kuali.rice.krad.service.AttachmentService;
40 import org.kuali.rice.krad.service.BusinessObjectService;
41 import org.kuali.rice.krad.service.DataDictionaryService;
42 import org.kuali.rice.krad.service.DocumentHelperService;
43 import org.kuali.rice.krad.service.DocumentService;
44 import org.kuali.rice.krad.service.KRADServiceLocator;
45 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
46 import org.kuali.rice.krad.service.NoteService;
47 import org.kuali.rice.krad.uif.UifParameters;
48 import org.kuali.rice.krad.uif.container.CollectionGroup;
49 import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
50 import org.kuali.rice.krad.util.GlobalVariables;
51 import org.kuali.rice.krad.util.KRADConstants;
52 import org.kuali.rice.krad.util.KRADPropertyConstants;
53 import org.kuali.rice.krad.util.KRADUtils;
54 import org.kuali.rice.krad.util.NoteType;
55 import org.kuali.rice.krad.util.SessionTicket;
56 import org.kuali.rice.krad.web.form.DocumentFormBase;
57 import org.kuali.rice.krad.web.form.UifFormBase;
58 import org.springframework.util.FileCopyUtils;
59 import org.springframework.validation.BindingResult;
60 import org.springframework.web.bind.ServletRequestBindingException;
61 import org.springframework.web.bind.annotation.ModelAttribute;
62 import org.springframework.web.bind.annotation.RequestMapping;
63 import org.springframework.web.bind.annotation.RequestMethod;
64 import org.springframework.web.multipart.MultipartFile;
65 import org.springframework.web.servlet.ModelAndView;
66
67 import javax.servlet.http.HttpServletRequest;
68 import javax.servlet.http.HttpServletResponse;
69 import java.io.FileNotFoundException;
70 import java.io.IOException;
71 import java.io.InputStream;
72 import java.util.ArrayList;
73 import java.util.HashMap;
74 import java.util.Map;
75
76
77
78
79
80
81
82
83
84
85
86
87
88 public abstract class DocumentControllerBase extends UifControllerBase {
89 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DocumentControllerBase.class);
90
91
92
93 protected static final String[] DOCUMENT_LOAD_COMMANDS = { KEWConstants.ACTIONLIST_COMMAND,
94 KEWConstants.DOCSEARCH_COMMAND, KEWConstants.SUPERUSER_COMMAND, KEWConstants.HELPDESK_ACTIONLIST_COMMAND };
95
96 private BusinessObjectService businessObjectService;
97 private DataDictionaryService dataDictionaryService;
98 private DocumentService documentService;
99 private DocumentHelperService documentHelperService;
100 private AttachmentService attachmentService;
101 private NoteService noteService;
102
103 @Override
104 protected abstract Class<? extends DocumentFormBase> formType();
105
106
107
108
109
110
111
112
113
114
115 @RequestMapping(params = "methodToCall=docHandler")
116 public ModelAndView docHandler(@ModelAttribute("KualiForm") DocumentFormBase form, BindingResult result, HttpServletRequest request,
117 HttpServletResponse response) throws Exception {
118 String command = form.getCommand();
119
120
121 if (ArrayUtils.contains(DOCUMENT_LOAD_COMMANDS, command) && form.getDocId() != null) {
122 loadDocument(form);
123 }
124 else if (KEWConstants.INITIATE_COMMAND.equals(command)) {
125 createDocument(form);
126 }
127 else {
128 LOG.error("docHandler called with invalid parameters");
129 throw new IllegalStateException("docHandler called with invalid parameters");
130 }
131
132
133
134
135
136
137 return getUIFModelAndView(form);
138 }
139
140
141
142
143
144
145
146
147
148
149 protected void loadDocument(DocumentFormBase form) throws WorkflowException {
150 String docId = form.getDocId();
151
152 Document doc = null;
153 doc = getDocumentService().getByDocumentHeaderId(docId);
154 if (doc == null) {
155 throw new UnknownDocumentIdException(
156 "Document no longer exists. It may have been cancelled before being saved.");
157 }
158
159 WorkflowDocument workflowDocument = doc.getDocumentHeader().getWorkflowDocument();
160 if (!getDocumentHelperService().getDocumentAuthorizer(doc).canOpen(doc,
161 GlobalVariables.getUserSession().getPerson())) {
162 throw buildAuthorizationException("open", doc);
163 }
164
165
166
167 if (workflowDocument != doc.getDocumentHeader().getWorkflowDocument()) {
168 LOG.warn("Workflow document changed via canOpen check");
169 doc.getDocumentHeader().setWorkflowDocument(workflowDocument);
170 }
171
172 form.setDocument(doc);
173 WorkflowDocument workflowDoc = doc.getDocumentHeader().getWorkflowDocument();
174 form.setDocTypeName(workflowDoc.getDocumentTypeName());
175
176 KRADServiceLocatorWeb.getSessionDocumentService().addDocumentToUserSession(GlobalVariables.getUserSession(), workflowDoc);
177 }
178
179
180
181
182
183
184
185
186
187
188 protected void createDocument(DocumentFormBase form) throws WorkflowException {
189 Document doc = getDocumentService().getNewDocument(form.getDocTypeName());
190
191 form.setDocument(doc);
192 form.setDocTypeName(doc.getDocumentHeader().getWorkflowDocument().getDocumentTypeName());
193 }
194
195
196
197
198 @RequestMapping(params = "methodToCall=save")
199 public ModelAndView save(@ModelAttribute("KualiForm") DocumentFormBase form, BindingResult result, HttpServletRequest request,
200 HttpServletResponse response) throws Exception {
201
202 doProcessingAfterPost(form, request);
203
204
205
206
207
208 Document document = form.getDocument();
209
210 String viewName = checkAndWarnAboutSensitiveData(form, request, response,
211 KRADPropertyConstants.DOCUMENT_EXPLANATION, document.getDocumentHeader().getExplanation(), "save", "");
212
213
214 if (viewName != null) {
215 return new ModelAndView(viewName);
216 }
217
218 try {
219
220 getDocumentService().saveDocument(document);
221
222
223
224 form.setAnnotation("");
225 }
226 catch(ValidationException vex) {
227
228
229 if(GlobalVariables.getMessageMap().hasNoErrors()) {
230 throw new RuntimeException("Validation Exception with no error message.", vex);
231 }
232 }
233
234 return getUIFModelAndView(form);
235 }
236
237
238
239
240 @RequestMapping(params = "methodToCall=route")
241 public ModelAndView route(@ModelAttribute("KualiForm") DocumentFormBase form, BindingResult result, HttpServletRequest request,
242 HttpServletResponse response) throws Exception {
243 doProcessingAfterPost(form, request);
244
245
246
247
248
249
250
251
252
253 Document document = form.getDocument();
254
255 String viewName = checkAndWarnAboutSensitiveData(form, request, response,
256 KRADPropertyConstants.DOCUMENT_EXPLANATION, document.getDocumentHeader().getExplanation(), "route", "");
257 if (viewName != null) {
258 return new ModelAndView(viewName);
259 }
260
261
262
263
264 getDocumentService().routeDocument(document, form.getAnnotation(), new ArrayList<AdHocRouteRecipient>());
265
266
267
268 form.setAnnotation("");
269
270
271 return getUIFModelAndView(form);
272 }
273
274
275
276
277
278
279
280
281
282 @RequestMapping(method = RequestMethod.POST, params = "methodToCall=insertNote")
283 public ModelAndView insertNote(@ModelAttribute("KualiForm") UifFormBase uifForm,
284 BindingResult result, HttpServletRequest request, HttpServletResponse response) {
285
286
287 String selectedCollectionPath = uifForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH);
288 CollectionGroup collectionGroup = uifForm.getPreviousView().getViewIndex()
289 .getCollectionGroupByPath(selectedCollectionPath);
290 String addLinePath = collectionGroup.getAddLineBindingInfo().getBindingPath();
291 Object addLine = ObjectPropertyUtils.getPropertyValue(uifForm, addLinePath);
292 Note newNote = (Note) addLine;
293 newNote.setNotePostedTimestampToCurrent();
294
295 Document document = ((DocumentFormBase) uifForm).getDocument();
296
297 newNote.setRemoteObjectIdentifier(document.getNoteTarget().getObjectId());
298
299
300 String attachmentTypeCode = null;
301 MultipartFile attachmentFile = uifForm.getAttachmentFile();
302 Attachment attachment = null;
303 if (attachmentFile != null && !StringUtils.isBlank(attachmentFile.getOriginalFilename())) {
304 if (attachmentFile.getSize() == 0) {
305 GlobalVariables.getMessageMap().putError(
306 String.format("%s.%s",
307 KRADConstants.NEW_DOCUMENT_NOTE_PROPERTY_NAME,
308 KRADConstants.NOTE_ATTACHMENT_FILE_PROPERTY_NAME),
309 RiceKeyConstants.ERROR_UPLOADFILE_EMPTY,
310 attachmentFile.getOriginalFilename());
311 } else {
312 if (newNote.getAttachment() != null) {
313 attachmentTypeCode = newNote.getAttachment().getAttachmentTypeCode();
314 }
315
316 DocumentAuthorizer documentAuthorizer = KRADServiceLocatorWeb.getDocumentHelperService().getDocumentAuthorizer(
317 document);
318 if (!documentAuthorizer.canAddNoteAttachment(document, attachmentTypeCode, GlobalVariables.getUserSession()
319 .getPerson())) {
320 throw buildAuthorizationException("annotate", document);
321 }
322 try {
323 String attachmentType = null;
324 Attachment newAttachment = newNote.getAttachment();
325 if (newAttachment != null) {
326 attachmentType = newAttachment.getAttachmentTypeCode();
327 }
328 attachment = getAttachmentService().createAttachment(document.getNoteTarget(),
329 attachmentFile.getOriginalFilename(), attachmentFile.getContentType(),
330 (int) attachmentFile.getSize(), attachmentFile.getInputStream(), attachmentType);
331 } catch (IOException e) {
332 e.printStackTrace();
333 }
334 }
335 }
336
337 Person kualiUser = GlobalVariables.getUserSession().getPerson();
338 if (kualiUser == null) {
339 throw new IllegalStateException("Current UserSession has a null Person.");
340 }
341
342 newNote.setAuthorUniversalIdentifier(kualiUser.getPrincipalId());
343
344
345 boolean rulePassed = KRADServiceLocatorWeb.getKualiRuleService()
346 .applyRules(new AddNoteEvent(document, newNote));
347
348
349 if (rulePassed) {
350 newNote.refresh();
351
352 DocumentHeader documentHeader = document.getDocumentHeader();
353
354
355
356
357 if (attachment != null) {
358 newNote.addAttachment(attachment);
359 }
360
361 if (!documentHeader.getWorkflowDocument().isInitiated()
362 && StringUtils.isNotEmpty(document.getNoteTarget().getObjectId())
363 && !(document instanceof MaintenanceDocument && NoteType.BUSINESS_OBJECT.getCode().equals(
364 newNote.getNoteTypeCode()))) {
365
366 getNoteService().save(newNote);
367 }
368
369 }
370
371 return addLine(uifForm, result, request, response);
372 }
373
374
375
376
377
378
379
380 @RequestMapping(method = RequestMethod.POST, params = "methodToCall=deleteNote")
381 public ModelAndView deleteNote(@ModelAttribute("KualiForm") UifFormBase uifForm,
382 BindingResult result, HttpServletRequest request, HttpServletResponse response) {
383
384 String selectedLineIndex = uifForm.getActionParamaterValue("selectedLineIndex");
385 Document document = ((DocumentFormBase)uifForm).getDocument();
386 Note note = document.getNote(Integer.parseInt(selectedLineIndex));
387
388 Attachment attachment = note.getAttachment();
389 String attachmentTypeCode = null;
390 if (attachment != null) {
391 attachmentTypeCode = attachment.getAttachmentTypeCode();
392 }
393
394 String authorUniversalIdentifier = note.getAuthorUniversalIdentifier();
395 if (!KRADUtils.canDeleteNoteAttachment(document, attachmentTypeCode, authorUniversalIdentifier)) {
396 throw buildAuthorizationException("annotate", document);
397 }
398
399 if (attachment != null && attachment.isComplete()) {
400
401
402
403 if (note.getNoteIdentifier() != null) {
404 attachment.refreshNonUpdateableReferences();
405 }
406 getAttachmentService().deleteAttachmentContents(attachment);
407 }
408
409 if (!document.getDocumentHeader().getWorkflowDocument().isInitiated()) {
410 getNoteService().deleteNote(note);
411 }
412
413 return deleteLine(uifForm, result, request, response);
414 }
415
416
417
418
419
420
421
422 @RequestMapping(method = RequestMethod.POST, params = "methodToCall=downloadAttachment")
423 public ModelAndView downloadAttachment(@ModelAttribute("KualiForm") UifFormBase uifForm,
424 BindingResult result, HttpServletRequest request, HttpServletResponse response) throws ServletRequestBindingException, FileNotFoundException, IOException {
425
426 String selectedLineIndex = uifForm.getActionParamaterValue("selectedLineIndex");
427 Note note = ((DocumentFormBase)uifForm).getDocument().getNote(Integer.parseInt(selectedLineIndex));
428 Attachment attachment = note.getAttachment();
429 InputStream is = getAttachmentService().retrieveAttachmentContents(attachment);
430
431
432 response.setContentType(attachment.getAttachmentMimeTypeCode());
433 response.setContentLength(attachment.getAttachmentFileSize().intValue());
434 response.setHeader("Expires", "0");
435 response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
436 response.setHeader("Pragma", "public");
437 response.setHeader("Content-Disposition","attachment; filename=\"" + attachment.getAttachmentFileName() + "\"");
438
439
440 FileCopyUtils.copy(is, response.getOutputStream());
441 return null;
442 }
443
444
445
446
447
448
449 @RequestMapping(method = RequestMethod.POST, params = "methodToCall=cancelAttachment")
450 public ModelAndView cancelAttachment(@ModelAttribute("KualiForm") UifFormBase uifForm,
451 BindingResult result, HttpServletRequest request, HttpServletResponse response) {
452
453 uifForm.setAttachmentFile(null);
454 return getUIFModelAndView(uifForm);
455 }
456
457
458
459
460
461
462
463
464
465
466
467 protected void doProcessingAfterPost(DocumentFormBase form, HttpServletRequest request) {
468 getBusinessObjectService().linkUserFields(form.getDocument());
469 }
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542 protected String checkAndWarnAboutSensitiveData(DocumentFormBase form, HttpServletRequest request,
543 HttpServletResponse response, String fieldName, String fieldValue, String caller, String context)
544 throws Exception {
545
546 String viewName = null;
547 Document document = form.getDocument();
548
549
550 boolean containsSensitiveData = false;
551
552
553
554
555 boolean warnForSensitiveData = CoreFrameworkServiceLocator.getParameterService().getParameterValueAsBoolean(
556 KRADConstants.KRAD_NAMESPACE, ParameterConstants.ALL_COMPONENT,
557 KRADConstants.SystemGroupParameterNames.SENSITIVE_DATA_PATTERNS_WARNING_IND);
558
559
560 Map<String, String> ticketContext = new HashMap<String, String>();
561 ticketContext.put(KRADPropertyConstants.DOCUMENT_NUMBER, document.getDocumentNumber());
562 ticketContext.put(KRADConstants.CALLING_METHOD, caller);
563 ticketContext.put(KRADPropertyConstants.NAME, fieldName);
564
565 boolean questionAsked = GlobalVariables.getUserSession().hasMatchingSessionTicket(
566 KRADConstants.SENSITIVE_DATA_QUESTION_SESSION_TICKET, ticketContext);
567
568
569 if (containsSensitiveData && warnForSensitiveData && !questionAsked) {
570 Object question = request.getParameter(KRADConstants.QUESTION_INST_ATTRIBUTE_NAME);
571 if (question == null || !KRADConstants.DOCUMENT_SENSITIVE_DATA_QUESTION.equals(question)) {
572
573
574
575
576
577
578
579
580
581
582
583 viewName = "ask_user_questions";
584 }
585 else {
586 Object buttonClicked = request.getParameter(KRADConstants.QUESTION_CLICKED_BUTTON);
587
588
589 if (ConfirmationQuestion.NO.equals(buttonClicked)) {
590
591 viewName = "user_says_no";
592 }
593
594
595
596 SessionTicket ticket = new SessionTicket(KRADConstants.SENSITIVE_DATA_QUESTION_SESSION_TICKET);
597 ticket.setTicketContext(ticketContext);
598 GlobalVariables.getUserSession().putSessionTicket(ticket);
599 }
600 }
601
602
603 return viewName;
604 }
605
606
607
608
609
610
611
612
613
614 protected DocumentAuthorizationException buildAuthorizationException(String action, Document document) {
615 return new DocumentAuthorizationException(GlobalVariables.getUserSession().getPerson().getPrincipalName(),
616 action, document.getDocumentNumber());
617 }
618
619 public BusinessObjectService getBusinessObjectService() {
620 if (this.businessObjectService == null) {
621 this.businessObjectService = KRADServiceLocator.getBusinessObjectService();
622 }
623 return this.businessObjectService;
624 }
625
626 public void setBusinessObjectService(BusinessObjectService businessObjectService) {
627 this.businessObjectService = businessObjectService;
628 }
629
630 public DataDictionaryService getDataDictionaryService() {
631 if (this.dataDictionaryService == null) {
632 this.dataDictionaryService = KRADServiceLocatorWeb.getDataDictionaryService();
633 }
634 return this.dataDictionaryService;
635 }
636
637 public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
638 this.dataDictionaryService = dataDictionaryService;
639 }
640
641 public DocumentService getDocumentService() {
642 if (this.documentService == null) {
643 this.documentService = KRADServiceLocatorWeb.getDocumentService();
644 }
645 return this.documentService;
646 }
647
648 public void setDocumentService(DocumentService documentService) {
649 this.documentService = documentService;
650 }
651
652 public DocumentHelperService getDocumentHelperService() {
653 if (this.documentHelperService == null) {
654 this.documentHelperService = KRADServiceLocatorWeb.getDocumentHelperService();
655 }
656 return this.documentHelperService;
657 }
658
659 public void setDocumentHelperService(DocumentHelperService documentHelperService) {
660 this.documentHelperService = documentHelperService;
661 }
662
663 public AttachmentService getAttachmentService() {
664 if (attachmentService == null) {
665 attachmentService = KRADServiceLocator.getAttachmentService();
666 }
667 return this.attachmentService;
668 }
669
670 public NoteService getNoteService() {
671 if (noteService == null) {
672 noteService = KRADServiceLocator.getNoteService();
673 }
674 return this.noteService;
675 }
676 }