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