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