1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   *
13   */
14  
15  package com.liferay.portlet.journal.util;
16  
17  import com.liferay.portal.PortalException;
18  import com.liferay.portal.SystemException;
19  import com.liferay.portal.kernel.configuration.Filter;
20  import com.liferay.portal.kernel.log.Log;
21  import com.liferay.portal.kernel.log.LogFactoryUtil;
22  import com.liferay.portal.kernel.util.Constants;
23  import com.liferay.portal.kernel.util.GetterUtil;
24  import com.liferay.portal.kernel.util.HttpUtil;
25  import com.liferay.portal.kernel.util.InstancePool;
26  import com.liferay.portal.kernel.util.LocaleUtil;
27  import com.liferay.portal.kernel.util.LocalizationUtil;
28  import com.liferay.portal.kernel.util.OrderByComparator;
29  import com.liferay.portal.kernel.util.PropertiesUtil;
30  import com.liferay.portal.kernel.util.PropsKeys;
31  import com.liferay.portal.kernel.util.StringPool;
32  import com.liferay.portal.kernel.util.StringUtil;
33  import com.liferay.portal.kernel.util.Time;
34  import com.liferay.portal.kernel.util.Validator;
35  import com.liferay.portal.kernel.xml.Attribute;
36  import com.liferay.portal.kernel.xml.Document;
37  import com.liferay.portal.kernel.xml.Element;
38  import com.liferay.portal.kernel.xml.Node;
39  import com.liferay.portal.kernel.xml.SAXReaderUtil;
40  import com.liferay.portal.kernel.xml.XPath;
41  import com.liferay.portal.model.Group;
42  import com.liferay.portal.model.Layout;
43  import com.liferay.portal.model.LayoutSet;
44  import com.liferay.portal.model.User;
45  import com.liferay.portal.service.ImageLocalServiceUtil;
46  import com.liferay.portal.service.LayoutLocalServiceUtil;
47  import com.liferay.portal.service.UserLocalServiceUtil;
48  import com.liferay.portal.theme.ThemeDisplay;
49  import com.liferay.portal.util.ContentUtil;
50  import com.liferay.portal.util.FriendlyURLNormalizer;
51  import com.liferay.portal.util.PropsUtil;
52  import com.liferay.portal.util.PropsValues;
53  import com.liferay.portal.util.WebKeys;
54  import com.liferay.portlet.journal.TransformException;
55  import com.liferay.portlet.journal.model.JournalArticle;
56  import com.liferay.portlet.journal.model.JournalStructure;
57  import com.liferay.portlet.journal.model.JournalTemplate;
58  import com.liferay.portlet.journal.model.impl.JournalStructureImpl;
59  import com.liferay.portlet.journal.service.JournalArticleImageLocalServiceUtil;
60  import com.liferay.portlet.journal.service.JournalTemplateLocalServiceUtil;
61  import com.liferay.portlet.journal.util.comparator.ArticleCreateDateComparator;
62  import com.liferay.portlet.journal.util.comparator.ArticleDisplayDateComparator;
63  import com.liferay.portlet.journal.util.comparator.ArticleIDComparator;
64  import com.liferay.portlet.journal.util.comparator.ArticleModifiedDateComparator;
65  import com.liferay.portlet.journal.util.comparator.ArticleReviewDateComparator;
66  import com.liferay.portlet.journal.util.comparator.ArticleTitleComparator;
67  import com.liferay.portlet.journal.util.comparator.ArticleVersionComparator;
68  import com.liferay.portlet.tags.service.TagsEntryLocalServiceUtil;
69  import com.liferay.util.FiniteUniqueStack;
70  import com.liferay.util.xml.XMLFormatter;
71  
72  import java.io.IOException;
73  
74  import java.util.ArrayList;
75  import java.util.Date;
76  import java.util.HashMap;
77  import java.util.Iterator;
78  import java.util.List;
79  import java.util.Map;
80  import java.util.Stack;
81  
82  import javax.portlet.PortletPreferences;
83  import javax.portlet.PortletRequest;
84  import javax.portlet.PortletSession;
85  
86  /**
87   * <a href="JournalUtil.java.html"><b><i>View Source</i></b></a>
88   *
89   * @author Brian Wing Shun Chan
90   * @author Raymond Augé
91   * @author Wesley Gong
92   */
93  public class JournalUtil {
94  
95      public static final int MAX_STACK_SIZE = 20;
96  
97      public static final String XML_INDENT = "  ";
98  
99      public static void addRecentArticle(
100         PortletRequest portletRequest, JournalArticle article) {
101 
102         if (article != null) {
103             Stack<JournalArticle> stack = getRecentArticles(portletRequest);
104 
105             stack.push(article);
106         }
107     }
108 
109     public static void addRecentStructure(
110         PortletRequest portletRequest, JournalStructure structure) {
111 
112         if (structure != null) {
113             Stack<JournalStructure> stack = getRecentStructures(portletRequest);
114 
115             stack.push(structure);
116         }
117     }
118 
119     public static void addRecentTemplate(
120         PortletRequest portletRequest, JournalTemplate template) {
121 
122         if (template != null) {
123             Stack<JournalTemplate> stack = getRecentTemplates(portletRequest);
124 
125             stack.push(template);
126         }
127     }
128 
129     public static void addReservedEl(
130         Element root, Map<String, String> tokens, String name, double value) {
131 
132         addReservedEl(root, tokens, name, String.valueOf(value));
133     }
134 
135     public static void addReservedEl(
136         Element root, Map<String, String> tokens, String name, Date value) {
137 
138         addReservedEl(root, tokens, name, Time.getRFC822(value));
139     }
140 
141     public static void addReservedEl(
142         Element root, Map<String, String> tokens, String name, String value) {
143 
144         // XML
145 
146         if (root != null) {
147             Element dynamicEl = SAXReaderUtil.createElement("dynamic-element");
148 
149             dynamicEl.add(
150                 SAXReaderUtil.createAttribute(dynamicEl, "name", name));
151             dynamicEl.add(
152                 SAXReaderUtil.createAttribute(dynamicEl, "type", "text"));
153 
154             Element dynamicContent = SAXReaderUtil.createElement(
155                 "dynamic-content");
156 
157             //dynamicContent.setText("<![CDATA[" + value + "]]>");
158             dynamicContent.setText(value);
159 
160             dynamicEl.add(dynamicContent);
161 
162             root.add(dynamicEl);
163         }
164 
165         // Tokens
166 
167         tokens.put(
168             StringUtil.replace(name, StringPool.DASH, StringPool.UNDERLINE),
169             value);
170     }
171 
172     public static void addAllReservedEls(
173         Element root, Map<String, String> tokens, JournalArticle article) {
174 
175         JournalUtil.addReservedEl(
176             root, tokens, JournalStructureImpl.RESERVED_ARTICLE_ID,
177             article.getArticleId());
178 
179         JournalUtil.addReservedEl(
180             root, tokens, JournalStructureImpl.RESERVED_ARTICLE_VERSION,
181             article.getVersion());
182 
183         JournalUtil.addReservedEl(
184             root, tokens, JournalStructureImpl.RESERVED_ARTICLE_TITLE,
185             article.getTitle());
186 
187         JournalUtil.addReservedEl(
188             root, tokens, JournalStructureImpl.RESERVED_ARTICLE_URL_TITLE,
189             article.getUrlTitle());
190 
191         JournalUtil.addReservedEl(
192             root, tokens, JournalStructureImpl.RESERVED_ARTICLE_DESCRIPTION,
193             article.getDescription());
194 
195         JournalUtil.addReservedEl(
196             root, tokens, JournalStructureImpl.RESERVED_ARTICLE_TYPE,
197             article.getType());
198 
199         JournalUtil.addReservedEl(
200             root, tokens, JournalStructureImpl.RESERVED_ARTICLE_CREATE_DATE,
201             article.getCreateDate());
202 
203         JournalUtil.addReservedEl(
204             root, tokens,
205             JournalStructureImpl.RESERVED_ARTICLE_MODIFIED_DATE,
206             article.getModifiedDate());
207 
208         if (article.getDisplayDate() != null) {
209             JournalUtil.addReservedEl(
210                 root, tokens,
211                 JournalStructureImpl.RESERVED_ARTICLE_DISPLAY_DATE,
212                 article.getDisplayDate());
213         }
214 
215         JournalUtil.addReservedEl(
216             root, tokens, JournalStructureImpl.RESERVED_ARTICLE_SMALL_IMAGE_URL,
217             article.getSmallImageURL());
218 
219         String[] tagsEntries = new String[0];
220 
221         try {
222             tagsEntries = TagsEntryLocalServiceUtil.getEntryNames(
223                 JournalArticle.class.getName(), article.getResourcePrimKey());
224         }
225         catch (SystemException se) {
226         }
227 
228         JournalUtil.addReservedEl(
229             root, tokens, JournalStructureImpl.RESERVED_ARTICLE_ASSET_TAG_NAMES,
230             StringUtil.merge(tagsEntries));
231 
232         JournalUtil.addReservedEl(
233             root, tokens, JournalStructureImpl.RESERVED_ARTICLE_AUTHOR_ID,
234             String.valueOf(article.getUserId()));
235 
236         String userName = StringPool.BLANK;
237         String userEmailAddress = StringPool.BLANK;
238         String userComments = StringPool.BLANK;
239         String userJobTitle = StringPool.BLANK;
240 
241         User user = null;
242 
243         try {
244             user = UserLocalServiceUtil.getUserById(article.getUserId());
245 
246             userName = user.getFullName();
247             userEmailAddress = user.getEmailAddress();
248             userComments = user.getComments();
249             userJobTitle = user.getJobTitle();
250         }
251         catch (PortalException pe) {
252         }
253         catch (SystemException se) {
254         }
255 
256         JournalUtil.addReservedEl(
257             root, tokens, JournalStructureImpl.RESERVED_ARTICLE_AUTHOR_NAME,
258             userName);
259 
260         JournalUtil.addReservedEl(
261             root, tokens,
262             JournalStructureImpl.RESERVED_ARTICLE_AUTHOR_EMAIL_ADDRESS,
263             userEmailAddress);
264 
265         JournalUtil.addReservedEl(
266             root, tokens,
267             JournalStructureImpl.RESERVED_ARTICLE_AUTHOR_COMMENTS,
268             userComments);
269 
270         JournalUtil.addReservedEl(
271             root, tokens,
272             JournalStructureImpl.RESERVED_ARTICLE_AUTHOR_JOB_TITLE,
273             userJobTitle);
274     }
275 
276     public static String formatVM(String vm) {
277         return vm;
278     }
279 
280     public static String formatXML(String xml)
281         throws org.dom4j.DocumentException, IOException {
282 
283         // This is only supposed to format your xml, however, it will also
284         // unwantingly change &#169; and other characters like it into their
285         // respective readable versions
286 
287         xml = StringUtil.replace(xml, "&#", "[$SPECIAL_CHARACTER$]");
288 
289         xml = XMLFormatter.toString(xml, XML_INDENT);
290 
291         xml = StringUtil.replace(xml, "[$SPECIAL_CHARACTER$]", "&#");
292 
293         return xml;
294     }
295 
296     public static String formatXML(Document doc) throws IOException {
297         return doc.formattedString(XML_INDENT);
298     }
299 
300     public static OrderByComparator getArticleOrderByComparator(
301         String orderByCol, String orderByType) {
302 
303         boolean orderByAsc = false;
304 
305         if (orderByType.equals("asc")) {
306             orderByAsc = true;
307         }
308 
309         OrderByComparator orderByComparator = null;
310 
311         if (orderByCol.equals("create-date")) {
312             orderByComparator = new ArticleCreateDateComparator(orderByAsc);
313         }
314         else if (orderByCol.equals("display-date")) {
315             orderByComparator = new ArticleDisplayDateComparator(orderByAsc);
316         }
317         else if (orderByCol.equals("id")) {
318             orderByComparator = new ArticleIDComparator(orderByAsc);
319         }
320         else if (orderByCol.equals("modified-date")) {
321             orderByComparator = new ArticleModifiedDateComparator(orderByAsc);
322         }
323         else if (orderByCol.equals("review-date")) {
324             orderByComparator = new ArticleReviewDateComparator(orderByAsc);
325         }
326         else if (orderByCol.equals("title")) {
327             orderByComparator = new ArticleTitleComparator(orderByAsc);
328         }
329         else if (orderByCol.equals("version")) {
330             orderByComparator = new ArticleVersionComparator(orderByAsc);
331         }
332 
333         return orderByComparator;
334     }
335 
336     public static String getEmailFromAddress(PortletPreferences preferences) {
337         String emailFromAddress = PropsUtil.get(
338             PropsKeys.JOURNAL_EMAIL_FROM_ADDRESS);
339 
340         return preferences.getValue("email-from-address", emailFromAddress);
341     }
342 
343     public static String getEmailFromName(PortletPreferences preferences) {
344         String emailFromName = PropsUtil.get(
345             PropsKeys.JOURNAL_EMAIL_FROM_NAME);
346 
347         return preferences.getValue("email-from-name", emailFromName);
348     }
349 
350     public static boolean getEmailArticleApprovalDeniedEnabled(
351         PortletPreferences preferences) {
352 
353         String emailArticleApprovalDeniedEnabled = preferences.getValue(
354             "email-article-approval-denied-enabled", StringPool.BLANK);
355 
356         if (Validator.isNotNull(emailArticleApprovalDeniedEnabled)) {
357             return GetterUtil.getBoolean(emailArticleApprovalDeniedEnabled);
358         }
359         else {
360             return GetterUtil.getBoolean(PropsUtil.get(
361                 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_DENIED_ENABLED));
362         }
363     }
364 
365     public static String getEmailArticleApprovalDeniedBody(
366         PortletPreferences preferences) {
367 
368         String emailArticleApprovalDeniedBody = preferences.getValue(
369             "email-article-approval-denied-body", StringPool.BLANK);
370 
371         if (Validator.isNotNull(emailArticleApprovalDeniedBody)) {
372             return emailArticleApprovalDeniedBody;
373         }
374         else {
375             return ContentUtil.get(PropsUtil.get(
376                 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_DENIED_BODY));
377         }
378     }
379 
380     public static String getEmailArticleApprovalDeniedSubject(
381         PortletPreferences preferences) {
382 
383         String emailArticleApprovalDeniedSubject = preferences.getValue(
384             "email-article-approval-denied-subject", StringPool.BLANK);
385 
386         if (Validator.isNotNull(emailArticleApprovalDeniedSubject)) {
387             return emailArticleApprovalDeniedSubject;
388         }
389         else {
390             return ContentUtil.get(PropsUtil.get(
391                 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_DENIED_SUBJECT));
392         }
393     }
394 
395     public static boolean getEmailArticleApprovalGrantedEnabled(
396         PortletPreferences preferences) {
397 
398         String emailArticleApprovalGrantedEnabled = preferences.getValue(
399             "email-article-approval-granted-enabled", StringPool.BLANK);
400 
401         if (Validator.isNotNull(emailArticleApprovalGrantedEnabled)) {
402             return GetterUtil.getBoolean(emailArticleApprovalGrantedEnabled);
403         }
404         else {
405             return GetterUtil.getBoolean(PropsUtil.get(
406                 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_GRANTED_ENABLED));
407         }
408     }
409 
410     public static String getEmailArticleApprovalGrantedBody(
411         PortletPreferences preferences) {
412 
413         String emailArticleApprovalGrantedBody = preferences.getValue(
414             "email-article-approval-granted-body", StringPool.BLANK);
415 
416         if (Validator.isNotNull(emailArticleApprovalGrantedBody)) {
417             return emailArticleApprovalGrantedBody;
418         }
419         else {
420             return ContentUtil.get(PropsUtil.get(
421                 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_GRANTED_BODY));
422         }
423     }
424 
425     public static String getEmailArticleApprovalGrantedSubject(
426         PortletPreferences preferences) {
427 
428         String emailArticleApprovalGrantedSubject = preferences.getValue(
429             "email-article-approval-granted-subject", StringPool.BLANK);
430 
431         if (Validator.isNotNull(emailArticleApprovalGrantedSubject)) {
432             return emailArticleApprovalGrantedSubject;
433         }
434         else {
435             return ContentUtil.get(PropsUtil.get(
436                 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_GRANTED_SUBJECT));
437         }
438     }
439 
440     public static boolean getEmailArticleApprovalRequestedEnabled(
441         PortletPreferences preferences) {
442 
443         String emailArticleApprovalRequestedEnabled = preferences.getValue(
444             "email-article-approval-requested-enabled", StringPool.BLANK);
445 
446         if (Validator.isNotNull(emailArticleApprovalRequestedEnabled)) {
447             return GetterUtil.getBoolean(emailArticleApprovalRequestedEnabled);
448         }
449         else {
450             return GetterUtil.getBoolean(PropsUtil.get(
451                 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_REQUESTED_ENABLED));
452         }
453     }
454 
455     public static String getEmailArticleApprovalRequestedBody(
456         PortletPreferences preferences) {
457 
458         String emailArticleApprovalRequestedBody = preferences.getValue(
459             "email-article-approval-requested-body", StringPool.BLANK);
460 
461         if (Validator.isNotNull(emailArticleApprovalRequestedBody)) {
462             return emailArticleApprovalRequestedBody;
463         }
464         else {
465             return ContentUtil.get(PropsUtil.get(
466                 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_REQUESTED_BODY));
467         }
468     }
469 
470     public static String getEmailArticleApprovalRequestedSubject(
471         PortletPreferences preferences) {
472 
473         String emailArticleApprovalRequestedSubject = preferences.getValue(
474             "email-article-approval-requested-subject", StringPool.BLANK);
475 
476         if (Validator.isNotNull(emailArticleApprovalRequestedSubject)) {
477             return emailArticleApprovalRequestedSubject;
478         }
479         else {
480             return ContentUtil.get(PropsUtil.get(
481                 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_REQUESTED_SUBJECT));
482         }
483     }
484 
485     public static boolean getEmailArticleReviewEnabled(
486         PortletPreferences preferences) {
487 
488         String emailArticleReviewEnabled = preferences.getValue(
489             "email-article-review-enabled", StringPool.BLANK);
490 
491         if (Validator.isNotNull(emailArticleReviewEnabled)) {
492             return GetterUtil.getBoolean(emailArticleReviewEnabled);
493         }
494         else {
495             return GetterUtil.getBoolean(PropsUtil.get(
496                 PropsKeys.JOURNAL_EMAIL_ARTICLE_REVIEW_ENABLED));
497         }
498     }
499 
500     public static String getEmailArticleReviewBody(
501         PortletPreferences preferences) {
502 
503         String emailArticleReviewBody = preferences.getValue(
504             "email-article-review-body", StringPool.BLANK);
505 
506         if (Validator.isNotNull(emailArticleReviewBody)) {
507             return emailArticleReviewBody;
508         }
509         else {
510             return ContentUtil.get(PropsUtil.get(
511                 PropsKeys.JOURNAL_EMAIL_ARTICLE_REVIEW_BODY));
512         }
513     }
514 
515     public static String getEmailArticleReviewSubject(
516         PortletPreferences preferences) {
517 
518         String emailArticleReviewSubject = preferences.getValue(
519             "email-article-review-subject", StringPool.BLANK);
520 
521         if (Validator.isNotNull(emailArticleReviewSubject)) {
522             return emailArticleReviewSubject;
523         }
524         else {
525             return ContentUtil.get(PropsUtil.get(
526                 PropsKeys.JOURNAL_EMAIL_ARTICLE_REVIEW_SUBJECT));
527         }
528     }
529 
530     public static Stack<JournalArticle> getRecentArticles(
531         PortletRequest portletRequest) {
532 
533         PortletSession portletSession = portletRequest.getPortletSession();
534 
535         Stack<JournalArticle> recentArticles =
536             (Stack<JournalArticle>)portletSession.getAttribute(
537                 WebKeys.JOURNAL_RECENT_ARTICLES);
538 
539         if (recentArticles == null) {
540             recentArticles = new FiniteUniqueStack<JournalArticle>(
541                 MAX_STACK_SIZE);
542 
543             portletSession.setAttribute(
544                 WebKeys.JOURNAL_RECENT_ARTICLES, recentArticles);
545         }
546 
547         return recentArticles;
548     }
549 
550     public static Stack<JournalStructure> getRecentStructures(
551         PortletRequest portletRequest) {
552 
553         PortletSession portletSession = portletRequest.getPortletSession();
554 
555         Stack<JournalStructure> recentStructures =
556             (Stack<JournalStructure>)portletSession.getAttribute(
557                 WebKeys.JOURNAL_RECENT_STRUCTURES);
558 
559         if (recentStructures == null) {
560             recentStructures = new FiniteUniqueStack<JournalStructure>(
561                 MAX_STACK_SIZE);
562 
563             portletSession.setAttribute(
564                 WebKeys.JOURNAL_RECENT_STRUCTURES, recentStructures);
565         }
566 
567         return recentStructures;
568     }
569 
570     public static Stack<JournalTemplate> getRecentTemplates(
571         PortletRequest portletRequest) {
572 
573         PortletSession portletSession = portletRequest.getPortletSession();
574 
575         Stack<JournalTemplate> recentTemplates =
576             (Stack<JournalTemplate>)portletSession.getAttribute(
577                 WebKeys.JOURNAL_RECENT_TEMPLATES);
578 
579         if (recentTemplates == null) {
580             recentTemplates = new FiniteUniqueStack<JournalTemplate>(
581                 MAX_STACK_SIZE);
582 
583             portletSession.setAttribute(
584                 WebKeys.JOURNAL_RECENT_TEMPLATES, recentTemplates);
585         }
586 
587         return recentTemplates;
588     }
589 
590     public static String getTemplateScript(
591             long groupId, String templateId, Map<String, String> tokens,
592             String languageId)
593         throws PortalException, SystemException {
594 
595         return getTemplateScript(groupId, templateId, tokens, languageId, true);
596     }
597 
598     public static String getTemplateScript(
599             long groupId, String templateId, Map<String, String> tokens,
600             String languageId, boolean transform)
601         throws PortalException, SystemException {
602 
603         JournalTemplate template = JournalTemplateLocalServiceUtil.getTemplate(
604             groupId, templateId);
605 
606         return getTemplateScript(template, tokens, languageId, transform);
607     }
608 
609     public static String getTemplateScript(
610         JournalTemplate template, Map<String, String> tokens, String languageId,
611         boolean transform) {
612 
613         String script = template.getXsl();
614 
615         if (transform) {
616 
617             // Listeners
618 
619             String[] listeners =
620                 PropsUtil.getArray(PropsKeys.JOURNAL_TRANSFORMER_LISTENER);
621 
622             for (int i = 0; i < listeners.length; i++) {
623                 TransformerListener listener = null;
624 
625                 try {
626                     listener =
627                         (TransformerListener)Class.forName(
628                             listeners[i]).newInstance();
629 
630                     listener.setTemplateDriven(true);
631                     listener.setLanguageId(languageId);
632                     listener.setTokens(tokens);
633                 }
634                 catch (Exception e) {
635                     _log.error(e, e);
636                 }
637 
638                 // Modify transform script
639 
640                 if (listener != null) {
641                     script = listener.onScript(script);
642                 }
643             }
644         }
645 
646         return script;
647     }
648 
649     public static Map<String, String> getTokens(
650         long groupId, ThemeDisplay themeDisplay) {
651 
652         return getTokens(groupId, themeDisplay, null);
653     }
654 
655     public static Map<String, String> getTokens(
656         long groupId, ThemeDisplay themeDisplay, String xmlRequest) {
657 
658         Map<String, String> tokens = new HashMap<String, String>();
659 
660         if (themeDisplay != null) {
661             _populateTokens(tokens, groupId, themeDisplay);
662         }
663         else if (Validator.isNotNull(xmlRequest)) {
664             try {
665                 _populateTokens(tokens, groupId, xmlRequest);
666             }
667             catch (Exception e) {
668                 if (_log.isWarnEnabled()) {
669                     _log.warn(e, e);
670                 }
671             }
672         }
673 
674         return tokens;
675     }
676 
677     public static String getUrlTitle(long id, String title) {
678         title = title.trim().toLowerCase();
679 
680         if (Validator.isNull(title) || Validator.isNumber(title) ||
681             title.equals("rss")) {
682 
683             return String.valueOf(id);
684         }
685         else {
686             return FriendlyURLNormalizer.normalize(
687                 title, _URL_TITLE_REPLACE_CHARS);
688         }
689     }
690 
691     public static String mergeArticleContent(
692         String curContent, String newContent) {
693 
694         try {
695             Document curDocument = SAXReaderUtil.read(curContent);
696             Document newDocument = SAXReaderUtil.read(newContent);
697 
698             Element curRoot = curDocument.getRootElement();
699             Element newRoot = newDocument.getRootElement();
700 
701             curRoot.addAttribute(
702                 "default-locale",
703                 newRoot.attributeValue("default-locale"));
704             curRoot.addAttribute(
705                 "available-locales",
706                 newRoot.attributeValue("available-locales"));
707 
708             _mergeArticleContentUpdate(
709                 curDocument, newRoot,
710                 LocaleUtil.toLanguageId(LocaleUtil.getDefault()));
711             _mergeArticleContentDelete(curRoot, newDocument);
712 
713             curContent = JournalUtil.formatXML(curDocument);
714         }
715         catch (Exception e) {
716             _log.error(e, e);
717         }
718 
719         return curContent;
720     }
721 
722     public static String removeArticleLocale(
723         String content, String languageId) {
724 
725         try {
726             Document doc = SAXReaderUtil.read(content);
727 
728             Element root = doc.getRootElement();
729 
730             String availableLocales = root.attributeValue("available-locales");
731 
732             if (availableLocales == null) {
733                 return content;
734             }
735 
736             availableLocales = StringUtil.remove(availableLocales, languageId);
737 
738             if (availableLocales.endsWith(",")) {
739                 availableLocales = availableLocales.substring(
740                     0, availableLocales.length() - 1);
741             }
742 
743             root.addAttribute("available-locales", availableLocales);
744 
745             removeArticleLocale(root, languageId);
746 
747             content = formatXML(doc);
748         }
749         catch (Exception e) {
750             _log.error(e, e);
751         }
752 
753         return content;
754     }
755 
756     public static void removeArticleLocale(Element el, String languageId)
757         throws PortalException, SystemException {
758 
759         for (Element dynamicEl : el.elements("dynamic-element")) {
760             for (Element dynamicContentEl :
761                     dynamicEl.elements("dynamic-content")) {
762 
763                 String curLanguageId = GetterUtil.getString(
764                     dynamicContentEl.attributeValue("language-id"));
765 
766                 if (curLanguageId.equals(languageId)) {
767                     long id = GetterUtil.getLong(
768                         dynamicContentEl.attributeValue("id"));
769 
770                     if (id > 0) {
771                         ImageLocalServiceUtil.deleteImage(id);
772                     }
773 
774                     dynamicContentEl.detach();
775                 }
776             }
777 
778             removeArticleLocale(dynamicEl, languageId);
779         }
780     }
781 
782     public static String removeOldContent(String content, String xsd) {
783         try {
784             Document contentDoc = SAXReaderUtil.read(content);
785             Document xsdDoc = SAXReaderUtil.read(xsd);
786 
787             Element contentRoot = contentDoc.getRootElement();
788 
789             Stack<String> path = new Stack<String>();
790 
791             path.push(contentRoot.getName());
792 
793             _removeOldContent(path, contentRoot, xsdDoc);
794 
795             content = formatXML(contentDoc);
796         }
797         catch (Exception e) {
798             _log.error(e, e);
799         }
800 
801         return content;
802     }
803 
804     public static void removeRecentArticle(
805         PortletRequest portletRequest, String articleId) {
806 
807         Stack<JournalArticle> stack = getRecentArticles(portletRequest);
808 
809         Iterator<JournalArticle> itr = stack.iterator();
810 
811         while (itr.hasNext()) {
812             JournalArticle journalArticle = itr.next();
813 
814             if (journalArticle.getArticleId().equals(articleId)) {
815                 itr.remove();
816 
817                 break;
818             }
819         }
820     }
821 
822     public static void removeRecentStructure(
823         PortletRequest portletRequest, String structureId) {
824 
825         Stack<JournalStructure> stack = getRecentStructures(portletRequest);
826 
827         Iterator<JournalStructure> itr = stack.iterator();
828 
829         while (itr.hasNext()) {
830             JournalStructure journalStructure = itr.next();
831 
832             if (journalStructure.getStructureId().equals(structureId)) {
833                 itr.remove();
834 
835                 break;
836             }
837         }
838     }
839 
840     public static void removeRecentTemplate(
841         PortletRequest portletRequest, String templateId) {
842 
843         Stack<JournalTemplate> stack = getRecentTemplates(portletRequest);
844 
845         Iterator<JournalTemplate> itr = stack.iterator();
846 
847         while (itr.hasNext()) {
848             JournalTemplate journalTemplate = itr.next();
849 
850             if (journalTemplate.getTemplateId().equals(templateId)) {
851                 itr.remove();
852 
853                 break;
854             }
855         }
856     }
857 
858     public static String transform(
859             ThemeDisplay themeDisplay, Map<String, String> tokens,
860             String viewMode, String languageId, String xml, String script,
861             String langType)
862         throws Exception {
863 
864         // Setup Listeners
865 
866         if (_log.isDebugEnabled()) {
867             _log.debug("Language " + languageId);
868         }
869 
870         if (Validator.isNull(viewMode)) {
871             viewMode = Constants.VIEW;
872         }
873 
874         if (_logTokens.isDebugEnabled()) {
875             String tokensString = PropertiesUtil.list(tokens);
876 
877             _logTokens.debug(tokensString);
878         }
879 
880         if (_logTransformBefore.isDebugEnabled()) {
881             _logTransformBefore.debug(xml);
882         }
883 
884         List<TransformerListener> listenersList =
885             new ArrayList<TransformerListener>();
886 
887         String[] listeners = PropsUtil.getArray(
888             PropsKeys.JOURNAL_TRANSFORMER_LISTENER);
889 
890         for (int i = 0; i < listeners.length; i++) {
891             TransformerListener listener = null;
892 
893             try {
894                 if (_log.isDebugEnabled()) {
895                     _log.debug("Instantiate listener " + listeners[i]);
896                 }
897 
898                 boolean templateDriven = Validator.isNotNull(langType);
899 
900                 listener = (TransformerListener)Class.forName(
901                     listeners[i]).newInstance();
902 
903                 listener.setTemplateDriven(templateDriven);
904                 listener.setLanguageId(languageId);
905                 listener.setTokens(tokens);
906 
907                 listenersList.add(listener);
908             }
909             catch (Exception e) {
910                 _log.error(e, e);
911             }
912 
913             // Modify XML
914 
915             if (_logXmlBeforeListener.isDebugEnabled()) {
916                 _logXmlBeforeListener.debug(xml);
917             }
918 
919             if (listener != null) {
920                 xml = listener.onXml(xml);
921 
922                 if (_logXmlAfterListener.isDebugEnabled()) {
923                     _logXmlAfterListener.debug(xml);
924                 }
925             }
926 
927             // Modify script
928 
929             if (_logScriptBeforeListener.isDebugEnabled()) {
930                 _logScriptBeforeListener.debug(script);
931             }
932 
933             if (listener != null) {
934                 script = listener.onScript(script);
935 
936                 if (_logScriptAfterListener.isDebugEnabled()) {
937                     _logScriptAfterListener.debug(script);
938                 }
939             }
940         }
941 
942         // Transform
943 
944         String output = null;
945 
946         if (Validator.isNull(langType)) {
947             output = LocalizationUtil.getLocalization(xml, languageId);
948         }
949         else {
950             String templateParserClassName = PropsUtil.get(
951                 PropsKeys.JOURNAL_TEMPLATE_LANGUAGE_PARSER,
952                 new Filter(langType));
953 
954             if (_log.isDebugEnabled()) {
955                 _log.debug(
956                     "Template parser class name " + templateParserClassName);
957             }
958 
959             if (Validator.isNotNull(templateParserClassName)) {
960                 TemplateParser templateParser =
961                     (TemplateParser)InstancePool.get(templateParserClassName);
962 
963                 if (templateParser == null) {
964                     throw new TransformException(
965                         "No template parser found for " +
966                             templateParserClassName);
967                 }
968 
969                 output = templateParser.transform(
970                     themeDisplay, tokens, viewMode, languageId, xml, script);
971             }
972         }
973 
974         // Postprocess output
975 
976         for (int i = 0; i < listenersList.size(); i++) {
977             TransformerListener listener = listenersList.get(i);
978 
979             // Modify output
980 
981             if (_logOutputBeforeListener.isDebugEnabled()) {
982                 _logOutputBeforeListener.debug(output);
983             }
984 
985             output = listener.onOutput(output);
986 
987             if (_logOutputAfterListener.isDebugEnabled()) {
988                 _logOutputAfterListener.debug(output);
989             }
990         }
991 
992         if (_logTransfromAfter.isDebugEnabled()) {
993             _logTransfromAfter.debug(output);
994         }
995 
996         return output;
997     }
998 
999     private static void _addElementOptions (
1000        Element curContentElement, Element newContentElement) {
1001
1002        List<Element> newElementOptions = newContentElement.elements("option");
1003
1004        for (Element newElementOption : newElementOptions) {
1005            Element curElementOption = SAXReaderUtil.createElement("option");
1006
1007            curElementOption.addCDATA(newElementOption.getText());
1008
1009            curContentElement.add(curElementOption);
1010        }
1011    }
1012
1013    private static Element _getElementByInstanceId(
1014        Document document, String instanceId) {
1015
1016        XPath xPathSelector = SAXReaderUtil.createXPath(
1017            "//dynamic-element[@instance-id='" + instanceId + "']");
1018
1019        List<Node> nodes = xPathSelector.selectNodes(document);
1020
1021        if (nodes.size() == 1) {
1022            return (Element)nodes.get(0);
1023        }
1024        else {
1025            return null;
1026        }
1027    }
1028
1029    private static void _mergeArticleContentDelete(
1030            Element curParentElement, Document newDocument)
1031        throws Exception {
1032
1033        List<Element> curElements = curParentElement.elements(
1034            "dynamic-element");
1035
1036        for (int i = 0; i < curElements.size(); i++) {
1037            Element curElement = curElements.get(i);
1038
1039            _mergeArticleContentDelete(curElement, newDocument);
1040
1041            String instanceId = curElement.attributeValue("instance-id");
1042
1043            Element newElement = _getElementByInstanceId(
1044                newDocument, instanceId);
1045
1046            if (newElement == null) {
1047                curElement.detach();
1048
1049                String type = curElement.attributeValue("type");
1050
1051                if (type.equals("image")) {
1052                    _mergeArticleContentDeleteImages(
1053                        curElement.elements("dynamic-content"));
1054                }
1055            }
1056        }
1057    }
1058
1059    private static void _mergeArticleContentDeleteImages(List<Element> elements)
1060        throws Exception {
1061
1062        for (Element element : elements) {
1063            long articleImageId = GetterUtil.getLong(
1064                element.attributeValue("id"));
1065
1066            JournalArticleImageLocalServiceUtil.deleteArticleImage(
1067                articleImageId);
1068        }
1069    }
1070
1071    private static void _mergeArticleContentUpdate(
1072            Document curDocument, Element newParentElement,
1073            String defaultLocale)
1074        throws Exception {
1075
1076        List<Element> newElements = newParentElement.elements(
1077            "dynamic-element");
1078
1079        for (int i = 0; i < newElements.size(); i++) {
1080            Element newElement = newElements.get(i);
1081
1082            _mergeArticleContentUpdate(
1083                curDocument, newParentElement, newElement, i, defaultLocale);
1084        }
1085    }
1086
1087    private static void _mergeArticleContentUpdate(
1088            Document curDocument, Element newParentElement, Element newElement,
1089            int pos, String defaultLocale)
1090        throws Exception {
1091
1092        _mergeArticleContentUpdate(curDocument, newElement, defaultLocale);
1093
1094        String instanceId = newElement.attributeValue("instance-id");
1095
1096        Element curElement = _getElementByInstanceId(curDocument, instanceId);
1097
1098        if (curElement != null) {
1099            _mergeArticleContentUpdate(curElement, newElement, defaultLocale);
1100        }
1101        else {
1102            String parentInstanceId = newParentElement.attributeValue(
1103                "instance-id");
1104
1105            if (Validator.isNull(parentInstanceId)) {
1106                Element curRoot = curDocument.getRootElement();
1107
1108                List<Element> curRootElements = curRoot.elements();
1109
1110                curRootElements.add(pos, newElement.createCopy());
1111            }
1112            else {
1113                Element curParentElement = _getElementByInstanceId(
1114                    curDocument, parentInstanceId);
1115
1116                if (curParentElement != null) {
1117                    List<Element> curParentElements =
1118                        curParentElement.elements();
1119
1120                    curParentElements.add(pos, newElement.createCopy());
1121                }
1122            }
1123        }
1124    }
1125
1126    private static void _mergeArticleContentUpdate(
1127        Element curElement, Element newElement, String defaultLocale) {
1128
1129        Attribute curTypeAttribute = curElement.attribute("type");
1130        Attribute newTypeAttribute = newElement.attribute("type");
1131
1132        curTypeAttribute.setValue(newTypeAttribute.getValue());
1133
1134        Attribute curIndexTypeAttribute = curElement.attribute("index-type");
1135        Attribute newIndexTypeAttribute = newElement.attribute("index-type");
1136
1137        if (newIndexTypeAttribute != null) {
1138            if (curIndexTypeAttribute == null) {
1139                curElement.addAttribute(
1140                    "index-type", newIndexTypeAttribute.getValue());
1141            } else {
1142                curIndexTypeAttribute.setValue(
1143                    newIndexTypeAttribute.getValue());
1144            }
1145        }
1146
1147        Element newContentElement = newElement.elements(
1148            "dynamic-content").get(0);
1149
1150        String newLanguageId = newContentElement.attributeValue("language-id");
1151        String newValue = newContentElement.getText();
1152
1153        List<Element> curContentElements = curElement.elements(
1154            "dynamic-content");
1155
1156        if (Validator.isNull(newLanguageId)) {
1157            for (Element curContentElement : curContentElements) {
1158                curContentElement.detach();
1159            }
1160
1161            Element curContentElement = SAXReaderUtil.createElement(
1162                "dynamic-content");
1163
1164            if (newContentElement.element("option") != null) {
1165                _addElementOptions(curContentElement, newContentElement);
1166            }
1167            else {
1168                curContentElement.addCDATA(newValue);
1169            }
1170
1171            curElement.add(curContentElement);
1172        }
1173        else {
1174            boolean alreadyExists = false;
1175
1176            for (Element curContentElement : curContentElements) {
1177                String curLanguageId = curContentElement.attributeValue(
1178                    "language-id");
1179
1180                if (newLanguageId.equals(curLanguageId)) {
1181                    alreadyExists = true;
1182
1183                    curContentElement.clearContent();
1184
1185                    if (newContentElement.element("option") != null) {
1186                        _addElementOptions(
1187                            curContentElement, newContentElement);
1188                    }
1189                    else {
1190                        curContentElement.addCDATA(newValue);
1191                    }
1192
1193                    break;
1194                }
1195            }
1196
1197            if (!alreadyExists) {
1198                Element curContentElement = curContentElements.get(0);
1199
1200                String curLanguageId = curContentElement.attributeValue(
1201                    "language-id");
1202
1203                if (Validator.isNull(curLanguageId)) {
1204                    curContentElement.detach();
1205                }
1206
1207                curElement.add(newContentElement.createCopy());
1208            }
1209        }
1210    }
1211
1212    private static void _populateCustomTokens(Map<String, String> tokens) {
1213        if (_customTokens == null) {
1214            synchronized (JournalUtil.class) {
1215                _customTokens = new HashMap<String, String>();
1216
1217                for (String customToken :
1218                        PropsValues.JOURNAL_ARTICLE_CUSTOM_TOKENS) {
1219
1220                    String value = PropsUtil.get(
1221                        PropsKeys.JOURNAL_ARTICLE_CUSTOM_TOKEN_VALUE,
1222                        new Filter(customToken));
1223
1224                    _customTokens.put(customToken, value);
1225                }
1226            }
1227        }
1228
1229        if (!_customTokens.isEmpty()) {
1230            tokens.putAll(_customTokens);
1231        }
1232    }
1233
1234    private static void _populateTokens(
1235            Map<String, String> tokens, long groupId, String xmlRequest)
1236        throws Exception {
1237
1238        Document request = SAXReaderUtil.read(xmlRequest);
1239
1240        Element root = request.getRootElement();
1241
1242        Element themeDisplayEl = root.element("theme-display");
1243
1244        Layout layout = LayoutLocalServiceUtil.getLayout(
1245            GetterUtil.getLong(themeDisplayEl.elementText("plid")));
1246
1247        Group group = layout.getGroup();
1248
1249        LayoutSet layoutSet = layout.getLayoutSet();
1250
1251        String friendlyUrlCurrent = null;
1252
1253        if (layout.isPublicLayout()) {
1254            friendlyUrlCurrent = themeDisplayEl.elementText(
1255                "path-friendly-url-public");
1256        }
1257        else if (group.isUserGroup()) {
1258            friendlyUrlCurrent = themeDisplayEl.elementText(
1259                "path-friendly-url-private-user");
1260        }
1261        else {
1262            friendlyUrlCurrent = themeDisplayEl.elementText(
1263                "path-friendly-url-private-group");
1264        }
1265
1266        String layoutSetFriendlyUrl = StringPool.BLANK;
1267
1268        String virtualHost = layoutSet.getVirtualHost();
1269
1270        if (Validator.isNull(virtualHost) ||
1271            !virtualHost.equals(themeDisplayEl.elementText("server-name"))) {
1272
1273            layoutSetFriendlyUrl = friendlyUrlCurrent + group.getFriendlyURL();
1274        }
1275
1276        tokens.put("cdn_host", themeDisplayEl.elementText("cdn-host"));
1277        tokens.put("company_id", themeDisplayEl.elementText("company-id"));
1278        tokens.put("friendly_url_current", friendlyUrlCurrent);
1279        tokens.put(
1280            "friendly_url_private_group",
1281            themeDisplayEl.elementText("path-friendly-url-private-group"));
1282        tokens.put(
1283            "friendly_url_private_user",
1284            themeDisplayEl.elementText("path-friendly-url-private-user"));
1285        tokens.put(
1286            "friendly_url_public",
1287            themeDisplayEl.elementText("path-friendly-url-public"));
1288        tokens.put("group_friendly_url", group.getFriendlyURL());
1289        tokens.put("group_id", String.valueOf(groupId));
1290        tokens.put("image_path", themeDisplayEl.elementText("path-image"));
1291        tokens.put("layout_set_friendly_url", layoutSetFriendlyUrl);
1292        tokens.put("main_path", themeDisplayEl.elementText("path-main"));
1293        tokens.put("portal_ctx", themeDisplayEl.elementText("path-context"));
1294        tokens.put(
1295            "portal_url",
1296            HttpUtil.removeProtocol(themeDisplayEl.elementText("url-portal")));
1297        tokens.put(
1298            "protocol",
1299            HttpUtil.getProtocol(themeDisplayEl.elementText("url-portal")));
1300        tokens.put("root_path", themeDisplayEl.elementText("path-context"));
1301        tokens.put(
1302            "theme_image_path",
1303            themeDisplayEl.elementText("path-theme-images"));
1304
1305        _populateCustomTokens(tokens);
1306
1307        // Deprecated tokens
1308
1309        tokens.put(
1310            "friendly_url",
1311            themeDisplayEl.elementText("path-friendly-url-public"));
1312        tokens.put(
1313            "friendly_url_private",
1314            themeDisplayEl.elementText("path-friendly-url-private-group"));
1315        tokens.put(
1316            "page_url", themeDisplayEl.elementText("path-friendly-url-public"));
1317    }
1318
1319    private static void _populateTokens(
1320        Map<String, String> tokens, long groupId, ThemeDisplay themeDisplay) {
1321
1322        Layout layout = themeDisplay.getLayout();
1323
1324        Group group = layout.getGroup();
1325
1326        LayoutSet layoutSet = layout.getLayoutSet();
1327
1328        String friendlyUrlCurrent = null;
1329
1330        if (layout.isPublicLayout()) {
1331            friendlyUrlCurrent = themeDisplay.getPathFriendlyURLPublic();
1332        }
1333        else if (group.isUserGroup()) {
1334            friendlyUrlCurrent = themeDisplay.getPathFriendlyURLPrivateUser();
1335        }
1336        else {
1337            friendlyUrlCurrent = themeDisplay.getPathFriendlyURLPrivateGroup();
1338        }
1339
1340        String layoutSetFriendlyUrl = StringPool.BLANK;
1341
1342        String virtualHost = layoutSet.getVirtualHost();
1343
1344        if (Validator.isNull(virtualHost) ||
1345            !virtualHost.equals(themeDisplay.getServerName())) {
1346
1347            layoutSetFriendlyUrl = friendlyUrlCurrent + group.getFriendlyURL();
1348        }
1349
1350        tokens.put("cdn_host", themeDisplay.getCDNHost());
1351        tokens.put("company_id", String.valueOf(themeDisplay.getCompanyId()));
1352        tokens.put("friendly_url_current", friendlyUrlCurrent);
1353        tokens.put(
1354            "friendly_url_private_group",
1355            themeDisplay.getPathFriendlyURLPrivateGroup());
1356        tokens.put(
1357            "friendly_url_private_user",
1358            themeDisplay.getPathFriendlyURLPrivateUser());
1359        tokens.put(
1360            "friendly_url_public", themeDisplay.getPathFriendlyURLPublic());
1361        tokens.put("group_friendly_url", group.getFriendlyURL());
1362        tokens.put("group_id", String.valueOf(groupId));
1363        tokens.put("image_path", themeDisplay.getPathImage());
1364        tokens.put("layout_set_friendly_url", layoutSetFriendlyUrl);
1365        tokens.put("main_path", themeDisplay.getPathMain());
1366        tokens.put("portal_ctx", themeDisplay.getPathContext());
1367        tokens.put(
1368            "portal_url", HttpUtil.removeProtocol(themeDisplay.getURLPortal()));
1369        tokens.put(
1370            "protocol", HttpUtil.getProtocol(themeDisplay.getURLPortal()));
1371        tokens.put("root_path", themeDisplay.getPathContext());
1372        tokens.put("theme_image_path", themeDisplay.getPathThemeImages());
1373
1374        _populateCustomTokens(tokens);
1375
1376        // Deprecated tokens
1377
1378        tokens.put("friendly_url", themeDisplay.getPathFriendlyURLPublic());
1379        tokens.put(
1380            "friendly_url_private",
1381            themeDisplay.getPathFriendlyURLPrivateGroup());
1382        tokens.put("page_url", themeDisplay.getPathFriendlyURLPublic());
1383    }
1384
1385    private static void _removeOldContent(
1386            Stack<String> path, Element contentEl, Document xsdDoc)
1387        throws SystemException {
1388
1389        String elPath = "";
1390
1391        for (int i = 0; i < path.size(); i++) {
1392            elPath += "/" + path.elementAt(i);
1393        }
1394
1395        for (int i = 0; i < contentEl.nodeCount(); i++) {
1396            Node contentNode = contentEl.node(i);
1397
1398            if (contentNode instanceof Element) {
1399                _removeOldContent(path, (Element)contentNode, xsdDoc, elPath);
1400            }
1401        }
1402    }
1403
1404    private static void _removeOldContent(
1405            Stack<String> path, Element contentEl, Document xsdDoc,
1406            String elPath)
1407        throws SystemException {
1408
1409        String name = contentEl.attributeValue("name");
1410
1411        if (Validator.isNull(name)) {
1412            return;
1413        }
1414
1415        String localPath = "dynamic-element[@name='" + name + "']";
1416
1417        String fullPath = elPath + "/" + localPath;
1418
1419        XPath xPathSelector = SAXReaderUtil.createXPath(fullPath);
1420
1421        List<Node> curNodes = xPathSelector.selectNodes(xsdDoc);
1422
1423        if (curNodes.size() == 0) {
1424            contentEl.detach();
1425        }
1426
1427        path.push(localPath);
1428
1429        _removeOldContent(path, contentEl, xsdDoc);
1430
1431        path.pop();
1432    }
1433
1434    private static final char[] _URL_TITLE_REPLACE_CHARS = new char[] {
1435        '.', '/'
1436    };
1437
1438    private static Log _log = LogFactoryUtil.getLog(JournalUtil.class);
1439
1440    private static Log _logOutputAfterListener = LogFactoryUtil.getLog(
1441        JournalUtil.class.getName() + ".OutputAfterListener");
1442
1443    private static Log _logOutputBeforeListener = LogFactoryUtil.getLog(
1444        JournalUtil.class.getName() + ".OutputBeforeListener");
1445
1446    private static Log _logScriptAfterListener = LogFactoryUtil.getLog(
1447        JournalUtil.class.getName() + ".ScriptAfterListener");
1448
1449    private static Log _logScriptBeforeListener = LogFactoryUtil.getLog(
1450        JournalUtil.class.getName() + ".ScriptBeforeListener");
1451
1452    private static Log _logTransfromAfter = LogFactoryUtil.getLog(
1453        JournalUtil.class.getName() + ".TransformAfter");
1454
1455    private static Log _logTransformBefore = LogFactoryUtil.getLog(
1456        JournalUtil.class.getName() + ".BeforeTransform");
1457
1458    private static Log _logTokens = LogFactoryUtil.getLog(
1459        JournalUtil.class.getName() + ".Tokens");
1460
1461    private static Log _logXmlAfterListener = LogFactoryUtil.getLog(
1462        JournalUtil.class.getName() + ".XmlAfterListener");
1463
1464    private static Log _logXmlBeforeListener = LogFactoryUtil.getLog(
1465        JournalUtil.class.getName() + ".XmlBeforeListener");
1466
1467    private static Map<String, String> _customTokens;
1468
1469}