/** * Returns a map containing the token name (<code>String</code>) as key and token value (<code> * String</code>) as value. This map can be used to substitute the token name with the token value * in a string. * * <p>Override this method to define additional substitution values for the token processor. * * @param request request context for the exit, assumed not <code>null</code>, used to obtain the * values for the tokens * @return the map containing the token name and values. This map contains non-<code>null</code> * value for all supported token names. The value may be empty if this token does not the * corresponding property defined in "rxconfig/Workflow/rxworkflow.properties" file and a * non-empty value could not be obtained from the request context object. If a non-<code>null * </code> and non-empty value is obtained from the request context then it is used as the * token value, otherwise the value configured in "rxconfig/Workflow/rxworkflow.properties" * file is used (which defaults to empty if no property containing the token name as key is * defined). */ @Deprecated protected Map<String, String> getTokenValues(IPSRequestContext request) { Map<String, String> tokenValues = new HashMap<String, String>(MAIL_TOKENS_DEFAULT_VALUE); for (int i = 0; i < MAIL_TOKENS.length; i++) { String tokenName = MAIL_TOKENS[i]; if (tokenName.equals(WORKFLOW_COMMENT_TOKEN)) { String transitionComment = PSWorkFlowUtils.getTransitionCommentFromHTMLParams(request.getParameters()); if ((transitionComment != null) && (transitionComment.trim().length() > 0)) { tokenValues.put(tokenName, transitionComment); } } } return tokenValues; }
/** * Sets the CC list. Override this method to change the CC list. * * @param request the users request context * @param messageCtx the current message * @param users the delimited string of users * @param communityId the community of the item being transitioned. */ @SuppressWarnings("unchecked") protected void setCCAddress( IPSRequestContext request, IPSMailMessageWritable messageCtx, String users, String communityId) { if (users == null) { return; } users = users.trim(); if (users.length() == 0) { return; } List<String> ccList = PSWorkFlowUtils.tokenizeString(users, PSWorkFlowUtils.EMAIL_STRING_DELIMITER); this.setCCAddress(request, messageCtx, ccList.iterator(), communityId); }
/** * Executive method for sending mail notifications, Gets notifications, constructs recipient list * and sends the mail notifications. * * @param contentURL URL of the content item * @param workflowID WorkflowID for the content item * @param fromStateID ID of content state before transition * @param toStateID ID of content state after transition * @param userName name of user sending the notification param wfRoleInfo Object containing role * info such as from and to state adhoc user information. * @param request request context for the exit * @param connection connection to back-end database * @param communityId the community id by which to filter the subjects to which the notifications * are sent, may be <code>null</code> to ignore the ccommunity filter. * @throws PSMailException if an error occurs while sending the mail. * @throws SQLException if a database error occurs * @throws PSEntryNotFoundException if there is no data base entry for the content item. */ @SuppressWarnings("unchecked") private void sendNotifications( String contentURL, int contentId, int workflowID, int transitionID, int fromStateID, int toStateID, String userName, PSWorkflowRoleInfo wfRoleInfo, IPSRequestContext request, Connection connection, String communityId) throws PSEntryNotFoundException, PSMailException, SQLException { PSWorkFlowUtils.printWorkflowMessage(request, " Entering Method sendNotifications"); List toStateUserList = new ArrayList(); List fromStateUserList = new ArrayList(); String emailCCString = ""; PSNotificationsContext nc = null; PSTransitionNotificationsContext tnc = null; int notificationID = 0; String additionalRecipientString = ""; String subject = ""; String body = ""; // Get the notification messages for the transition try { tnc = new PSTransitionNotificationsContext(workflowID, transitionID, connection); if (0 == tnc.getCount()) { log.info( " There are no notifications for the transition " + transitionID + " in the workflow " + workflowID + "."); return; } if (!this.checkNotification(request, wfRoleInfo, tnc)) { log.debug("Notification not performed"); return; } // Get whichever state role lists will be needed if (tnc.requireFromStateRoles()) { fromStateUserList = this.getStateUserList( request, contentId, wfRoleInfo, wfRoleInfo.getFromStateCauc(), workflowID, connection, fromStateID, communityId); } if (tnc.requireToStateRoles()) { toStateUserList = this.getStateUserList( request, contentId, wfRoleInfo, wfRoleInfo.getToStateCauc(), workflowID, connection, toStateID, communityId); } do // Loop over the notifications for this transition { IPSMailMessageWritable messageContext = buildMessageContext(); this.setFromAddress(request, messageContext, userName, communityId); additionalRecipientString = ""; notificationID = tnc.getNotificationID(); // This will throw an exception if the notification does not exist nc = new PSNotificationsContext(workflowID, notificationID, connection); subject = nc.getSubject(); body = nc.getBody(); processTokens(request, contentId, messageContext, subject, body); additionalRecipientString = tnc.getAdditionalRecipientList(); emailCCString = tnc.getCCList(); this.setCCAddress(request, messageContext, emailCCString, communityId); if (tnc.notifyToStateRoles() && !toStateUserList.isEmpty()) { this.setToAddress(request, messageContext, toStateUserList.iterator(), communityId); } if (tnc.notifyFromStateRoles() && !fromStateUserList.isEmpty()) { this.setToAddress(request, messageContext, fromStateUserList.iterator(), communityId); } this.setToAddress(request, messageContext, additionalRecipientString, communityId); messageContext.setUrl(contentURL); if (messageContext.getToList().isEmpty()) { /* * A message must have "To" recipients. Therefore if there are * "CC" recipients but no "To" recipients, send the mail "To" * the CC list. This is desired because they should get mail even * if all the roles have turned off notification. */ Collection ccList = messageContext.getCCList(); if (!ccList.isEmpty()) { messageContext.setTo(ccList); messageContext.setCC(Collections.EMPTY_LIST); log.info( " There are no \"to\" recipients for notification " + notificationID + " in the workflow " + workflowID + ". \"to\" email will be sent to the \"CC\" recipients"); } else { log.info( " There are no \"to\" or \"CC\" recipients for notification " + notificationID + " in the workflow " + workflowID + ", so this notification will not be sent."); continue; } } /* * Send mail using the mail domain, host and plugin specified in the * workflow properties file. */ String ccMessage = ""; if (!messageContext.getCCList().isEmpty()) { ccMessage = " , CC to " + messageContext.getCc(); } log.debug( "Email sent to " + messageContext.getTo() + ccMessage + ". " + "Email sent by " + messageContext.getFrom()); this.sendMail(request, messageContext); } while (tnc.moveNext()); // End Loop over mail notifications } catch (Exception ex) { log.error("Unexpected Exception " + ex + " " + ex.getMessage(), ex); } PSWorkFlowUtils.printWorkflowMessage(request, " Exiting Method sendNotifications"); log.debug("Exiting Method sendNotifications"); }
/** * Process the notification messages. * * @see * com.percussion.extension.IPSResultDocumentProcessor#processResultDocument(java.lang.Object[], * com.percussion.server.IPSRequestContext, org.w3c.dom.Document) */ public Document processResultDocument(Object[] params, IPSRequestContext request, Document resDoc) throws PSParameterMismatchException, PSExtensionProcessingException { log.debug("Entering Notification"); PSWorkFlowUtils.printWorkflowMessage( request, "\nNotify Assignees: enter processResultDocument "); int transitionID = 0; int toStateID = 0; int fromStateID = 0; int contentID = 0; int workflowID = 0; int revisionID = 0; String userName = null; PSWorkFlowContext wfContext = null; PSTransitionsContext tc = null; PSWorkflowRoleInfo wfRoleInfo = null; PSContentStatusContext csc = null; String contentURL = null; String lang = null; PSConnectionMgr connectionMgr = null; Connection connection = null; try { if (null == request) { throw new PSExtensionProcessingException( m_fullExtensionName, new IllegalArgumentException("The request must not be null")); } lang = (String) request.getSessionPrivateObject(PSI18nUtils.USER_SESSION_OBJECT_SYS_LANG); if (lang == null) lang = PSI18nUtils.DEFAULT_LANG; wfContext = (PSWorkFlowContext) request.getPrivateObject(IPSWorkFlowContext.WORKFLOW_CONTEXT_PRIVATE_OBJECT); if (null == wfContext) { log.debug("No transition, no notification sent"); PSWorkFlowUtils.printWorkflowMessage( request, "Notify assignees: - no transition was performed - " + "no notifications will be sent"); return resDoc; } revisionID = wfContext.getBaseRevisionNum(); transitionID = wfContext.getTransitionID(); if (IPSConstants.TRANSITIONID_NO_ACTION_TAKEN == transitionID || IPSConstants.TRANSITIONID_CHECKINOUT == transitionID) { PSWorkFlowUtils.printWorkflowMessage( request, "Notify assignees: - no transition was performed - " + "no notifications will be sent"); return resDoc; // no action at all - no history } workflowID = wfContext.getWorkflowID(); toStateID = wfContext.getStateID(); // Note: we could get content id from workflow context if (null == params[0] || 0 == params[0].toString().trim().length()) { log.debug("no content id, no notification sent"); return resDoc; // no content id means no notifications! } contentID = new Integer(params[0].toString()).intValue(); if (0 == contentID) { log.debug("content id = 0, no notification sent"); return resDoc; // no content id means no notifications! } if (null == params[1] || 0 == params[1].toString().trim().length()) { throw new PSInvalidParameterTypeException(lang, IPSExtensionErrors.EMPTY_USRNAME1); } userName = params[1].toString(); // Get the connection connectionMgr = new PSConnectionMgr(); connection = connectionMgr.getConnection(); /* * get the old state id from the transition context TODO - put the old * state id into the workflow context, to avoid database reads. */ tc = new PSTransitionsContext(transitionID, workflowID, connection); tc.close(); fromStateID = tc.getTransitionFromStateID(); wfRoleInfo = (PSWorkflowRoleInfo) request.getPrivateObject(PSWorkflowRoleInfo.WORKFLOW_ROLE_INFO_PRIVATE_OBJECT); if (null == wfRoleInfo) { throw new PSExtensionProcessingException( m_fullExtensionName, new PSRoleException(lang, IPSExtensionErrors.ROLEINFO_OBJ_NULL)); } contentURL = PSWorkFlowUtils.getContentItemURL(contentID, revisionID, request, true); csc = new PSContentStatusContext(connection, contentID); sendNotifications( contentURL, contentID, workflowID, transitionID, fromStateID, toStateID, userName, wfRoleInfo, request, connection, String.valueOf(csc.getCommunityID())); } catch (PSNotificationSkipException se) { log.debug("Notification Skipped"); } catch (PSExtensionProcessingException pe) { log.error( "Error while sending notification with user " + userName + " and contentid " + contentID, pe); throw (PSExtensionProcessingException) pe.fillInStackTrace(); } catch (Exception e) { log.error( "Error while sending notification with user " + userName + " and contentid " + contentID, e); // error message should be improved String language = null; // if(e instanceof PSEntryNotFoundException || e instanceof // PSInvalidParameterTypeException ) // { // language = e.getLanguageString(); // } if (language == null) language = PSI18nUtils.DEFAULT_LANG; throw new PSExtensionProcessingException(language, m_fullExtensionName, e); } finally { if (csc != null) { try { csc.close(); } catch (Exception ex) { // no-op } } try { if (null != connectionMgr) connectionMgr.releaseConnection(); } catch (SQLException sqe) { } log.debug("End of notification"); PSWorkFlowUtils.printWorkflowMessage( request, "Notify Assignees: exit processResultDocument "); } return resDoc; }