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.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
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
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(value);
159
160 dynamicEl.add(dynamicContent);
161
162 root.add(dynamicEl);
163 }
164
165
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
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
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
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
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
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
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
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
976 for (int i = 0; i < listenersList.size(); i++) {
977 TransformerListener listener = listenersList.get(i);
978
979
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
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
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}