1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kew.mail;
17
18 import java.io.StringReader;
19
20 import javax.xml.parsers.DocumentBuilder;
21 import javax.xml.parsers.DocumentBuilderFactory;
22 import javax.xml.transform.Templates;
23 import javax.xml.transform.TransformerConfigurationException;
24
25 import org.apache.commons.lang.StringUtils;
26 import org.kuali.rice.core.config.ConfigContext;
27 import org.kuali.rice.kew.dto.DTOConverter;
28 import org.kuali.rice.kew.dto.RouteHeaderDTO;
29 import org.kuali.rice.kew.dto.RouteNodeInstanceDTO;
30 import org.kuali.rice.kew.engine.RouteContext;
31 import org.kuali.rice.kew.engine.RouteHelper;
32 import org.kuali.rice.kew.engine.node.SimpleNode;
33 import org.kuali.rice.kew.engine.node.SimpleResult;
34 import org.kuali.rice.kew.exception.WorkflowRuntimeException;
35 import org.kuali.rice.kew.service.KEWServiceLocator;
36 import org.kuali.rice.kew.util.KEWConstants;
37 import org.kuali.rice.kew.util.XmlHelper;
38 import org.kuali.rice.kim.bo.Person;
39 import org.kuali.rice.kim.service.KIMServiceLocator;
40 import org.w3c.dom.Document;
41 import org.w3c.dom.Element;
42 import org.w3c.dom.NodeList;
43 import org.xml.sax.InputSource;
44
45 import com.thoughtworks.xstream.XStream;
46
47
48
49
50
51
52
53 public class EmailNode implements SimpleNode {
54
55 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(EmailNode.class);
56
57 private EmailStyleHelper emailStyleHelper = new EmailStyleHelper();
58 private String styleName;
59 private String from;
60 private String to;
61
62 public SimpleResult process(RouteContext context, RouteHelper helper) throws Exception {
63 if (context.isSimulation()) {
64 if (!context.getActivationContext().isActivateRequests()) {
65 return new SimpleResult(true);
66 }
67 }
68 loadConfiguration(context);
69 Document document = generateXmlInput(context);
70 if (LOG.isDebugEnabled()) {
71 LOG.debug("XML input for email tranformation:\n" + XmlHelper.jotNode(document));
72 }
73 Templates style = loadStyleSheet(styleName);
74 EmailContent emailContent = emailStyleHelper.generateEmailContent(style, document);
75 if (!StringUtils.isBlank(to)) {
76 KEWServiceLocator.getEmailService().sendEmail(new EmailFrom(from), new EmailTo(to), new EmailSubject(emailContent.getSubject()), new EmailBody(emailContent.getBody()), emailContent.isHtml());
77 }
78 return new SimpleResult(true);
79 }
80
81 protected Document generateXmlInput(RouteContext context) throws Exception {
82 DocumentBuilder db = getDocumentBuilder(true);
83 Document doc = db.newDocument();
84 Element emailNodeElem = doc.createElement("emailNode");
85 doc.appendChild(emailNodeElem);
86 String principalId = null;
87 RouteHeaderDTO routeHeaderVO = DTOConverter.convertRouteHeader(context.getDocument(), principalId);
88 RouteNodeInstanceDTO routeNodeInstanceVO = DTOConverter.convertRouteNodeInstance(context.getNodeInstance());
89 Document documentContent = context.getDocumentContent().getDocument();
90 XStream xstream = new XStream();
91 Element docElem = XmlHelper.readXml(xstream.toXML(routeHeaderVO)).getDocumentElement();
92 Element nodeElem = XmlHelper.readXml(xstream.toXML(routeNodeInstanceVO)).getDocumentElement();
93 emailNodeElem.appendChild(doc.importNode(docElem, true));
94 emailNodeElem.appendChild(doc.importNode(nodeElem, true));
95 emailNodeElem.appendChild(doc.importNode(documentContent.getDocumentElement(), true));
96 Element dConElem = context.getDocumentContent().getApplicationContent();
97 emailNodeElem.appendChild(doc.importNode(dConElem, true));
98 return doc;
99 }
100
101 protected DocumentBuilder getDocumentBuilder(boolean coalesce) throws Exception {
102 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
103 dbf.setCoalescing(coalesce);
104 return dbf.newDocumentBuilder();
105 }
106
107 protected Templates loadStyleSheet(String styleName) {
108 try {
109 Templates style = KEWServiceLocator.getStyleService().getStyleAsTranslet(styleName);
110 if (style == null) {
111 throw new WorkflowRuntimeException("Failed to locate stylesheet with name '" + styleName + "'");
112 }
113 return style;
114 } catch (TransformerConfigurationException tce) {
115 throw new WorkflowRuntimeException("Failed to load stylesheet with name '" + styleName + "'");
116 }
117 }
118
119 protected boolean isProduction() {
120 return ConfigContext.getCurrentContextConfig().getProperty(KEWConstants.PROD_DEPLOYMENT_CODE).equalsIgnoreCase(
121 ConfigContext.getCurrentContextConfig().getEnvironment());
122 }
123
124 protected void loadConfiguration(RouteContext context) throws Exception {
125 String contentFragment = context.getNodeInstance().getRouteNode().getContentFragment();
126 DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
127 Document document = db.parse(new InputSource(new StringReader(contentFragment)));
128 if (!isProduction()) {
129 NodeList testAddresses = document.getElementsByTagName("testAddress");
130 if (testAddresses.getLength() >= 1) {
131 this.to = testAddresses.item(0).getTextContent();
132 }
133 } else {
134 NodeList toAddresses = document.getElementsByTagName("to");
135 if (toAddresses.getLength() != 1) {
136 throw new WorkflowRuntimeException("Must have exactly one 'to' address");
137 }
138 to = toAddresses.item(0).getTextContent();
139 if ("initiator".equalsIgnoreCase(to))
140 {
141 Person person = KIMServiceLocator.getPersonService().getPerson(context.getDocument().getInitiatorWorkflowId());
142 to = (person == null ? "" : person.getEmailAddressUnmasked());
143 }
144 if (StringUtils.isBlank(to)) {
145 throw new WorkflowRuntimeException("Email Address is missing from user's profile.");
146 }
147 }
148
149 NodeList fromAddresses = document.getElementsByTagName("from");
150 if (fromAddresses.getLength() != 1) {
151 throw new WorkflowRuntimeException("Must have exactly one 'from' address");
152 }
153 this.from = fromAddresses.item(0).getTextContent();
154
155 if ("initiator".equalsIgnoreCase(this.from)) {
156 Person initiator = KEWServiceLocator.getIdentityHelperService().getPerson(context.getDocument().getInitiatorWorkflowId());
157
158
159 this.from = "\"" + initiator.getName() + "\" <";
160 this.from += initiator.getEmailAddress() + ">";
161 }
162 if (StringUtils.isBlank(this.from)) {
163 throw new WorkflowRuntimeException("No email address could be found found for principal with id " + context.getDocument().getInitiatorWorkflowId());
164 }
165
166 if (LOG.isInfoEnabled()) {
167 LOG.info("Email From is set to:" + this.from);
168 LOG.info("Email To is set to:" + this.to);
169 }
170
171 NodeList styleNames = document.getElementsByTagName("style");
172 if (styleNames.getLength() != 1) {
173 throw new WorkflowRuntimeException("Must have exactly one 'style'");
174 }
175 this.styleName = styleNames.item(0).getTextContent();
176 }
177
178
179
180
181 }