001    /**
002     * Copyright (c) 2000-present 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.layouts.admin.kernel.util.Sitemap;
018    import com.liferay.layouts.admin.kernel.util.SitemapURLProvider;
019    import com.liferay.layouts.admin.kernel.util.SitemapURLProviderRegistryUtil;
020    import com.liferay.portal.kernel.exception.PortalException;
021    import com.liferay.portal.kernel.language.LanguageUtil;
022    import com.liferay.portal.kernel.model.Layout;
023    import com.liferay.portal.kernel.model.LayoutSet;
024    import com.liferay.portal.kernel.security.pacl.DoPrivileged;
025    import com.liferay.portal.kernel.service.LayoutSetLocalServiceUtil;
026    import com.liferay.portal.kernel.theme.ThemeDisplay;
027    import com.liferay.portal.kernel.util.DateUtil;
028    import com.liferay.portal.kernel.util.LocaleUtil;
029    import com.liferay.portal.kernel.util.PortalUtil;
030    import com.liferay.portal.kernel.util.StringPool;
031    import com.liferay.portal.kernel.util.StringUtil;
032    import com.liferay.portal.kernel.util.UnicodeProperties;
033    import com.liferay.portal.kernel.util.Validator;
034    import com.liferay.portal.kernel.xml.Document;
035    import com.liferay.portal.kernel.xml.Element;
036    import com.liferay.portal.kernel.xml.SAXReaderUtil;
037    import com.liferay.portal.util.PropsValues;
038    
039    import java.text.DateFormat;
040    
041    import java.util.Date;
042    import java.util.HashMap;
043    import java.util.List;
044    import java.util.Locale;
045    import java.util.Map;
046    
047    /**
048     * @author Jorge Ferrer
049     * @author Vilmos Papp
050     */
051    @DoPrivileged
052    public class SitemapImpl implements Sitemap {
053    
054            @Override
055            public void addURLElement(
056                    Element element, String url, UnicodeProperties typeSettingsProperties,
057                    Date modifiedDate, String canonicalURL,
058                    Map<Locale, String> alternateURLs) {
059    
060                    Element urlElement = element.addElement("url");
061    
062                    Element locElement = urlElement.addElement("loc");
063    
064                    locElement.addText(encodeXML(url));
065    
066                    if (typeSettingsProperties == null) {
067                            if (Validator.isNotNull(
068                                            PropsValues.SITES_SITEMAP_DEFAULT_CHANGE_FREQUENCY)) {
069    
070                                    Element changefreqElement = urlElement.addElement("changefreq");
071    
072                                    changefreqElement.addText(
073                                            PropsValues.SITES_SITEMAP_DEFAULT_CHANGE_FREQUENCY);
074                            }
075    
076                            if (Validator.isNotNull(
077                                            PropsValues.SITES_SITEMAP_DEFAULT_PRIORITY)) {
078    
079                                    Element priorityElement = urlElement.addElement("priority");
080    
081                                    priorityElement.addText(
082                                            PropsValues.SITES_SITEMAP_DEFAULT_PRIORITY);
083                            }
084                    }
085                    else {
086                            String changefreq = typeSettingsProperties.getProperty(
087                                    "sitemap-changefreq");
088    
089                            if (Validator.isNotNull(changefreq)) {
090                                    Element changefreqElement = urlElement.addElement("changefreq");
091    
092                                    changefreqElement.addText(changefreq);
093                            }
094                            else if (Validator.isNotNull(
095                                                    PropsValues.SITES_SITEMAP_DEFAULT_CHANGE_FREQUENCY)) {
096    
097                                    Element changefreqElement = urlElement.addElement("changefreq");
098    
099                                    changefreqElement.addText(
100                                            PropsValues.SITES_SITEMAP_DEFAULT_CHANGE_FREQUENCY);
101                            }
102    
103                            String priority = typeSettingsProperties.getProperty(
104                                    "sitemap-priority");
105    
106                            if (Validator.isNotNull(priority)) {
107                                    Element priorityElement = urlElement.addElement("priority");
108    
109                                    priorityElement.addText(priority);
110                            }
111                            else if (Validator.isNotNull(
112                                                    PropsValues.SITES_SITEMAP_DEFAULT_PRIORITY)) {
113    
114                                    Element priorityElement = urlElement.addElement("priority");
115    
116                                    priorityElement.addText(
117                                            PropsValues.SITES_SITEMAP_DEFAULT_PRIORITY);
118                            }
119                    }
120    
121                    if (modifiedDate != null) {
122                            Element modifiedDateElement = urlElement.addElement("lastmod");
123    
124                            DateFormat iso8601DateFormat = DateUtil.getISO8601Format();
125    
126                            modifiedDateElement.addText(iso8601DateFormat.format(modifiedDate));
127                    }
128    
129                    if (alternateURLs != null) {
130                            for (Map.Entry<Locale, String> entry : alternateURLs.entrySet()) {
131                                    Locale locale = entry.getKey();
132                                    String href = entry.getValue();
133    
134                                    Element alternateURLElement = urlElement.addElement(
135                                            "xhtml:link", "http://www.w3.org/1999/xhtml");
136    
137                                    alternateURLElement.addAttribute("href", href);
138                                    alternateURLElement.addAttribute(
139                                            "hreflang", LocaleUtil.toW3cLanguageId(locale));
140                                    alternateURLElement.addAttribute("rel", "alternate");
141                            }
142    
143                            Element alternateURLElement = urlElement.addElement(
144                                    "xhtml:link", "http://www.w3.org/1999/xhtml");
145    
146                            alternateURLElement.addAttribute("rel", "alternate");
147                            alternateURLElement.addAttribute("hreflang", "x-default");
148                            alternateURLElement.addAttribute("href", canonicalURL);
149                    }
150            }
151    
152            @Override
153            public String encodeXML(String input) {
154                    return StringUtil.replace(
155                            input, new char[] {'&', '<', '>', '\'', '\"'},
156                            new String[] {"&amp;", "&lt;", "&gt;", "&apos;", "&quot;"});
157            }
158    
159            @Override
160            public Map<Locale, String> getAlternateURLs(
161                            String canonicalURL, ThemeDisplay themeDisplay, Layout layout)
162                    throws PortalException {
163    
164                    Map<Locale, String> alternateURLs = new HashMap<>();
165    
166                    for (Locale availableLocale : LanguageUtil.getAvailableLocales(
167                                    layout.getGroupId())) {
168    
169                            String alternateURL = PortalUtil.getAlternateURL(
170                                    canonicalURL, themeDisplay, availableLocale, layout);
171    
172                            alternateURLs.put(availableLocale, alternateURL);
173                    }
174    
175                    return alternateURLs;
176            }
177    
178            @Override
179            public String getSitemap(
180                            long groupId, boolean privateLayout, ThemeDisplay themeDisplay)
181                    throws PortalException {
182    
183                    Document document = SAXReaderUtil.createDocument();
184    
185                    document.setXMLEncoding(StringPool.UTF8);
186    
187                    Element rootElement = document.addElement(
188                            "urlset", "http://www.sitemaps.org/schemas/sitemap/0.9");
189    
190                    rootElement.addAttribute("xmlns:xhtml", "http://www.w3.org/1999/xhtml");
191    
192                    LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
193                            groupId, privateLayout);
194    
195                    List<SitemapURLProvider> sitemapURLProviders =
196                            SitemapURLProviderRegistryUtil.getSitemapURLProviders();
197    
198                    for (SitemapURLProvider sitemapURLProvider : sitemapURLProviders) {
199                            sitemapURLProvider.visitLayoutSet(
200                                    rootElement, layoutSet, themeDisplay);
201                    }
202    
203                    return document.asXML();
204            }
205    
206    }