/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.portal.upgrade.v6_2_0; import com.liferay.document.library.kernel.model.DLFileEntryTypeConstants; import com.liferay.document.library.kernel.model.DLFolderConstants; import com.liferay.document.library.kernel.store.DLStoreUtil; import com.liferay.portal.kernel.dao.jdbc.AutoBatchPreparedStatementUtil; import com.liferay.portal.kernel.exception.PortalException; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.model.TreeModel; import com.liferay.portal.kernel.security.auth.FullNameGenerator; import com.liferay.portal.kernel.security.auth.FullNameGeneratorFactory; import com.liferay.portal.kernel.tree.TreeModelTasksAdapter; import com.liferay.portal.kernel.tree.TreePathUtil; import com.liferay.portal.kernel.upgrade.UpgradeProcess; import com.liferay.portal.kernel.upgrade.util.UpgradeProcessUtil; import com.liferay.portal.kernel.util.GetterUtil; import com.liferay.portal.kernel.util.LocaleUtil; import com.liferay.portal.kernel.util.LocalizationUtil; import com.liferay.portal.kernel.util.LoggingTimer; import com.liferay.portal.kernel.util.StringPool; import com.liferay.portal.kernel.util.StringUtil; import com.liferay.portal.kernel.util.Validator; import com.liferay.portal.kernel.workflow.WorkflowConstants; import com.liferay.portal.upgrade.v6_2_0.util.DLFileEntryTypeTable; import com.liferay.portal.util.PortalInstances; import java.io.Serializable; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; /** * @author Dennis Ju * @author Mate Thurzo * @author Alexander Chow * @author Roberto Díaz */ public class UpgradeDocumentLibrary extends UpgradeProcess { protected void deleteChecksumDirectory() throws Exception { try (LoggingTimer loggingTimer = new LoggingTimer(); PreparedStatement ps = connection.prepareStatement( "select distinct companyId from DLFileEntry"); ResultSet rs = ps.executeQuery()) { while (rs.next()) { long companyId = rs.getLong("companyId"); DLStoreUtil.deleteDirectory(companyId, 0, "checksum"); } } } protected void deleteTempDirectory() { try (LoggingTimer loggingTimer = new LoggingTimer()) { DLStoreUtil.deleteDirectory(0, 0, "liferay_temp/"); } } @Override protected void doUpgrade() throws Exception { // DLFileEntryType alter( DLFileEntryTypeTable.class, new AlterTableAddColumn("fileEntryTypeKey STRING"), new AlterColumnType("name", "STRING null")); updateFileEntryTypes(); // Checksum directory deleteChecksumDirectory(); // Temp directory deleteTempDirectory(); // DLFolder updateDLFolderUserName(); // Tree path updateTreePath(); } protected String getUserName(long userId) throws Exception { try (PreparedStatement ps = connection.prepareStatement( "select firstName, middleName, lastName from User_ where " + "userId = ?")) { ps.setLong(1, userId); try (ResultSet rs = ps.executeQuery()) { if (rs.next()) { String firstName = rs.getString("firstName"); String middleName = rs.getString("middleName"); String lastName = rs.getString("lastName"); FullNameGenerator fullNameGenerator = FullNameGeneratorFactory.getInstance(); return fullNameGenerator.getFullName( firstName, middleName, lastName); } return StringPool.BLANK; } } } protected String localize(long companyId, String content, String key) throws Exception { String languageId = UpgradeProcessUtil.getDefaultLanguageId(companyId); Locale locale = LocaleUtil.fromLanguageId(languageId); Map<Locale, String> localizationMap = new HashMap<>(); localizationMap.put(locale, content); return LocalizationUtil.updateLocalization( localizationMap, StringPool.BLANK, key, languageId); } protected void rebuildTree( long companyId, PreparedStatement folderPreparedStatement, PreparedStatement fileEntryPreparedStatement, PreparedStatement fileShortcutPreparedStatement, PreparedStatement fileVersionPreparedStatement) throws PortalException { TreePathUtil.rebuildTree( companyId, DLFolderConstants.DEFAULT_PARENT_FOLDER_ID, StringPool.SLASH, new TreeModelTasksAdapter<DLFolderTreeModel>() { @Override public List<DLFolderTreeModel> findTreeModels( long previousId, long companyId, long parentPrimaryKey, int size) { List<DLFolderTreeModel> treeModels = new ArrayList<>(); try (PreparedStatement ps = connection.prepareStatement( _SELECT_DLFOLDER_BY_PARENT)) { ps.setLong(1, previousId); ps.setLong(2, companyId); ps.setLong(3, parentPrimaryKey); ps.setInt(4, WorkflowConstants.STATUS_IN_TRASH); ps.setFetchSize(size); try (ResultSet rs = ps.executeQuery()) { while (rs.next()) { long folderId = rs.getLong(1); DLFolderTreeModel treeModel = new DLFolderTreeModel( folderPreparedStatement); treeModel.setPrimaryKeyObj(folderId); treeModels.add(treeModel); } } } catch (SQLException sqle) { _log.error( "Unable to get folders with parent primary key " + parentPrimaryKey, sqle); } return treeModels; } @Override public void rebuildDependentModelsTreePaths( long parentPrimaryKey, String treePath) throws PortalException { try { fileEntryPreparedStatement.setString(1, treePath); fileEntryPreparedStatement.setLong(2, parentPrimaryKey); fileEntryPreparedStatement.addBatch(); } catch (SQLException sqle) { _log.error( "Unable to update file entries with tree path " + treePath, sqle); } try { fileShortcutPreparedStatement.setString(1, treePath); fileShortcutPreparedStatement.setLong( 2, parentPrimaryKey); fileShortcutPreparedStatement.addBatch(); } catch (SQLException sqle) { _log.error( "Unable to update file shortcuts with tree path " + treePath, sqle); } try { fileVersionPreparedStatement.setString(1, treePath); fileVersionPreparedStatement.setLong( 2, parentPrimaryKey); fileVersionPreparedStatement.addBatch(); } catch (SQLException sqle) { _log.error( "Unable to update file versions with tree path " + treePath, sqle); } } }); } protected void updateDLFolderUserName() throws Exception { try (LoggingTimer loggingTimer = new LoggingTimer(); PreparedStatement ps1 = connection.prepareStatement( "select distinct userId from DLFolder where userName is null " + "or userName = ''"); ResultSet rs = ps1.executeQuery(); PreparedStatement ps2 = AutoBatchPreparedStatementUtil.autoBatch( connection.prepareStatement( "update DLFolder set userName = ? where userId = ? and " + "(userName is null or userName = '')"))) { while (rs.next()) { long userId = rs.getLong("userId"); String userName = getUserName(userId); if (Validator.isNotNull(userName)) { ps2.setString(1, userName); ps2.setLong(2, userId); ps2.addBatch(); } else { if (_log.isInfoEnabled()) { _log.info("User " + userId + " does not exist"); } } } ps2.executeBatch(); } } protected void updateFileEntryType( long fileEntryTypeId, long companyId, String fileEntryTypeKey, String name, String description) throws Exception { try (PreparedStatement ps = connection.prepareStatement( "update DLFileEntryType set fileEntryTypeKey = ?, name = ?, " + "description = ? where fileEntryTypeId = ?")) { ps.setString(1, fileEntryTypeKey); ps.setString(2, localize(companyId, name, "Name")); ps.setString(3, localize(companyId, description, "Description")); ps.setLong(4, fileEntryTypeId); ps.executeUpdate(); } } protected void updateFileEntryTypes() throws Exception { try (LoggingTimer loggingTimer = new LoggingTimer(); PreparedStatement ps = connection.prepareStatement( "select fileEntryTypeId, companyId, name, description from " + "DLFileEntryType"); ResultSet rs = ps.executeQuery()) { while (rs.next()) { long fileEntryTypeId = rs.getLong("fileEntryTypeId"); long companyId = rs.getLong("companyId"); String name = GetterUtil.getString(rs.getString("name")); String description = rs.getString("description"); if (fileEntryTypeId == DLFileEntryTypeConstants. FILE_ENTRY_TYPE_ID_BASIC_DOCUMENT) { name = DLFileEntryTypeConstants.NAME_BASIC_DOCUMENT; } updateFileEntryType( fileEntryTypeId, companyId, StringUtil.toUpperCase(name), name, description); } } } protected void updateTreePath() { try (LoggingTimer loggingTimer = new LoggingTimer()) { long[] companyIds = PortalInstances.getCompanyIdsBySQL(); for (long companyId : companyIds) { try (PreparedStatement folderPreparedStatement = AutoBatchPreparedStatementUtil.concurrentAutoBatch( connection, "update DLFolder set treePath = ? where folderId " + "= ?"); PreparedStatement fileEntryPreparedStatement = AutoBatchPreparedStatementUtil.concurrentAutoBatch( connection, "update DLFileEntry set treePath = ? where " + "folderId = ?"); PreparedStatement fileShortcutPreparedStatement = AutoBatchPreparedStatementUtil.concurrentAutoBatch( connection, "update DLFileShortcut set treePath = ? where " + "folderId = ?"); PreparedStatement fileVersionPreparedStatement = AutoBatchPreparedStatementUtil.concurrentAutoBatch( connection, "update DLFileVersion set treePath = ? where " + "folderId = ?")) { try { rebuildTree( companyId, folderPreparedStatement, fileEntryPreparedStatement, fileShortcutPreparedStatement, fileVersionPreparedStatement); } catch (PortalException pe) { _log.error( "Unable to update tree paths for company " + companyId, pe); } folderPreparedStatement.executeBatch(); fileEntryPreparedStatement.executeBatch(); fileShortcutPreparedStatement.executeBatch(); fileVersionPreparedStatement.executeBatch(); } } } catch (SQLException sqle) { _log.error("Unable to update tree paths", sqle); } } private static final String _SELECT_DLFOLDER_BY_PARENT = "select folderId from DLFolder dlFolder where dlFolder.folderId > ? " + "and dlFolder.companyId = ? and dlFolder.parentFolderId = ? and " + "dlFolder.status != ?"; private static final Log _log = LogFactoryUtil.getLog( UpgradeDocumentLibrary.class); private class DLFolderTreeModel implements TreeModel { public DLFolderTreeModel(PreparedStatement ps) { _ps = ps; } @Override public String buildTreePath() throws PortalException { return null; } @Override public Serializable getPrimaryKeyObj() { return _folderId; } @Override public String getTreePath() { return null; } public void setPrimaryKeyObj(Serializable primaryKeyObj) { _folderId = (Long)primaryKeyObj; } @Override public void updateTreePath(String treePath) { try { _ps.setString(1, treePath); _ps.setLong(2, _folderId); _ps.addBatch(); } catch (SQLException sqle) { _log.error("Unable to update tree path: " + treePath, sqle); } } private long _folderId; private final PreparedStatement _ps; } }