com.liferay.portal.verify.VerifyProcess.java Source code

Java tutorial

Introduction

Here is the source code for com.liferay.portal.verify.VerifyProcess.java

Source

/**
 * 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.petra.function.UnsafeConsumer;
import com.liferay.petra.string.StringBundler;
import com.liferay.portal.kernel.dao.db.BaseDBProcess;
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.model.ReleaseConstants;
import com.liferay.portal.kernel.util.ClassUtil;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.util.PropsValues;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * This abstract class should be extended for startup processes that verify the
 * integrity of the database. They can be added as part of
 * <code>VerifyProcessSuite</code> or be executed independently by being set in
 * the portal.properties file. Each of these processes should not cause any
 * problems if run multiple times.
 *
 * @author Alexander Chow
 * @author Hugo Huijser
 */
public abstract class VerifyProcess extends BaseDBProcess {

    public static final int ALWAYS = -1;

    public static final int NEVER = 0;

    public static final int ONCE = 1;

    public void verify() throws VerifyException {
        long start = System.currentTimeMillis();

        if (_log.isInfoEnabled()) {
            _log.info("Verifying " + ClassUtil.getClassName(this));
        }

        try (Connection con = DataAccess.getConnection()) {
            connection = con;

            doVerify();
        } catch (Exception e) {
            throw new VerifyException(e);
        } finally {
            connection = null;

            if (_log.isInfoEnabled()) {
                _log.info(StringBundler.concat("Completed verification process ", ClassUtil.getClassName(this),
                        " in ", System.currentTimeMillis() - start, " ms"));
            }
        }
    }

    public void verify(VerifyProcess verifyProcess) throws VerifyException {
        verifyProcess.verify();
    }

    protected void doVerify() throws Exception {
    }

    protected void doVerify(Collection<? extends Callable<Void>> callables) throws Exception {

        try {
            if ((callables.size() < PropsValues.VERIFY_PROCESS_CONCURRENCY_THRESHOLD)
                    && !isForceConcurrent(callables)) {

                UnsafeConsumer.accept(callables, Callable<Void>::call);
            } else {
                ExecutorService executorService = Executors.newFixedThreadPool(callables.size());

                List<Future<Void>> futures = executorService.invokeAll(callables);

                executorService.shutdown();

                UnsafeConsumer.accept(futures, Future::get);
            }
        } catch (Throwable throwable) {
            Class<?> clazz = getClass();

            throw new Exception("Verification error: " + clazz.getName(), throwable);
        }
    }

    /**
     * @return the portal build number before {@link
     *         com.liferay.portal.tools.DBUpgrader} has a chance to update it to
     *         the value in {@link
     *         com.liferay.portal.kernel.util.ReleaseInfo#getBuildNumber}
     */
    protected int getBuildNumber() throws Exception {
        try (PreparedStatement ps = connection
                .prepareStatement("select buildNumber from Release_ where servletContextName = " + "?")) {

            ps.setString(1, ReleaseConstants.DEFAULT_SERVLET_CONTEXT_NAME);

            try (ResultSet rs = ps.executeQuery()) {
                rs.next();

                return rs.getInt(1);
            }
        }
    }

    protected Set<String> getPortalTableNames() throws Exception {
        if (_portalTableNames != null) {
            return _portalTableNames;
        }

        Thread currentThread = Thread.currentThread();

        String sql = StringUtil.read(currentThread.getContextClassLoader(),
                "com/liferay/portal/tools/sql/dependencies/portal-tables.sql");

        Matcher matcher = _createTablePattern.matcher(sql);

        Set<String> tableNames = new HashSet<>();

        while (matcher.find()) {
            String match = matcher.group(1);

            tableNames.add(StringUtil.toLowerCase(match));
        }

        _portalTableNames = tableNames;

        return tableNames;
    }

    protected boolean isForceConcurrent(Collection<? extends Callable<Void>> callables) {

        return false;
    }

    protected boolean isPortalTableName(String tableName) throws Exception {
        Set<String> portalTableNames = getPortalTableNames();

        return portalTableNames.contains(StringUtil.toLowerCase(tableName));
    }

    private static final Log _log = LogFactoryUtil.getLog(VerifyProcess.class);

    private static final Pattern _createTablePattern = Pattern.compile("create table (\\S*) \\(");

    private Set<String> _portalTableNames;

}