org.sonar.server.qualityprofile.ESActiveRule.java Source code

Java tutorial

Introduction

Here is the source code for org.sonar.server.qualityprofile.ESActiveRule.java

Source

/*
 * SonarQube, open source software quality management tool.
 * Copyright (C) 2008-2014 SonarSource
 * mailto:contact AT sonarsource DOT com
 *
 * SonarQube 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 3 of the License, or (at your option) any later version.
 *
 * SonarQube 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.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package org.sonar.server.qualityprofile;

import com.google.common.base.Function;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import org.apache.ibatis.session.SqlSession;
import org.elasticsearch.common.io.BytesStream;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.FilterBuilders;
import org.elasticsearch.index.query.QueryBuilders;
import org.sonar.api.utils.TimeProfiler;
import org.sonar.core.persistence.MyBatis;
import org.sonar.core.profiling.Profiling;
import org.sonar.core.profiling.Profiling.Level;
import org.sonar.core.profiling.StopWatch;
import org.sonar.core.qualityprofile.db.ActiveRuleDao;
import org.sonar.core.qualityprofile.db.ActiveRuleDto;
import org.sonar.core.qualityprofile.db.ActiveRuleParamDto;
import org.sonar.server.es.ESIndex;
import org.sonar.server.es.SearchQuery;
import org.sonar.server.rule.RuleDocument;
import org.sonar.server.rule.RuleRegistry;

import java.io.IOException;
import java.util.Collection;
import java.util.List;

import static com.google.common.collect.Lists.newArrayList;

public class ESActiveRule {

    public static final String TYPE_ACTIVE_RULE = "active_rule";
    private final ESIndex esIndex;
    private final ActiveRuleDao activeRuleDao;
    private final MyBatis myBatis;
    private final Profiling profiling;

    public ESActiveRule(ESIndex esIndex, ActiveRuleDao activeRuleDao, MyBatis myBatis, Profiling profiling) {
        this.esIndex = esIndex;
        this.activeRuleDao = activeRuleDao;
        this.myBatis = myBatis;
        this.profiling = profiling;
    }

    public void start() {
        esIndex.addMappingFromClasspath(RuleRegistry.INDEX_RULES, TYPE_ACTIVE_RULE,
                "/org/sonar/server/es/config/mappings/active_rule_mapping.json");
    }

    public void bulkRegisterActiveRules() {
        SqlSession session = myBatis.openSession();
        try {

            StopWatch bulkWatch = startWatch();
            List<ActiveRuleDto> activeRules = activeRuleDao.selectAll(session);
            List<ActiveRuleParamDto> activeRuleParams = activeRuleDao.selectAllParams(session);
            bulkWatch.stop(String.format("Loaded %d active rules from DB", activeRules.size()));

            Multimap<Integer, ActiveRuleParamDto> paramsByActiveRule = ArrayListMultimap.create();
            for (ActiveRuleParamDto param : activeRuleParams) {
                paramsByActiveRule.put(param.getActiveRuleId(), param);
            }

            String[] ids = bulkIndexActiveRules(activeRules, paramsByActiveRule);
            removeDeletedActiveRules(ids);
        } finally {
            MyBatis.closeQuietly(session);
        }
    }

    public void bulkIndexProfile(int profileId) {
        SqlSession session = myBatis.openSession();
        try {
            bulkIndexProfile(profileId, session);
        } finally {
            MyBatis.closeQuietly(session);
        }
    }

    public void bulkIndexProfile(int profileId, SqlSession session) {
        bulkIndexActiveRules(activeRuleDao.selectByProfileId(profileId, session), session);
    }

    public void bulkIndexActiveRuleIds(List<Integer> activeRulesIds, SqlSession session) {
        bulkIndexActiveRules(activeRuleDao.selectByIds(activeRulesIds, session), session);
    }

    public void bulkIndexActiveRules(List<Integer> ids) {
        SqlSession session = myBatis.openSession();
        try {
            bulkIndexActiveRuleIds(ids, session);
        } finally {
            MyBatis.closeQuietly(session);
        }
    }

    public void deleteActiveRulesFromProfile(int profileId) {
        esIndex.client().prepareDeleteByQuery(RuleRegistry.INDEX_RULES).setTypes(ESActiveRule.TYPE_ACTIVE_RULE)
                .setQuery(QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(),
                        FilterBuilders.termFilter(ActiveRuleDocument.FIELD_PROFILE_ID, profileId)))
                .execute().actionGet();
    }

    public String[] bulkIndexActiveRules(List<ActiveRuleDto> activeRules,
            Multimap<Integer, ActiveRuleParamDto> paramsByActiveRule) {
        StopWatch bulkWatch = startWatch();
        try {
            int size = activeRules.size();
            String[] ids = new String[size];
            BytesStream[] docs = new BytesStream[size];
            String[] parentIds = new String[size];
            int index = 0;

            for (ActiveRuleDto activeRule : activeRules) {
                ids[index] = activeRule.getId().toString();
                docs[index] = activeRuleDocument(activeRule, paramsByActiveRule.get(activeRule.getId()));
                parentIds[index] = activeRule.getRulId().toString();
                index++;
            }

            if (!activeRules.isEmpty()) {
                esIndex.bulkIndex(RuleRegistry.INDEX_RULES, ESActiveRule.TYPE_ACTIVE_RULE, ids, docs, parentIds);
            }
            bulkWatch.stop(String.format("Indexed %d active rules", size));
            return ids;
        } catch (IOException e) {
            bulkWatch.stop("Failed to indes active rules");
            throw new IllegalStateException("Unable to index active rules", e);
        }
    }

    public void save(ActiveRuleDto activeRule, Collection<ActiveRuleParamDto> params) {
        try {
            esIndex.putSynchronous(RuleRegistry.INDEX_RULES, ESActiveRule.TYPE_ACTIVE_RULE,
                    Long.toString(activeRule.getId()), activeRuleDocument(activeRule, params),
                    Long.toString(activeRule.getRulId()));
        } catch (IOException ioexception) {
            throw new IllegalStateException("Unable to index active rule with id=" + activeRule.getId(),
                    ioexception);
        }
    }

    public void deleteActiveRules(List<Integer> activeRuleIds) {
        List<String> indexIds = newArrayList();
        for (Integer ruleId : activeRuleIds) {
            indexIds.add(ruleId.toString());
        }
        bulkDeleteActiveRules(indexIds);
    }

    private void bulkDeleteActiveRules(List<String> indexIds) {
        if (!indexIds.isEmpty()) {
            esIndex.bulkDelete(RuleRegistry.INDEX_RULES, ESActiveRule.TYPE_ACTIVE_RULE,
                    indexIds.toArray(new String[0]));
        }
    }

    private void bulkIndexActiveRules(List<ActiveRuleDto> activeRules, SqlSession session) {
        Multimap<Integer, ActiveRuleParamDto> paramsByActiveRule = ArrayListMultimap.create();
        List<Integer> activeRulesIdList = newArrayList(
                Iterables.transform(activeRules, new Function<ActiveRuleDto, Integer>() {
                    @Override
                    public Integer apply(ActiveRuleDto input) {
                        return input.getId();
                    }
                }));
        for (ActiveRuleParamDto param : activeRuleDao.selectParamsByActiveRuleIds(activeRulesIdList, session)) {
            paramsByActiveRule.put(param.getActiveRuleId(), param);
        }
        bulkIndexActiveRules(activeRules, paramsByActiveRule);
    }

    private void removeDeletedActiveRules(String[] ids) {
        TimeProfiler profiler = new TimeProfiler();
        List<String> indexIds = esIndex.findDocumentIds(
                SearchQuery.create().index(RuleRegistry.INDEX_RULES).type(ESActiveRule.TYPE_ACTIVE_RULE));
        indexIds.removeAll(newArrayList(ids));
        profiler.start("Remove deleted active rule documents");
        bulkDeleteActiveRules(indexIds);
        profiler.stop();
    }

    private XContentBuilder activeRuleDocument(ActiveRuleDto activeRule, Collection<ActiveRuleParamDto> params)
            throws IOException {
        XContentBuilder document = XContentFactory.jsonBuilder().startObject()
                .field(ActiveRuleDocument.FIELD_ID, activeRule.getId())
                .field(ActiveRuleDocument.FIELD_ACTIVE_RULE_PARENT_ID, activeRule.getParentId())
                .field(ActiveRuleDocument.FIELD_SEVERITY, activeRule.getSeverityString())
                .field(ActiveRuleDocument.FIELD_PROFILE_ID, activeRule.getProfileId())
                .field(ActiveRuleDocument.FIELD_INHERITANCE, activeRule.getInheritance());
        if (activeRule.getNoteData() != null || activeRule.getNoteUserLogin() != null) {
            document.startObject(RuleDocument.FIELD_NOTE)
                    .field(ActiveRuleDocument.FIELD_NOTE_DATA, activeRule.getNoteData())
                    .field(ActiveRuleDocument.FIELD_NOTE_USER_LOGIN, activeRule.getNoteUserLogin())
                    .field(ActiveRuleDocument.FIELD_NOTE_CREATED_AT, activeRule.getNoteCreatedAt())
                    .field(ActiveRuleDocument.FIELD_NOTE_UPDATED_AT, activeRule.getNoteUpdatedAt()).endObject();
        }
        if (!params.isEmpty()) {
            document.startArray(ActiveRuleDocument.FIELD_PARAMS);
            for (ActiveRuleParamDto param : params) {
                document.startObject().field(ActiveRuleDocument.FIELD_PARAM_KEY, param.getKey())
                        .field(ActiveRuleDocument.FIELD_PARAM_VALUE, param.getValue()).endObject();
            }
            document.endArray();
        }
        document.endObject();
        return document;
    }

    private StopWatch startWatch() {
        return profiling.start("qprofile", Level.BASIC);
    }
}