001
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.security.pacl.DoPrivileged;
021 import com.liferay.portal.kernel.util.DateUtil;
022 import com.liferay.portal.kernel.util.GetterUtil;
023 import com.liferay.portal.kernel.util.LocaleUtil;
024 import com.liferay.portal.kernel.util.StringBundler;
025 import com.liferay.portal.kernel.util.StringPool;
026 import com.liferay.portal.kernel.util.StringUtil;
027 import com.liferay.portal.kernel.util.UnicodeProperties;
028 import com.liferay.portal.kernel.util.Validator;
029 import com.liferay.portal.kernel.workflow.WorkflowConstants;
030 import com.liferay.portal.kernel.xml.Document;
031 import com.liferay.portal.kernel.xml.Element;
032 import com.liferay.portal.kernel.xml.SAXReaderUtil;
033 import com.liferay.portal.model.Layout;
034 import com.liferay.portal.model.LayoutConstants;
035 import com.liferay.portal.service.GroupLocalServiceUtil;
036 import com.liferay.portal.service.LayoutLocalServiceUtil;
037 import com.liferay.portal.theme.ThemeDisplay;
038 import com.liferay.portal.util.PortalUtil;
039 import com.liferay.portal.util.PropsValues;
040 import com.liferay.portlet.journal.model.JournalArticle;
041 import com.liferay.portlet.journal.model.JournalArticleConstants;
042 import com.liferay.portlet.journal.service.JournalArticleServiceUtil;
043
044 import java.text.DateFormat;
045
046 import java.util.Date;
047 import java.util.HashSet;
048 import java.util.List;
049 import java.util.Locale;
050 import java.util.Set;
051
052
056 @DoPrivileged
057 public class SitemapImpl implements Sitemap {
058
059 @Override
060 public String encodeXML(String input) {
061 return StringUtil.replace(
062 input,
063 new String[] {"&", "<", ">", "'", "\""},
064 new String[] {"&", "<", ">", "'", """});
065 }
066
067 @Override
068 public String getSitemap(
069 long groupId, boolean privateLayout, ThemeDisplay themeDisplay)
070 throws PortalException, SystemException {
071
072 Document document = SAXReaderUtil.createDocument();
073
074 document.setXMLEncoding(StringPool.UTF8);
075
076 Element rootElement = document.addElement(
077 "urlset", "http:
078
079 List<Layout> layouts = LayoutLocalServiceUtil.getLayouts(
080 groupId, privateLayout, LayoutConstants.DEFAULT_PARENT_LAYOUT_ID);
081
082 visitLayouts(rootElement, layouts, themeDisplay);
083
084 return document.asXML();
085 }
086
087 protected void addURLElement(
088 Element element, String url, UnicodeProperties typeSettingsProperties,
089 Date modifiedDate) {
090
091 Element urlElement = element.addElement("url");
092
093 Element locElement = urlElement.addElement("loc");
094
095 locElement.addText(encodeXML(url));
096
097 if (typeSettingsProperties == null) {
098 if (Validator.isNotNull(
099 PropsValues.SITES_SITEMAP_DEFAULT_CHANGE_FREQUENCY)) {
100
101 Element changefreqElement = urlElement.addElement("changefreq");
102
103 changefreqElement.addText(
104 PropsValues.SITES_SITEMAP_DEFAULT_CHANGE_FREQUENCY);
105 }
106
107 if (Validator.isNotNull(
108 PropsValues.SITES_SITEMAP_DEFAULT_PRIORITY)) {
109
110 Element priorityElement = urlElement.addElement("priority");
111
112 priorityElement.addText(
113 PropsValues.SITES_SITEMAP_DEFAULT_PRIORITY);
114 }
115 }
116 else {
117 String changefreq = typeSettingsProperties.getProperty(
118 "sitemap-changefreq");
119
120 if (Validator.isNotNull(changefreq)) {
121 Element changefreqElement = urlElement.addElement("changefreq");
122
123 changefreqElement.addText(changefreq);
124 }
125 else if (Validator.isNotNull(
126 PropsValues.SITES_SITEMAP_DEFAULT_CHANGE_FREQUENCY)) {
127
128 Element changefreqElement = urlElement.addElement("changefreq");
129
130 changefreqElement.addText(
131 PropsValues.SITES_SITEMAP_DEFAULT_CHANGE_FREQUENCY);
132 }
133
134 String priority = typeSettingsProperties.getProperty(
135 "sitemap-priority");
136
137 if (Validator.isNotNull(priority)) {
138 Element priorityElement = urlElement.addElement("priority");
139
140 priorityElement.addText(priority);
141 }
142 else if (Validator.isNotNull(
143 PropsValues.SITES_SITEMAP_DEFAULT_PRIORITY)) {
144
145 Element priorityElement = urlElement.addElement("priority");
146
147 priorityElement.addText(
148 PropsValues.SITES_SITEMAP_DEFAULT_PRIORITY);
149 }
150 }
151
152 if (modifiedDate != null) {
153 Element modifiedDateElement = urlElement.addElement("lastmod");
154
155 DateFormat iso8601DateFormat = DateUtil.getISO8601Format();
156
157 modifiedDateElement.addText(iso8601DateFormat.format(modifiedDate));
158 }
159 }
160
161 protected void visitArticles(
162 Element element, Layout layout, ThemeDisplay themeDisplay)
163 throws PortalException, SystemException {
164
165 List<JournalArticle> journalArticles =
166 JournalArticleServiceUtil.getArticlesByLayoutUuid(
167 layout.getGroupId(), layout.getUuid());
168
169 if (journalArticles.isEmpty()) {
170 return;
171 }
172
173 Set<String> processedArticleIds = new HashSet<String>();
174
175 for (JournalArticle journalArticle : journalArticles) {
176 if (processedArticleIds.contains(
177 journalArticle.getArticleId()) ||
178 (journalArticle.getStatus() !=
179 WorkflowConstants.STATUS_APPROVED)) {
180
181 continue;
182 }
183
184 String portalURL = PortalUtil.getPortalURL(layout, themeDisplay);
185
186 String groupFriendlyURL = PortalUtil.getGroupFriendlyURL(
187 GroupLocalServiceUtil.getGroup(journalArticle.getGroupId()),
188 false, themeDisplay);
189
190 StringBundler sb = new StringBundler(4);
191
192 if (!groupFriendlyURL.startsWith(portalURL)) {
193 sb.append(portalURL);
194 }
195
196 sb.append(groupFriendlyURL);
197 sb.append(JournalArticleConstants.CANONICAL_URL_SEPARATOR);
198 sb.append(journalArticle.getUrlTitle());
199
200 String articleURL = PortalUtil.getCanonicalURL(
201 sb.toString(), themeDisplay, layout);
202
203 addURLElement(
204 element, articleURL, null, journalArticle.getModifiedDate());
205
206 Locale[] availableLocales = LanguageUtil.getAvailableLocales();
207
208 if (availableLocales.length > 1) {
209 Locale defaultLocale = LocaleUtil.getDefault();
210
211 for (Locale availableLocale : availableLocales) {
212 if (!availableLocale.equals(defaultLocale)) {
213 String alternateURL = PortalUtil.getAlternateURL(
214 articleURL, themeDisplay, availableLocale);
215
216 addURLElement(
217 element, alternateURL, null,
218 journalArticle.getModifiedDate());
219 }
220 }
221 }
222
223 processedArticleIds.add(journalArticle.getArticleId());
224 }
225 }
226
227 protected void visitLayout(
228 Element element, Layout layout, ThemeDisplay themeDisplay)
229 throws PortalException, SystemException {
230
231 UnicodeProperties typeSettingsProperties =
232 layout.getTypeSettingsProperties();
233
234 if (layout.isHidden() || !PortalUtil.isLayoutSitemapable(layout) ||
235 !GetterUtil.getBoolean(
236 typeSettingsProperties.getProperty("sitemap-include"), true)) {
237
238 return;
239 }
240
241 String layoutFullURL = PortalUtil.getLayoutFullURL(
242 layout, themeDisplay);
243
244 layoutFullURL = PortalUtil.getCanonicalURL(
245 layoutFullURL, themeDisplay, layout);
246
247 addURLElement(
248 element, layoutFullURL, typeSettingsProperties,
249 layout.getModifiedDate());
250
251 Locale[] availableLocales = LanguageUtil.getAvailableLocales();
252
253 if (availableLocales.length > 1) {
254 Locale defaultLocale = LocaleUtil.getDefault();
255
256 for (Locale availableLocale : availableLocales) {
257 if (availableLocale.equals(defaultLocale)) {
258 continue;
259 }
260
261 String alternateURL = PortalUtil.getAlternateURL(
262 layoutFullURL, themeDisplay, availableLocale);
263
264 addURLElement(
265 element, alternateURL, typeSettingsProperties,
266 layout.getModifiedDate());
267 }
268 }
269
270 visitArticles(element, layout, themeDisplay);
271 visitLayouts(element, layout.getChildren(), themeDisplay);
272 }
273
274 protected void visitLayouts(
275 Element element, List<Layout> layouts, ThemeDisplay themeDisplay)
276 throws PortalException, SystemException {
277
278 for (Layout layout : layouts) {
279 visitLayout(element, layout, themeDisplay);
280 }
281 }
282
283 }