001
014
015 package com.liferay.portal.verify;
016
017 import com.liferay.portal.kernel.dao.db.DB;
018 import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
019 import com.liferay.portal.kernel.dao.jdbc.DataAccess;
020 import com.liferay.portal.kernel.dao.orm.ActionableDynamicQuery;
021 import com.liferay.portal.kernel.exception.PortalException;
022 import com.liferay.portal.kernel.exception.SystemException;
023 import com.liferay.portal.kernel.log.Log;
024 import com.liferay.portal.kernel.log.LogFactoryUtil;
025 import com.liferay.portal.kernel.util.FriendlyURLNormalizerUtil;
026 import com.liferay.portal.kernel.util.GetterUtil;
027 import com.liferay.portal.kernel.util.HtmlUtil;
028 import com.liferay.portal.kernel.util.StringPool;
029 import com.liferay.portal.kernel.util.Validator;
030 import com.liferay.portal.kernel.workflow.WorkflowConstants;
031 import com.liferay.portal.service.ResourceLocalServiceUtil;
032 import com.liferay.portal.util.PortalInstances;
033 import com.liferay.portlet.PortletPreferencesFactoryUtil;
034 import com.liferay.portlet.asset.model.AssetEntry;
035 import com.liferay.portlet.asset.service.AssetEntryLocalServiceUtil;
036 import com.liferay.portlet.dynamicdatamapping.NoSuchStructureException;
037 import com.liferay.portlet.journal.model.JournalArticle;
038 import com.liferay.portlet.journal.model.JournalArticleConstants;
039 import com.liferay.portlet.journal.model.JournalContentSearch;
040 import com.liferay.portlet.journal.model.JournalFolder;
041 import com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil;
042 import com.liferay.portlet.journal.service.JournalContentSearchLocalServiceUtil;
043 import com.liferay.portlet.journal.service.JournalFolderLocalServiceUtil;
044 import com.liferay.portlet.journal.service.persistence.JournalArticleActionableDynamicQuery;
045
046 import java.sql.Connection;
047 import java.sql.PreparedStatement;
048 import java.sql.ResultSet;
049
050 import java.util.List;
051 import java.util.regex.Pattern;
052
053 import javax.portlet.PortletPreferences;
054
055
059 public class VerifyJournal extends VerifyProcess {
060
061 public static final long DEFAULT_GROUP_ID = 14;
062
063 public static final int NUM_OF_ARTICLES = 5;
064
065 @Override
066 protected void doVerify() throws Exception {
067 updateFolderAssets();
068 verifyOracleNewLine();
069 verifyPermissionsAndAssets();
070 verifySearch();
071 verifyTree();
072 verifyURLTitle();
073 }
074
075 protected void updateFolderAssets() throws Exception {
076 List<JournalFolder> folders =
077 JournalFolderLocalServiceUtil.getNoAssetFolders();
078
079 if (_log.isDebugEnabled()) {
080 _log.debug(
081 "Processing " + folders.size() + " folders with no asset");
082 }
083
084 for (JournalFolder folder : folders) {
085 try {
086 JournalFolderLocalServiceUtil.updateAsset(
087 folder.getUserId(), folder, null, null, null);
088 }
089 catch (Exception e) {
090 if (_log.isWarnEnabled()) {
091 _log.warn(
092 "Unable to update asset for folder " +
093 folder.getFolderId() + ": " + e.getMessage());
094 }
095 }
096 }
097
098 if (_log.isDebugEnabled()) {
099 _log.debug("Assets verified for folders");
100 }
101 }
102
103 protected void updateURLTitle(
104 long groupId, String articleId, String urlTitle)
105 throws Exception {
106
107 String normalizedURLTitle = FriendlyURLNormalizerUtil.normalize(
108 urlTitle, _friendlyURLPattern);
109
110 if (urlTitle.equals(normalizedURLTitle)) {
111 return;
112 }
113
114 normalizedURLTitle = JournalArticleLocalServiceUtil.getUniqueUrlTitle(
115 groupId, articleId, normalizedURLTitle);
116
117 Connection con = null;
118 PreparedStatement ps = null;
119
120 try {
121 con = DataAccess.getUpgradeOptimizedConnection();
122
123 ps = con.prepareStatement(
124 "update JournalArticle set urlTitle = ? where urlTitle = ?");
125
126 ps.setString(1, normalizedURLTitle);
127 ps.setString(2, urlTitle);
128
129 ps.executeUpdate();
130 }
131 finally {
132 DataAccess.cleanUp(con, ps);
133 }
134 }
135
136 protected void verifyContentSearch(long groupId, String portletId)
137 throws Exception {
138
139 Connection con = null;
140 PreparedStatement ps = null;
141 ResultSet rs = null;
142
143 try {
144 con = DataAccess.getUpgradeOptimizedConnection();
145
146 ps = con.prepareStatement(
147 "select preferences from PortletPreferences inner join " +
148 "Layout on PortletPreferences.plid = Layout.plid where " +
149 "groupId = ? and portletId = ?");
150
151 ps.setLong(1, groupId);
152 ps.setString(2, portletId);
153
154 rs = ps.executeQuery();
155
156 while (rs.next()) {
157 String xml = rs.getString("preferences");
158
159 PortletPreferences portletPreferences =
160 PortletPreferencesFactoryUtil.fromDefaultXML(xml);
161
162 String articleId = portletPreferences.getValue(
163 "articleId", null);
164
165 List<JournalContentSearch> contentSearches =
166 JournalContentSearchLocalServiceUtil.
167 getArticleContentSearches(groupId, articleId);
168
169 if (contentSearches.isEmpty()) {
170 continue;
171 }
172
173 JournalContentSearch contentSearch = contentSearches.get(0);
174
175 JournalContentSearchLocalServiceUtil.updateContentSearch(
176 contentSearch.getGroupId(), contentSearch.isPrivateLayout(),
177 contentSearch.getLayoutId(), contentSearch.getPortletId(),
178 articleId, true);
179 }
180 }
181 finally {
182 DataAccess.cleanUp(con, ps, rs);
183 }
184 }
185
186 protected void verifyOracleNewLine() throws Exception {
187 DB db = DBFactoryUtil.getDB();
188
189 String dbType = db.getType();
190
191 if (!dbType.equals(DB.TYPE_ORACLE)) {
192 return;
193 }
194
195
196
197
198
199
200
201 boolean checkNewLine = false;
202
203 List<JournalArticle> articles =
204 JournalArticleLocalServiceUtil.getArticles(
205 DEFAULT_GROUP_ID, 0, NUM_OF_ARTICLES);
206
207 for (JournalArticle article : articles) {
208 String content = article.getContent();
209
210 if ((content != null) && content.contains("\\n")) {
211 articles = JournalArticleLocalServiceUtil.getArticles(
212 DEFAULT_GROUP_ID);
213
214 for (int j = 0; j < articles.size(); j++) {
215 article = articles.get(j);
216
217 JournalArticleLocalServiceUtil.checkNewLine(
218 article.getGroupId(), article.getArticleId(),
219 article.getVersion());
220 }
221
222 checkNewLine = true;
223
224 break;
225 }
226 }
227
228
229
230 if (!checkNewLine) {
231 if (_log.isInfoEnabled()) {
232 _log.info("Do not fix oracle new line");
233 }
234
235 return;
236 }
237 else {
238 if (_log.isInfoEnabled()) {
239 _log.info("Fix oracle new line");
240 }
241 }
242 }
243
244 protected void verifyPermissionsAndAssets() throws Exception {
245 ActionableDynamicQuery actionableDynamicQuery =
246 new JournalArticleActionableDynamicQuery() {
247
248 @Override
249 protected void performAction(Object object)
250 throws PortalException, SystemException {
251
252 JournalArticle article = (JournalArticle)object;
253
254 long groupId = article.getGroupId();
255 String articleId = article.getArticleId();
256 double version = article.getVersion();
257 String structureId = article.getStructureId();
258
259 if (article.getResourcePrimKey() <= 0) {
260 article =
261 JournalArticleLocalServiceUtil.
262 checkArticleResourcePrimKey(
263 groupId, articleId, version);
264 }
265
266 ResourceLocalServiceUtil.addResources(
267 article.getCompanyId(), 0, 0,
268 JournalArticle.class.getName(),
269 article.getResourcePrimKey(), false, false, false);
270
271 AssetEntry assetEntry = AssetEntryLocalServiceUtil.fetchEntry(
272 JournalArticle.class.getName(),
273 article.getResourcePrimKey());
274
275 if (assetEntry == null) {
276 try {
277 JournalArticleLocalServiceUtil.updateAsset(
278 article.getUserId(), article, null, null, null);
279 }
280 catch (Exception e) {
281 if (_log.isWarnEnabled()) {
282 _log.warn(
283 "Unable to update asset for article " +
284 article.getId() + ": " + e.getMessage());
285 }
286 }
287 }
288 else if ((article.getStatus() ==
289 WorkflowConstants.STATUS_DRAFT) &&
290 (article.getVersion() ==
291 JournalArticleConstants.VERSION_DEFAULT)) {
292
293 AssetEntryLocalServiceUtil.updateEntry(
294 assetEntry.getClassName(), assetEntry.getClassPK(),
295 null, assetEntry.isVisible());
296 }
297
298 String content = GetterUtil.getString(article.getContent());
299
300 String newContent = HtmlUtil.replaceMsWordCharacters(content);
301
302 if (Validator.isNotNull(structureId)) {
303
309 }
310
311 if (!content.equals(newContent)) {
312 JournalArticleLocalServiceUtil.updateContent(
313 groupId, articleId, version, newContent);
314 }
315
316 try {
317 JournalArticleLocalServiceUtil.checkStructure(
318 groupId, articleId, version);
319 }
320 catch (NoSuchStructureException nsse) {
321 if (_log.isWarnEnabled()) {
322 _log.warn(
323 "Removing reference to missing structure for " +
324 "article " + article.getId());
325 }
326
327 article.setStructureId(StringPool.BLANK);
328 article.setTemplateId(StringPool.BLANK);
329
330 JournalArticleLocalServiceUtil.updateJournalArticle(
331 article);
332 }
333 }
334
335 };
336
337 actionableDynamicQuery.performActions();
338
339 if (_log.isDebugEnabled()) {
340 _log.debug("Permissions and assets verified for articles");
341 }
342 }
343
344 protected void verifySearch() throws Exception {
345 Connection con = null;
346 PreparedStatement ps = null;
347 ResultSet rs = null;
348
349 try {
350 con = DataAccess.getUpgradeOptimizedConnection();
351
352 ps = con.prepareStatement(
353 "select groupId, portletId from JournalContentSearch group " +
354 "by groupId, portletId having count(groupId) > 1 and " +
355 "count(portletId) > 1");
356
357 rs = ps.executeQuery();
358
359 while (rs.next()) {
360 long groupId = rs.getLong("groupId");
361 String portletId = rs.getString("portletId");
362
363 verifyContentSearch(groupId, portletId);
364 }
365 }
366 finally {
367 DataAccess.cleanUp(con, ps, rs);
368 }
369 }
370
371 protected void verifyTree() throws Exception {
372 long[] companyIds = PortalInstances.getCompanyIdsBySQL();
373
374 for (long companyId : companyIds) {
375 JournalArticleLocalServiceUtil.rebuildTree(companyId);
376 JournalFolderLocalServiceUtil.rebuildTree(companyId);
377 }
378 }
379
380 protected void verifyURLTitle() throws Exception {
381 Connection con = null;
382 PreparedStatement ps = null;
383 ResultSet rs = null;
384
385 try {
386 con = DataAccess.getUpgradeOptimizedConnection();
387
388 ps = con.prepareStatement(
389 "select distinct groupId, articleId, urlTitle from " +
390 "JournalArticle");
391
392 rs = ps.executeQuery();
393
394 while (rs.next()) {
395 long groupId = rs.getLong("groupId");
396 String articleId = rs.getString("articleId");
397 String urlTitle = rs.getString("urlTitle");
398
399 updateURLTitle(groupId, articleId, urlTitle);
400 }
401 }
402 finally {
403 DataAccess.cleanUp(con, ps, rs);
404 }
405 }
406
407 private static Log _log = LogFactoryUtil.getLog(VerifyJournal.class);
408
409 private static Pattern _friendlyURLPattern = Pattern.compile("[^a-z0-9_-]");
410
411 }