1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.ken.util;
17
18 import java.io.ByteArrayOutputStream;
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.io.StringWriter;
22 import java.sql.Timestamp;
23 import java.text.DateFormat;
24 import java.text.ParseException;
25 import java.text.SimpleDateFormat;
26 import java.util.ArrayList;
27 import java.util.Date;
28 import java.util.HashMap;
29 import java.util.Map;
30 import java.util.TimeZone;
31
32 import javax.xml.namespace.NamespaceContext;
33 import javax.xml.parsers.DocumentBuilder;
34 import javax.xml.parsers.DocumentBuilderFactory;
35 import javax.xml.parsers.ParserConfigurationException;
36 import javax.xml.transform.OutputKeys;
37 import javax.xml.transform.Result;
38 import javax.xml.transform.Source;
39 import javax.xml.transform.Transformer;
40 import javax.xml.transform.TransformerException;
41 import javax.xml.transform.TransformerFactory;
42 import javax.xml.transform.dom.DOMSource;
43 import javax.xml.transform.stream.StreamResult;
44 import javax.xml.transform.stream.StreamSource;
45
46 import org.apache.commons.lang.StringUtils;
47 import org.apache.log4j.Logger;
48 import org.apache.xerces.jaxp.JAXPConstants;
49 import org.kuali.rice.core.config.ConfigContext;
50 import org.kuali.rice.core.dao.GenericDao;
51 import org.kuali.rice.ken.bo.Notification;
52 import org.kuali.rice.ken.bo.NotificationChannel;
53 import org.kuali.rice.ken.bo.NotificationContentType;
54 import org.kuali.rice.ken.bo.NotificationPriority;
55 import org.kuali.rice.ken.bo.NotificationProducer;
56 import org.kuali.rice.ken.bo.NotificationRecipient;
57 import org.kuali.rice.ken.bo.NotificationSender;
58 import org.kuali.rice.ken.service.NotificationContentTypeService;
59 import org.w3c.dom.Document;
60 import org.w3c.dom.Element;
61 import org.w3c.dom.Node;
62 import org.w3c.dom.NodeList;
63 import org.xml.sax.EntityResolver;
64 import org.xml.sax.ErrorHandler;
65 import org.xml.sax.InputSource;
66 import org.xml.sax.SAXException;
67 import org.xml.sax.SAXParseException;
68
69
70
71
72
73 public final class Util {
74 private static final Logger LOG = Logger.getLogger(Util.class);
75
76
77 public static final NamespaceContext NOTIFICATION_NAMESPACE_CONTEXT;
78
79
80 private static final DateFormat DATEFORMAT_ZULU = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
81
82
83 private static final DateFormat DATEFORMAT_CURR_TZ = new SimpleDateFormat(
84 "MM/dd/yyyy hh:mm a");
85
86 static {
87 Map<String, String> prefixToNS = new HashMap<String, String>();
88 prefixToNS.put("nreq", "ns:notification/NotificationRequest");
89 NOTIFICATION_NAMESPACE_CONTEXT = new ConfiguredNamespaceContext(prefixToNS);
90
91
92 DATEFORMAT_ZULU.setTimeZone(TimeZone.getTimeZone("UTC"));
93
94
95 }
96
97
98
99
100 public static String getNotificationSystemUser() {
101 String system_user = ConfigContext.getCurrentContextConfig().getProperty(NotificationConstants.KEW_CONSTANTS.NOTIFICATION_SYSTEM_USER_PARAM);
102 if (system_user == null) {
103 system_user = NotificationConstants.KEW_CONSTANTS.NOTIFICATION_SYSTEM_USER;
104 }
105 return system_user;
106 }
107
108
109
110
111
112
113
114
115 public static Date parseXSDDateTime(String dateTimeString) throws ParseException {
116 synchronized (DATEFORMAT_ZULU) {
117 return DATEFORMAT_ZULU.parse(dateTimeString);
118 }
119 }
120
121
122
123
124
125
126 public static String toXSDDateTimeString(Date d) {
127 synchronized (DATEFORMAT_ZULU) {
128 return DATEFORMAT_ZULU.format(d);
129 }
130 }
131
132
133
134
135
136 public static String getCurrentDateTime() {
137 return toUIDateTimeString(new Date());
138 }
139
140
141
142
143
144 public static String toUIDateTimeString(Date d) {
145 synchronized (DATEFORMAT_CURR_TZ) {
146 return DATEFORMAT_CURR_TZ.format(d);
147 }
148 }
149
150
151
152
153
154 public static Date parseUIDateTime(String s) throws ParseException {
155 synchronized (DATEFORMAT_CURR_TZ) {
156 return DATEFORMAT_CURR_TZ.parse(s);
157 }
158 }
159
160
161
162
163
164
165
166 public static NamespaceContext getNotificationNamespaceContext(Document doc) {
167 return new CompoundNamespaceContext(NOTIFICATION_NAMESPACE_CONTEXT, new DocumentNamespaceContext(doc));
168 }
169
170
171
172
173
174
175 public static EntityResolver getNotificationEntityResolver(NotificationContentTypeService notificationContentTypeService) {
176 return new CompoundEntityResolver(new ClassLoaderEntityResolver("schema", "notification"),
177 new ContentTypeEntityResolver(notificationContentTypeService));
178 }
179
180
181
182
183
184
185
186 public static String transformContent(Notification notification) {
187 NotificationContentType contentType = notification.getContentType();
188 String xsl = contentType.getXsl();
189
190 LOG.debug("xsl: "+xsl);
191
192 XslSourceResolver xslresolver = new XslSourceResolver();
193
194 StreamSource xslsource = xslresolver.resolveXslFromString(xsl);
195 String content = notification.getContent();
196 LOG.debug("xslsource:"+xslsource.toString());
197
198 String contenthtml = new String();
199 try {
200 ContentTransformer transformer = new ContentTransformer(xslsource);
201 contenthtml = transformer.transform(content);
202 LOG.debug("html: "+contenthtml);
203 } catch (IOException ex) {
204 LOG.error("IOException transforming document",ex);
205 } catch (Exception ex) {
206 LOG.error("Exception transforming document",ex);
207 }
208 return contenthtml;
209 }
210
211
212
213
214
215
216
217
218
219
220
221 public static Document parse(final InputSource source, boolean validate, boolean namespaceAware, EntityResolver entityResolver) throws ParserConfigurationException, IOException, SAXException {
222
223 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
224 dbf.setValidating(validate);
225 dbf.setNamespaceAware(namespaceAware);
226 dbf.setAttribute(JAXPConstants.JAXP_SCHEMA_LANGUAGE, JAXPConstants.W3C_XML_SCHEMA);
227 DocumentBuilder db = dbf.newDocumentBuilder();
228 if (entityResolver != null) {
229 db.setEntityResolver(entityResolver);
230 }
231 db.setErrorHandler(new ErrorHandler() {
232 public void warning(SAXParseException se) {
233 LOG.warn("Warning parsing xml doc " + source, se);
234 }
235 public void error(SAXParseException se) throws SAXException {
236 LOG.error("Error parsing xml doc " + source, se);
237 throw se;
238 }
239 public void fatalError(SAXParseException se) throws SAXException {
240 LOG.error("Fatal error parsing xml doc " + source, se);
241 throw se;
242 }
243 });
244 return db.parse(source);
245 }
246
247
248
249
250
251
252
253
254
255
256
257
258 public static Document parseWithNotificationEntityResolver(final InputSource source, boolean validate, boolean namespaceAware, NotificationContentTypeService notificationContentTypeService) throws ParserConfigurationException, IOException, SAXException {
259 return parse(source, validate, namespaceAware, getNotificationEntityResolver(notificationContentTypeService));
260 }
261
262
263
264
265
266
267 public static String getTextContent(org.w3c.dom.Element element) {
268 NodeList children = element.getChildNodes();
269 Node node = children.item(0);
270 return node.getNodeValue();
271 }
272
273
274
275
276
277
278
279
280 public static Element getChildElement(Node parent, String name) {
281 NodeList childList = parent.getChildNodes();
282 for (int i = 0; i < childList.getLength(); i++) {
283 Node node = childList.item(i);
284
285
286
287
288
289 if (node.getNodeType() == Node.ELEMENT_NODE
290 && (name.equals(node.getLocalName())
291 || name.equals(node.getNodeName()))) {
292 return (Element) node;
293 }
294 }
295 return null;
296 }
297
298
299
300
301
302
303
304
305
306 public static String getChildElementTextValue(Node parent, String name) {
307 Element child = getChildElement(parent, name);
308 if (child == null) {
309 return null;
310 }
311 return child.getTextContent();
312 }
313
314
315
316
317
318
319
320
321
322 public static byte[] readFully(InputStream stream) throws IOException {
323 byte[] buf = new byte[1024];
324 ByteArrayOutputStream baos = new ByteArrayOutputStream();
325 int read;
326 while ((read = stream.read(buf)) != -1) {
327 baos.write(buf, 0, read);
328 }
329 return baos.toByteArray();
330 }
331
332
333
334
335
336
337
338 public static String writeNode(org.w3c.dom.Node node) throws TransformerException {
339 return writeNode(node, false);
340 }
341
342
343
344
345
346
347
348
349 public static String writeNode(org.w3c.dom.Node node, boolean indent) throws TransformerException {
350 Source source = new DOMSource(node);
351 StringWriter writer = new StringWriter();
352 Result result = new StreamResult(writer);
353 Transformer transformer = TransformerFactory.newInstance().newTransformer();
354 transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
355 if (indent) {
356 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
357 }
358 transformer.transform(source, result);
359 return writer.toString();
360 }
361
362
363
364
365
366
367
368 public static final Notification cloneNotificationWithoutObjectReferences(Notification notification) {
369 Notification clone = new Notification();
370
371
372 if(notification.getCreationDateTime() != null) {
373 clone.setCreationDateTime(new Timestamp(notification.getCreationDateTime().getTime()));
374 }
375 if(notification.getAutoRemoveDateTime() != null) {
376 clone.setAutoRemoveDateTime(new Timestamp(notification.getAutoRemoveDateTime().getTime()));
377 }
378 clone.setContent(new String(notification.getContent()));
379 clone.setDeliveryType(new String(notification.getDeliveryType()));
380 if(notification.getId() != null) {
381 clone.setId(new Long(notification.getId()));
382 }
383 clone.setProcessingFlag(new String(notification.getProcessingFlag()));
384 if(notification.getSendDateTime() != null) {
385 clone.setSendDateTime(new Timestamp(notification.getSendDateTime().getTime()));
386 }
387
388 clone.setTitle(notification.getTitle());
389
390
391 NotificationChannel channel = new NotificationChannel();
392 channel.setId(new Long(notification.getChannel().getId()));
393 channel.setName(new String(notification.getChannel().getName()));
394 channel.setDescription(new String(notification.getChannel().getDescription()));
395 channel.setSubscribable(new Boolean(notification.getChannel().isSubscribable()).booleanValue());
396 clone.setChannel(channel);
397
398
399 NotificationContentType contentType = new NotificationContentType();
400 contentType.setId(new Long(notification.getContentType().getId()));
401 contentType.setDescription(new String(notification.getContentType().getDescription()));
402 contentType.setName(new String(notification.getContentType().getName()));
403 contentType.setNamespace(new String(notification.getContentType().getNamespace()));
404 clone.setContentType(contentType);
405
406
407 NotificationPriority priority = new NotificationPriority();
408 priority.setDescription(new String(notification.getPriority().getDescription()));
409 priority.setId(new Long(notification.getPriority().getId()));
410 priority.setName(new String(notification.getPriority().getName()));
411 priority.setOrder(new Integer(notification.getPriority().getOrder()));
412 clone.setPriority(priority);
413
414
415 NotificationProducer producer = new NotificationProducer();
416 producer.setDescription(new String(notification.getProducer().getDescription()));
417 producer.setId(new Long(notification.getProducer().getId()));
418 producer.setName(new String(notification.getProducer().getName()));
419 producer.setContactInfo(new String(notification.getProducer().getContactInfo()));
420 clone.setProducer(producer);
421
422
423 ArrayList<NotificationRecipient> recipients = new ArrayList<NotificationRecipient>();
424 for(int i = 0; i < notification.getRecipients().size(); i++) {
425 NotificationRecipient recipient = notification.getRecipient(i);
426 NotificationRecipient cloneRecipient = new NotificationRecipient();
427 cloneRecipient.setRecipientId(new String(recipient.getRecipientId()));
428 cloneRecipient.setRecipientType(new String(recipient.getRecipientType()));
429
430 recipients.add(cloneRecipient);
431 }
432 clone.setRecipients(recipients);
433
434
435 ArrayList<NotificationSender> senders = new ArrayList<NotificationSender>();
436 for(int i = 0; i < notification.getSenders().size(); i++) {
437 NotificationSender sender = notification.getSender(i);
438 NotificationSender cloneSender = new NotificationSender();
439 cloneSender.setSenderName(new String(sender.getSenderName()));
440
441 senders.add(cloneSender);
442 }
443 clone.setSenders(senders);
444
445 return clone;
446 }
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461 public static <T> T retrieveFieldReference(String fieldName, String keyName, String keyValue, Class clazz, GenericDao boDao) throws IllegalArgumentException {
462 LOG.debug(fieldName + " key value: " + keyValue);
463 if (StringUtils.isBlank(keyValue)) {
464 throw new IllegalArgumentException(fieldName + " must be specified in notification");
465 }
466 Map<String, Object> keys = new HashMap<String, Object>(1);
467 keys.put(keyName, keyValue);
468 T reference = (T) boDao.findByPrimaryKey(clazz, keys);
469 if (reference == null) {
470 throw new IllegalArgumentException(fieldName + " '" + keyValue + "' not found");
471 }
472 return reference;
473 }
474
475
476
477
478
479
480
481
482 public static <T extends Throwable> T findExceptionInStack(Throwable topLevelException, Class<T> exceptionClass) {
483 Throwable t = topLevelException;
484 while (t != null) {
485 if (exceptionClass.isAssignableFrom(t.getClass())) return (T) t;
486 t = t.getCause();
487 }
488 return null;
489 }
490 }