/** * 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.verify; import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil; import com.liferay.portal.kernel.concurrent.ThrowableAwareRunnable; import com.liferay.portal.kernel.dao.jdbc.AutoBatchPreparedStatementUtil; import com.liferay.portal.kernel.dao.jdbc.DataAccess; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.util.LoggingTimer; import com.liferay.portal.kernel.util.StringBundler; import com.liferay.portal.kernel.util.StringPool; import com.liferay.portal.kernel.verify.model.VerifiableGroupedModel; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; /** * @author Shinn Lok */ public class VerifyGroupedModel extends VerifyProcess { public void verify(VerifiableGroupedModel... verifiableGroupedModels) throws Exception { List<String> unverifiedTableNames = new ArrayList<>(); for (VerifiableGroupedModel verifiableGroupedModel : verifiableGroupedModels) { unverifiedTableNames.add(verifiableGroupedModel.getTableName()); } List<VerifiableGroupedModelRunnable> verifiableGroupedModelRunnables = new ArrayList<>(unverifiedTableNames.size()); while (!unverifiedTableNames.isEmpty()) { int count = unverifiedTableNames.size(); for (VerifiableGroupedModel verifiableGroupedModel : verifiableGroupedModels) { if (unverifiedTableNames.contains( verifiableGroupedModel.getRelatedTableName()) || !unverifiedTableNames.contains( verifiableGroupedModel.getTableName())) { continue; } VerifiableGroupedModelRunnable verifyAuditedModelRunnable = new VerifiableGroupedModelRunnable(verifiableGroupedModel); verifiableGroupedModelRunnables.add(verifyAuditedModelRunnable); unverifiedTableNames.remove( verifiableGroupedModel.getTableName()); } if (unverifiedTableNames.size() == count) { throw new VerifyException( "Circular dependency detected " + unverifiedTableNames); } } doVerify(verifiableGroupedModelRunnables); } @Override protected void doVerify() throws Exception { Map<String, VerifiableGroupedModel> verifiableGroupedModelsMap = PortalBeanLocatorUtil.locate(VerifiableGroupedModel.class); Collection<VerifiableGroupedModel> verifiableGroupedModels = verifiableGroupedModelsMap.values(); verify( verifiableGroupedModels.toArray( new VerifiableGroupedModel[verifiableGroupedModels.size()])); } protected long getGroupId( Connection con, String tableName, String primaryKeColumnName, long primKey) throws Exception { try (PreparedStatement ps = con.prepareStatement( "select groupId from " + tableName + " where " + primaryKeColumnName + " = ?")) { ps.setLong(1, primKey); try (ResultSet rs = ps.executeQuery()) { if (rs.next()) { return rs.getLong("groupId"); } if (_log.isDebugEnabled()) { _log.debug("Unable to find " + tableName + " " + primKey); } return 0; } } } @Override protected boolean isForceConcurrent( Collection<? extends ThrowableAwareRunnable> throwableAwareRunnables) { return true; } protected void verifyGroupedModel( VerifiableGroupedModel verifiableGroupedModel) throws Exception { try (LoggingTimer loggingTimer = new LoggingTimer( verifiableGroupedModel.getTableName())) { StringBundler sb = new StringBundler(7); sb.append("select "); sb.append(verifiableGroupedModel.getPrimaryKeyColumnName()); sb.append(StringPool.COMMA_AND_SPACE); sb.append(verifiableGroupedModel.getRelatedPrimaryKeyColumnName()); sb.append(" from "); sb.append(verifiableGroupedModel.getTableName()); sb.append(" where groupId is null"); try (Connection con = DataAccess.getUpgradeOptimizedConnection(); PreparedStatement ps1 = con.prepareStatement(sb.toString()); ResultSet rs = ps1.executeQuery()) { sb = new StringBundler(5); sb.append("update "); sb.append(verifiableGroupedModel.getTableName()); sb.append(" set groupId = ? where "); sb.append(verifiableGroupedModel.getPrimaryKeyColumnName()); sb.append(" = ?"); try (PreparedStatement ps2 = AutoBatchPreparedStatementUtil.autoBatch( con.prepareStatement(sb.toString()))) { while (rs.next()) { long primKey = rs.getLong( verifiableGroupedModel.getPrimaryKeyColumnName()); long relatedPrimKey = rs.getLong( verifiableGroupedModel. getRelatedPrimaryKeyColumnName()); long groupId = getGroupId( con, verifiableGroupedModel.getRelatedTableName(), verifiableGroupedModel. getRelatedPrimaryKeyColumnName(), relatedPrimKey); if (groupId <= 0) { continue; } ps2.setLong(1, groupId); ps2.setLong(2, primKey); ps2.addBatch(); } ps2.executeBatch(); } } } } private static final Log _log = LogFactoryUtil.getLog( VerifyGroupedModel.class); private class VerifiableGroupedModelRunnable extends ThrowableAwareRunnable { public VerifiableGroupedModelRunnable( VerifiableGroupedModel verifiableGroupedModel) { _verifiableGroupedModel = verifiableGroupedModel; } @Override protected void doRun() throws Exception { verifyGroupedModel(_verifiableGroupedModel); } private final VerifiableGroupedModel _verifiableGroupedModel; } }