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