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