001    /**
002     * Copyright (c) 2000-2012 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.layoutsadmin.util;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.language.LanguageUtil;
020    import com.liferay.portal.kernel.util.GetterUtil;
021    import com.liferay.portal.kernel.util.LocaleUtil;
022    import com.liferay.portal.kernel.util.StringBundler;
023    import com.liferay.portal.kernel.util.StringPool;
024    import com.liferay.portal.kernel.util.StringUtil;
025    import com.liferay.portal.kernel.util.UnicodeProperties;
026    import com.liferay.portal.kernel.util.Validator;
027    import com.liferay.portal.kernel.workflow.WorkflowConstants;
028    import com.liferay.portal.kernel.xml.Document;
029    import com.liferay.portal.kernel.xml.Element;
030    import com.liferay.portal.kernel.xml.SAXReaderUtil;
031    import com.liferay.portal.model.Layout;
032    import com.liferay.portal.model.LayoutConstants;
033    import com.liferay.portal.service.GroupLocalServiceUtil;
034    import com.liferay.portal.service.LayoutLocalServiceUtil;
035    import com.liferay.portal.theme.ThemeDisplay;
036    import com.liferay.portal.util.PortalUtil;
037    import com.liferay.portlet.journal.model.JournalArticle;
038    import com.liferay.portlet.journal.model.JournalArticleConstants;
039    import com.liferay.portlet.journal.service.JournalArticleServiceUtil;
040    
041    import java.util.ArrayList;
042    import java.util.List;
043    import java.util.Locale;
044    
045    /**
046     * @author Jorge Ferrer
047     */
048    public class SitemapImpl implements Sitemap {
049    
050            public String encodeXML(String input) {
051                    return StringUtil.replace(
052                            input,
053                            new String[] {"&", "<", ">", "'", "\""},
054                            new String[] {"&amp;", "&lt;", "&gt;", "&apos;", "&quot;"});
055            }
056    
057            public String getSitemap(
058                            long groupId, boolean privateLayout, ThemeDisplay themeDisplay)
059                    throws PortalException, SystemException {
060    
061                    Document document = SAXReaderUtil.createDocument();
062    
063                    document.setXMLEncoding(StringPool.UTF8);
064    
065                    Element rootElement = document.addElement(
066                            "urlset", "http://www.google.com/schemas/sitemap/0.84");
067    
068                    List<Layout> layouts = LayoutLocalServiceUtil.getLayouts(
069                            groupId, privateLayout, LayoutConstants.DEFAULT_PARENT_LAYOUT_ID);
070    
071                    visitLayouts(rootElement, layouts, themeDisplay);
072    
073                    return document.asXML();
074            }
075    
076            protected void addURLElement(
077                    Element element, String url, UnicodeProperties typeSettingsProperties) {
078    
079                    Element urlElement = element.addElement("url");
080    
081                    Element locElement = urlElement.addElement("loc");
082    
083                    locElement.addText(encodeXML(url));
084    
085                    if (typeSettingsProperties == null) {
086                            return;
087                    }
088    
089                    String changefreq = typeSettingsProperties.getProperty(
090                            "sitemap-changefreq");
091    
092                    if (Validator.isNotNull(changefreq)) {
093                            Element changefreqElement = urlElement.addElement("changefreq");
094    
095                            changefreqElement.addText(changefreq);
096                    }
097    
098                    String priority = typeSettingsProperties.getProperty(
099                            "sitemap-priority");
100    
101                    if (Validator.isNotNull(priority)) {
102                            Element priorityElement = urlElement.addElement("priority");
103    
104                            priorityElement.addText(priority);
105                    }
106            }
107    
108            protected void visitArticles(
109                            Element element, Layout layout, ThemeDisplay themeDisplay)
110                    throws PortalException, SystemException {
111    
112                    List<JournalArticle> journalArticles =
113                            JournalArticleServiceUtil.getArticlesByLayoutUuid(
114                                    layout.getGroupId(), layout.getUuid());
115    
116                    if (journalArticles.isEmpty()) {
117                            return;
118                    }
119    
120                    List<String> processedArticleIds = new ArrayList<String>();
121    
122                    for (JournalArticle journalArticle : journalArticles) {
123                            if (processedArticleIds.contains(
124                                            journalArticle.getArticleId()) ||
125                                    (journalArticle.getStatus() !=
126                                            WorkflowConstants.STATUS_APPROVED)) {
127    
128                                    continue;
129                            }
130    
131                            String portalURL = PortalUtil.getPortalURL(layout, themeDisplay);
132    
133                            String groupFriendlyURL = PortalUtil.getGroupFriendlyURL(
134                                    GroupLocalServiceUtil.getGroup(journalArticle.getGroupId()),
135                                    false, themeDisplay);
136    
137                            StringBundler sb = new StringBundler(4);
138    
139                            if (!groupFriendlyURL.startsWith(portalURL)) {
140                                    sb.append(portalURL);
141                            }
142    
143                            sb.append(groupFriendlyURL);
144                            sb.append(JournalArticleConstants.CANONICAL_URL_SEPARATOR);
145                            sb.append(journalArticle.getUrlTitle());
146    
147                            String articleURL = PortalUtil.getCanonicalURL(
148                                    sb.toString(), themeDisplay, layout);
149    
150                            addURLElement(element, articleURL, null);
151    
152                            Locale[] availableLocales = LanguageUtil.getAvailableLocales();
153    
154                            if (availableLocales.length > 1) {
155                                    Locale defaultLocale = LocaleUtil.getDefault();
156    
157                                    for (Locale availableLocale : availableLocales) {
158                                            if (!availableLocale.equals(defaultLocale)) {
159                                                    String alternateURL = PortalUtil.getAlternateURL(
160                                                            articleURL, themeDisplay, availableLocale);
161    
162                                                    addURLElement(element, alternateURL, null);
163                                            }
164                                    }
165                            }
166    
167                            processedArticleIds.add(journalArticle.getArticleId());
168                    }
169            }
170    
171            protected void visitLayout(
172                            Element element, Layout layout, ThemeDisplay themeDisplay)
173                    throws PortalException, SystemException {
174    
175                    UnicodeProperties typeSettingsProperties =
176                            layout.getTypeSettingsProperties();
177    
178                    if (layout.isHidden() || !PortalUtil.isLayoutSitemapable(layout) ||
179                            !GetterUtil.getBoolean(
180                                    typeSettingsProperties.getProperty("sitemap-include"), true)) {
181    
182                            return;
183                    }
184    
185                    String layoutFullURL = PortalUtil.getLayoutFullURL(
186                            layout, themeDisplay);
187    
188                    layoutFullURL = PortalUtil.getCanonicalURL(
189                            layoutFullURL, themeDisplay, layout);
190    
191                    addURLElement(element, layoutFullURL, typeSettingsProperties);
192    
193                    Locale[] availableLocales = LanguageUtil.getAvailableLocales();
194    
195                    if (availableLocales.length > 1) {
196                            Locale defaultLocale = LocaleUtil.getDefault();
197    
198                            for (Locale availableLocale : availableLocales) {
199                                    if (availableLocale.equals(defaultLocale)) {
200                                            continue;
201                                    }
202    
203                                    String alternateURL = PortalUtil.getAlternateURL(
204                                            layoutFullURL, themeDisplay, availableLocale);
205    
206                                    addURLElement(element, alternateURL, null);
207                            }
208                    }
209    
210                    visitArticles(element, layout, themeDisplay);
211                    visitLayouts(element, layout.getChildren(), themeDisplay);
212            }
213    
214            protected void visitLayouts(
215                            Element element, List<Layout> layouts, ThemeDisplay themeDisplay)
216                    throws PortalException, SystemException {
217    
218                    for (Layout layout : layouts) {
219                            visitLayout(element, layout, themeDisplay);
220                    }
221            }
222    
223    }