jorgediazest.indexchecker.portlet.IndexCheckerPortlet.java Source code

Java tutorial

Introduction

Here is the source code for jorgediazest.indexchecker.portlet.IndexCheckerPortlet.java

Source

/**
 * Copyright (c) 2015-present Jorge Daz 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 jorgediazest.indexchecker.portlet;

import com.liferay.portal.kernel.dao.orm.Conjunction;
import com.liferay.portal.kernel.dao.orm.Disjunction;
import com.liferay.portal.kernel.dao.orm.DynamicQuery;
import com.liferay.portal.kernel.dao.orm.QueryUtil;
import com.liferay.portal.kernel.dao.orm.RestrictionsFactoryUtil;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.ParamUtil;
import com.liferay.portal.kernel.util.PrefsPropsUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.model.Company;
import com.liferay.portal.kernel.model.Group;
import com.liferay.portal.kernel.model.User;
import com.liferay.portal.kernel.security.auth.CompanyThreadLocal;
import com.liferay.portal.kernel.service.ClassNameLocalServiceUtil;
import com.liferay.portal.kernel.service.CompanyLocalServiceUtil;
import com.liferay.portal.kernel.service.GroupLocalServiceUtil;
import com.liferay.portal.kernel.util.PortalUtil;
import com.liferay.document.library.kernel.model.DLFileEntry;
import com.liferay.portal.kernel.portlet.bridges.mvc.MVCPortlet;
import com.liferay.util.portlet.PortletProps;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;

import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;

import jorgediazest.indexchecker.ExecutionMode;
import jorgediazest.indexchecker.data.DataIndexCheckerModelComparator;
import jorgediazest.indexchecker.data.DataIndexCheckerResourceModelComparator;
import jorgediazest.indexchecker.index.IndexSearchUtil;
import jorgediazest.indexchecker.model.IndexCheckerModel;
import jorgediazest.indexchecker.model.IndexCheckerModelFactory;

import jorgediazest.util.data.Comparison;
import jorgediazest.util.data.ComparisonUtil;
import jorgediazest.util.data.Data;
import jorgediazest.util.data.DataComparator;
import jorgediazest.util.model.Model;
import jorgediazest.util.model.ModelFactory;
import jorgediazest.util.model.ModelFactory.DataComparatorFactory;
import jorgediazest.util.model.ModelUtil;

/**
 * Portlet implementation class IndexCheckerPortlet
 *
 * @author Jorge Daz
 */
public class IndexCheckerPortlet extends MVCPortlet {

    public static Map<Long, List<Comparison>> executeCheck(Company company, List<Long> groupIds,
            List<String> classNames, Set<ExecutionMode> executionMode, int threadsExecutor)
            throws ExecutionException, InterruptedException, SystemException {

        ModelFactory modelFactory = new IndexCheckerModelFactory();

        final String dateAttributes = PortletProps.get("data-comparator.date.attributes");
        final String dateAttributesUser = PortletProps.get("data-comparator.date.attributes.user");
        final String basicAttributes = PortletProps.get("data-comparator.basic.attributes");
        final String basicAttributesNoVersion = PortletProps.get("data-comparator.basic.attributes.noversion");
        final String categoriesTagsAttributes = PortletProps.get("data-comparator.categories-tags.attributes");
        final String assetEntryAttributes = PortletProps.get("data-comparator.assetentry.attributes");

        DataComparatorFactory dataComparatorFactory = new DataComparatorFactory() {

            protected boolean indexAllVersions = PrefsPropsUtil.getBoolean("journal.articles.index.all.versions");

            protected DataComparator defaultComparator = new DataIndexCheckerModelComparator((dateAttributes + ","
                    + basicAttributes + "," + assetEntryAttributes + "," + categoriesTagsAttributes).split(","));

            protected DataComparator userComparator = new DataIndexCheckerModelComparator(
                    (dateAttributesUser + "," + basicAttributes + "," + categoriesTagsAttributes).split(","));

            protected DataComparator dlFileEntryComparator = new DataIndexCheckerModelComparator(
                    (dateAttributes + "," + basicAttributesNoVersion + "," + assetEntryAttributes + ","
                            + categoriesTagsAttributes).split(","));

            protected DataComparator wikiPageComparator = new DataIndexCheckerResourceModelComparator(
                    (dateAttributes + "," + basicAttributesNoVersion + "," + assetEntryAttributes + ","
                            + categoriesTagsAttributes).split(","));

            protected DataComparator resourceComparator = new DataIndexCheckerResourceModelComparator(
                    (dateAttributes + "," + basicAttributes + "," + assetEntryAttributes + ","
                            + categoriesTagsAttributes).split(","));

            @Override
            public DataComparator getDataComparator(Model model) {
                if ("com.liferay.journal.model.JournalArticle".equals(model.getClassName()) && indexAllVersions) {

                    return defaultComparator;
                } else if (User.class.getName().equals(model.getClassName())) {
                    return userComparator;
                } else if (DLFileEntry.class.getName().equals(model.getClassName())) {

                    return dlFileEntryComparator;
                } else if ("com.liferay.wiki.model.WikiPage".equals(model.getClassName())) {

                    return wikiPageComparator;
                }

                if (model.isResourcedModel()) {
                    return resourceComparator;
                }

                return defaultComparator;
            }

        };

        modelFactory.setDataComparatorFactory(dataComparatorFactory);

        Map<String, Model> modelMap = modelFactory.getModelMap(classNames);

        IndexSearchUtil.autoAdjustIndexSearchLimit(modelMap.values());

        long companyId = company.getCompanyId();

        List<Long> groupIdsFor = new ArrayList<Long>();
        groupIdsFor.add(0L);

        if (executionMode.contains(ExecutionMode.GROUP_BY_SITE)) {
            groupIdsFor.addAll(groupIds);
        }

        ExecutorService executor = Executors.newFixedThreadPool(threadsExecutor);

        Map<Long, List<Future<Comparison>>> futureResultDataMap = new LinkedHashMap<Long, List<Future<Comparison>>>();

        for (long groupId : groupIdsFor) {
            List<Future<Comparison>> futureResultList = new ArrayList<Future<Comparison>>();

            for (Model model : modelMap.values()) {
                if (!model.hasIndexerEnabled()) {
                    continue;
                }

                CallableCheckGroupAndModel c = new CallableCheckGroupAndModel(companyId, groupId,
                        (IndexCheckerModel) model, executionMode);

                futureResultList.add(executor.submit(c));
            }

            futureResultDataMap.put(groupId, futureResultList);
        }

        Map<Long, List<Comparison>> resultDataMap = new LinkedHashMap<Long, List<Comparison>>();

        for (Entry<Long, List<Future<Comparison>>> entry : futureResultDataMap.entrySet()) {

            List<Comparison> resultList = new ArrayList<Comparison>();

            for (Future<Comparison> f : entry.getValue()) {
                Comparison results = f.get();

                if (results != null) {
                    resultList.add(results);
                }
            }

            resultDataMap.put(entry.getKey(), resultList);
        }

        executor.shutdownNow();

        return resultDataMap;
    }

    public static EnumSet<ExecutionMode> getExecutionMode(ActionRequest request) {

        EnumSet<ExecutionMode> executionMode = EnumSet.noneOf(ExecutionMode.class);

        if (ParamUtil.getBoolean(request, "outputGroupBySite")) {
            executionMode.add(ExecutionMode.GROUP_BY_SITE);
        }

        if (ParamUtil.getBoolean(request, "outputBothExact")) {
            executionMode.add(ExecutionMode.SHOW_BOTH_EXACT);
        }

        if (ParamUtil.getBoolean(request, "outputBothNotExact")) {
            executionMode.add(ExecutionMode.SHOW_BOTH_NOTEXACT);
        }

        if (ParamUtil.getBoolean(request, "outputLiferay")) {
            executionMode.add(ExecutionMode.SHOW_LIFERAY);
        }

        if (ParamUtil.getBoolean(request, "outputIndex")) {
            executionMode.add(ExecutionMode.SHOW_INDEX);
        }

        if (ParamUtil.getBoolean(request, "dumpAllObjectsToLog")) {
            executionMode.add(ExecutionMode.DUMP_ALL_OBJECTS_TO_LOG);
        }

        return executionMode;
    }

    public static Log getLogger() {
        return _log;
    }

    public static Map<Data, String> reindex(Comparison comparison) {

        Set<Data> objectsToReindex = new HashSet<Data>();

        for (String type : comparison.getOutputTypes()) {
            if (!type.endsWith("-right")) {
                Set<Data> aux = comparison.getData(type);

                if (aux != null) {
                    objectsToReindex.addAll(aux);
                }
            }
        }

        IndexCheckerModel model = (IndexCheckerModel) comparison.getModel();

        return model.reindex(objectsToReindex);
    }

    public static Map<Data, String> removeIndexOrphans(Comparison comparison) {
        Set<Data> indexOnlyData = comparison.getData("only-right");

        if ((indexOnlyData == null) || indexOnlyData.isEmpty()) {
            return null;
        }

        IndexCheckerModel model = (IndexCheckerModel) comparison.getModel();

        return model.deleteAndCheck(indexOnlyData);
    }

    public void doView(RenderRequest renderRequest, RenderResponse renderResponse)
            throws IOException, PortletException {

        String filterGroupId = ParamUtil.getString(renderRequest, "filterGroupId");

        if (Validator.isNull(filterGroupId)) {
            List<Long> siteGroupIds = this.getSiteGroupIds();

            filterGroupId = "";

            for (Long groupId : siteGroupIds) {
                if (Validator.isNotNull(filterGroupId)) {
                    filterGroupId += ",";
                }

                filterGroupId += groupId;
            }
        }

        renderRequest.setAttribute("filterGroupId", filterGroupId);

        int numberOfThreads = getNumberOfThreads(renderRequest);
        renderRequest.setAttribute("numberOfThreads", numberOfThreads);

        super.doView(renderRequest, renderResponse);
    }

    public void executeCheck(ActionRequest request, ActionResponse response) throws Exception {

        PortalUtil.copyRequestParameters(request, response);

        EnumSet<ExecutionMode> executionMode = getExecutionMode(request);

        String[] filterClassNameArr = null;
        String filterClassName = ParamUtil.getString(request, "filterClassName");

        if (Validator.isNotNull(filterClassName)) {
            filterClassNameArr = filterClassName.split(",");
        }

        String[] filterGroupIdArr = null;
        String filterGroupId = ParamUtil.getString(request, "filterGroupId");

        if (Validator.isNotNull(filterGroupId)) {
            filterGroupIdArr = filterGroupId.split(",");
        }

        List<Company> companies = CompanyLocalServiceUtil.getCompanies();

        Map<Company, Map<Long, List<Comparison>>> companyResultDataMap = new HashMap<Company, Map<Long, List<Comparison>>>();

        Map<Company, Long> companyProcessTime = new HashMap<Company, Long>();

        Map<Company, String> companyError = new HashMap<Company, String>();

        for (Company company : companies) {
            try {
                CompanyThreadLocal.setCompanyId(company.getCompanyId());

                List<String> classNames = getClassNames(filterClassNameArr);

                List<Long> groupIds = getGroupIds(company, filterGroupIdArr);

                long startTime = System.currentTimeMillis();

                Map<Long, List<Comparison>> resultDataMap = IndexCheckerPortlet.executeCheck(company, groupIds,
                        classNames, executionMode, getNumberOfThreads(request));

                long endTime = System.currentTimeMillis();

                if (_log.isInfoEnabled() && executionMode.contains(ExecutionMode.DUMP_ALL_OBJECTS_TO_LOG)) {

                    _log.info("COMPANY: " + company);

                    boolean groupBySite = executionMode.contains(ExecutionMode.GROUP_BY_SITE);

                    ComparisonUtil.dumpToLog(groupBySite, resultDataMap);
                }

                companyResultDataMap.put(company, resultDataMap);

                companyProcessTime.put(company, (endTime - startTime));
            } catch (Throwable t) {
                StringWriter swt = new StringWriter();
                PrintWriter pwt = new PrintWriter(swt);
                pwt.println("Error during execution: " + t.getMessage());
                t.printStackTrace(pwt);
                companyError.put(company, swt.toString());
                _log.error(t, t);
            }
        }

        request.setAttribute("title", "Check Index");
        request.setAttribute("executionMode", executionMode);
        request.setAttribute("companyProcessTime", companyProcessTime);
        request.setAttribute("companyResultDataMap", companyResultDataMap);
        request.setAttribute("companyError", companyError);
    }

    public void executeReindex(ActionRequest request, ActionResponse response) throws Exception {

        PortalUtil.copyRequestParameters(request, response);

        EnumSet<ExecutionMode> executionMode = getExecutionMode(request);

        String[] filterClassNameArr = null;
        String filterClassName = ParamUtil.getString(request, "filterClassName");

        if (Validator.isNotNull(filterClassName)) {
            filterClassNameArr = filterClassName.split(",");
        }

        String[] filterGroupIdArr = null;
        String filterGroupId = ParamUtil.getString(request, "filterGroupId");

        if (Validator.isNotNull(filterGroupId)) {
            filterGroupIdArr = filterGroupId.split(",");
        }

        List<Company> companies = CompanyLocalServiceUtil.getCompanies();

        Map<Company, Long> companyProcessTime = new HashMap<Company, Long>();

        Map<Company, String> companyError = new HashMap<Company, String>();

        for (Company company : companies) {
            StringWriter sw = new StringWriter();

            PrintWriter pw = new PrintWriter(sw);

            try {
                List<String> classNames = getClassNames(filterClassNameArr);

                List<Long> groupIds = getGroupIds(company, filterGroupIdArr);

                long startTime = System.currentTimeMillis();

                Map<Long, List<Comparison>> resultDataMap = IndexCheckerPortlet.executeCheck(company, groupIds,
                        classNames, executionMode, getNumberOfThreads(request));

                for (Entry<Long, List<Comparison>> entry : resultDataMap.entrySet()) {

                    List<Comparison> resultList = entry.getValue();

                    for (Comparison result : resultList) {
                        Map<Data, String> errors = reindex(result);
                        /* TODO Mover todo esto al JSP */
                        if (((errors != null) && (errors.size() > 0)) || (result.getError() != null)) {

                            pw.println();
                            pw.println("----");
                            pw.println(result.getModel().getName());
                            pw.println("----");

                            for (Entry<Data, String> e : errors.entrySet()) {
                                pw.println(" * " + e.getKey() + " - Exception: " + e.getValue());
                            }

                            pw.println(" * " + result.getError());
                        }
                    }
                }

                long endTime = System.currentTimeMillis();

                companyProcessTime.put(company, endTime - startTime);
            } catch (Throwable t) {
                StringWriter swt = new StringWriter();
                PrintWriter pwt = new PrintWriter(swt);
                pwt.println("Error during execution: " + t.getMessage());
                t.printStackTrace(pwt);
                companyError.put(company, swt.toString());
                _log.error(t, t);
            }

            companyError.put(company, sw.toString());
        }

        request.setAttribute("title", "Reindex");
        request.setAttribute("executionMode", executionMode);
        request.setAttribute("companyProcessTime", companyProcessTime);
        request.setAttribute("companyError", companyError);
    }

    public void executeRemoveOrphans(ActionRequest request, ActionResponse response) throws Exception {

        PortalUtil.copyRequestParameters(request, response);

        EnumSet<ExecutionMode> executionMode = getExecutionMode(request);

        String[] filterClassNameArr = null;
        String filterClassName = ParamUtil.getString(request, "filterClassName");

        if (Validator.isNotNull(filterClassName)) {
            filterClassNameArr = filterClassName.split(",");
        }

        String[] filterGroupIdArr = null;
        String filterGroupId = ParamUtil.getString(request, "filterGroupId");

        if (Validator.isNotNull(filterGroupId)) {
            filterGroupIdArr = filterGroupId.split(",");
        }

        List<Company> companies = CompanyLocalServiceUtil.getCompanies();

        Map<Company, Long> companyProcessTime = new HashMap<Company, Long>();

        Map<Company, String> companyError = new HashMap<Company, String>();

        for (Company company : companies) {
            StringWriter sw = new StringWriter();

            PrintWriter pw = new PrintWriter(sw);

            try {
                List<String> classNames = getClassNames(filterClassNameArr);

                List<Long> groupIds = getGroupIds(company, filterGroupIdArr);

                long startTime = System.currentTimeMillis();

                Map<Long, List<Comparison>> resultDataMap = IndexCheckerPortlet.executeCheck(company, groupIds,
                        classNames, executionMode, getNumberOfThreads(request));

                for (Entry<Long, List<Comparison>> entry : resultDataMap.entrySet()) {

                    List<Comparison> resultList = entry.getValue();

                    for (Comparison result : resultList) {
                        Map<Data, String> errors = removeIndexOrphans(result);
                        /* TODO Mover todo esto al JSP */
                        if (((errors != null) && (errors.size() > 0)) || (result.getError() != null)) {

                            pw.println();
                            pw.println("----");
                            pw.println(result.getModel().getName());
                            pw.println("----");

                            for (Entry<Data, String> e : errors.entrySet()) {
                                pw.println(" * " + e.getKey() + " - Exception: " + e.getValue());
                            }

                            pw.println(" * " + result.getError());
                        }
                    }
                }

                long endTime = System.currentTimeMillis();

                companyProcessTime.put(company, endTime - startTime);
            } catch (Throwable t) {
                StringWriter swt = new StringWriter();
                PrintWriter pwt = new PrintWriter(swt);
                pwt.println("Error during execution: " + t.getMessage());
                t.printStackTrace(pwt);
                companyError.put(company, swt.toString());
                _log.error(t, t);
            }

            companyError.put(company, sw.toString());
        }

        request.setAttribute("title", "Remove index orphan");
        request.setAttribute("executionMode", executionMode);
        request.setAttribute("companyProcessTime", companyProcessTime);
        request.setAttribute("companyError", companyError);
    }

    public List<String> getClassNames() throws SystemException {
        return getClassNames(null);
    }

    public List<String> getClassNames(String[] filterClassNameArr) throws SystemException {

        List<String> allClassName = ModelUtil
                .getClassNameValues(ClassNameLocalServiceUtil.getClassNames(QueryUtil.ALL_POS, QueryUtil.ALL_POS));

        List<String> classNames = new ArrayList<String>();

        for (String className : allClassName) {
            if (ignoreClassName(className)) {
                continue;
            }

            if (filterClassNameArr == null) {
                classNames.add(className);
                continue;
            }

            for (String filterClassName : filterClassNameArr) {
                if (className.contains(filterClassName)) {
                    classNames.add(className);
                    break;
                }
            }
        }

        return classNames;
    }

    public List<Long> getGroupIds(Company company, String[] filterGroupIdArr) throws SystemException {

        List<Group> groups = GroupLocalServiceUtil.getCompanyGroups(company.getCompanyId(), QueryUtil.ALL_POS,
                QueryUtil.ALL_POS);

        List<Long> groupIds = new ArrayList<Long>();

        for (Group group : groups) {
            if (filterGroupIdArr == null) {
                groupIds.add(group.getGroupId());
                continue;
            }

            String groupIdStr = "" + group.getGroupId();

            for (int i = 0; i < filterGroupIdArr.length; i++) {
                if (groupIdStr.equals(filterGroupIdArr[i])) {
                    groupIds.add(group.getGroupId());
                    break;
                }
            }
        }

        return groupIds;
    }

    public int getNumberOfThreads(ActionRequest actionRequest) {
        int def = GetterUtil.getInteger(PortletProps.get("number.threads"), 1);

        int num = ParamUtil.getInteger(actionRequest, "numberOfThreads", def);

        return (num == 0) ? def : num;
    }

    public int getNumberOfThreads(RenderRequest renderRequest) {
        int def = GetterUtil.getInteger(PortletProps.get("number.threads"), 1);

        int num = ParamUtil.getInteger(renderRequest, "numberOfThreads", def);

        return (num == 0) ? def : num;
    }

    @SuppressWarnings("unchecked")
    public List<Long> getSiteGroupIds() {

        long companyClassNameId = PortalUtil.getClassNameId(Company.class);

        ModelFactory modelFactory = new IndexCheckerModelFactory();

        Model model = modelFactory.getModelObject(Group.class);

        if (model == null) {
            return new ArrayList<Long>();
        }

        DynamicQuery groupDynamicQuery = model.getService().newDynamicQuery();

        Conjunction stagingSites = RestrictionsFactoryUtil.conjunction();
        stagingSites.add(model.getProperty("site").eq(false));
        stagingSites.add(model.getProperty("liveGroupId").ne(0L));

        Conjunction normalSites = RestrictionsFactoryUtil.conjunction();
        normalSites.add(model.getProperty("site").eq(true));
        normalSites.add(model.getProperty("classNameId").ne(companyClassNameId));

        Disjunction disjunction = RestrictionsFactoryUtil.disjunction();
        disjunction.add(stagingSites);
        disjunction.add(normalSites);

        groupDynamicQuery.add(disjunction);
        groupDynamicQuery.setProjection(model.getPropertyProjection("groupId"));

        try {
            return (List<Long>) model.getService().executeDynamicQuery(groupDynamicQuery);
        } catch (Exception e) {
            if (_log.isWarnEnabled()) {
                _log.warn(e, e);
            }

            return new ArrayList<Long>();
        }
    }

    public boolean ignoreClassName(String className) {
        if (Validator.isNull(className)) {
            return true;
        }

        for (String ignoreClassName : ignoreClassNames) {
            if (ignoreClassName.equals(className)) {
                return true;
            }
        }

        return false;
    }

    public void init() throws PortletException {
        super.init();

        try {
            ModelFactory modelFactory = new IndexCheckerModelFactory();

            Map<String, Model> modelMap = modelFactory.getModelMap(getClassNames());

            IndexSearchUtil.autoAdjustIndexSearchLimit(modelMap.values());
        } catch (Exception e) {
            _log.error(e, e);
        }
    }

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

    private static String[] ignoreClassNames = new String[] {
            "com.liferay.portal.kernel.repository.model.FileEntry",
            "com.liferay.portal.kernel.repository.model.Folder", "com.liferay.portal.model.UserPersonalSite" };

}