001 /* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2008-2012 SonarSource 004 * mailto:contact AT sonarsource DOT com 005 * 006 * Sonar is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * Sonar is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with Sonar; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 019 */ 020 package org.sonar.server.startup; 021 022 import com.google.common.collect.Lists; 023 import com.google.common.collect.Maps; 024 import org.apache.commons.lang.StringUtils; 025 import org.sonar.api.database.DatabaseSession; 026 import org.sonar.api.rules.ActiveRuleParam; 027 import org.sonar.api.rules.Rule; 028 import org.sonar.api.rules.RuleParam; 029 import org.sonar.api.rules.RuleRepository; 030 import org.sonar.api.utils.Logs; 031 import org.sonar.api.utils.TimeProfiler; 032 import org.sonar.jpa.session.DatabaseSessionFactory; 033 034 import java.util.*; 035 036 public final class RegisterRules { 037 038 private DatabaseSessionFactory sessionFactory; 039 private List<RuleRepository> repositories = Lists.newArrayList(); 040 041 public RegisterRules(DatabaseSessionFactory sessionFactory, RuleRepository[] repos) { 042 this.sessionFactory = sessionFactory; 043 this.repositories.addAll(Arrays.asList(repos)); 044 } 045 046 public RegisterRules(DatabaseSessionFactory sessionFactory) { 047 this(sessionFactory, new RuleRepository[0]); 048 } 049 050 public void start() { 051 TimeProfiler profiler = new TimeProfiler(); 052 053 DatabaseSession session = sessionFactory.getSession(); 054 disableAllRules(session); 055 for (RuleRepository repository : repositories) { 056 profiler.start("Register rules [" + repository.getKey() + "/" + StringUtils.defaultString(repository.getLanguage(), "-") + "]"); 057 registerRepository(repository, session); 058 profiler.stop(); 059 } 060 061 profiler.start("Disable deprecated user rules"); 062 disableDeprecatedUserRules(session); 063 profiler.stop(); 064 065 session.commit(); 066 } 067 068 private void disableDeprecatedUserRules(DatabaseSession session) { 069 List<Integer> deprecatedUserRuleIds = Lists.newLinkedList(); 070 deprecatedUserRuleIds.addAll(session.createQuery( 071 "SELECT r.id FROM " + Rule.class.getSimpleName() + 072 " r WHERE r.parent IS NOT NULL AND NOT EXISTS(FROM " + Rule.class.getSimpleName() + " p WHERE r.parent=p)").getResultList()); 073 074 deprecatedUserRuleIds.addAll(session.createQuery( 075 "SELECT r.id FROM " + Rule.class.getSimpleName() + 076 " r WHERE r.parent IS NOT NULL AND EXISTS(FROM " + Rule.class.getSimpleName() + " p WHERE r.parent=p and p.enabled=false)").getResultList()); 077 078 for (Integer deprecatedUserRuleId : deprecatedUserRuleIds) { 079 Rule rule = session.getSingleResult(Rule.class, "id", deprecatedUserRuleId); 080 rule.setEnabled(false); 081 session.saveWithoutFlush(rule); 082 } 083 084 } 085 086 private void disableAllRules(DatabaseSession session) { 087 // the hardcoded repository "manual" is used for manual violations 088 session.createQuery("UPDATE " + Rule.class.getSimpleName() + " SET enabled=false WHERE parent IS NULL AND pluginName<>'manual'").executeUpdate(); 089 } 090 091 private void registerRepository(RuleRepository repository, DatabaseSession session) { 092 Map<String, Rule> rulesByKey = Maps.newHashMap(); 093 for (Rule rule : repository.createRules()) { 094 rule.setRepositoryKey(repository.getKey()); 095 rulesByKey.put(rule.getKey(), rule); 096 } 097 Logs.INFO.info(rulesByKey.size() + " rules"); 098 099 List<Rule> persistedRules = session.getResults(Rule.class, "pluginName", repository.getKey()); 100 for (Rule persistedRule : persistedRules) { 101 Rule rule = rulesByKey.get(persistedRule.getKey()); 102 if (rule != null) { 103 updateRule(persistedRule, rule, session); 104 rulesByKey.remove(rule.getKey()); 105 } 106 } 107 108 saveNewRules(rulesByKey.values(), session); 109 } 110 111 private void updateRule(Rule persistedRule, Rule rule, DatabaseSession session) { 112 persistedRule.setName(rule.getName()); 113 persistedRule.setConfigKey(rule.getConfigKey()); 114 persistedRule.setDescription(rule.getDescription()); 115 persistedRule.setSeverity(rule.getSeverity()); 116 persistedRule.setEnabled(true); 117 persistedRule.setCardinality(rule.getCardinality()); 118 119 // delete deprecated params 120 deleteDeprecatedParameters(persistedRule, rule, session); 121 122 // add new params and update existing params 123 updateParameters(persistedRule, rule); 124 125 session.saveWithoutFlush(persistedRule); 126 } 127 128 private void updateParameters(Rule persistedRule, Rule rule) { 129 if (rule.getParams() != null) { 130 for (RuleParam param : rule.getParams()) { 131 RuleParam persistedParam = persistedRule.getParam(param.getKey()); 132 if (persistedParam == null) { 133 persistedParam = persistedRule.createParameter(param.getKey()); 134 } 135 persistedParam.setDescription(param.getDescription()); 136 persistedParam.setType(param.getType()); 137 persistedParam.setDefaultValue(param.getDefaultValue()); 138 } 139 } 140 } 141 142 private void deleteDeprecatedParameters(Rule persistedRule, Rule rule, DatabaseSession session) { 143 if (persistedRule.getParams() != null && persistedRule.getParams().size() > 0) { 144 for (Iterator<RuleParam> it = persistedRule.getParams().iterator(); it.hasNext(); ) { 145 RuleParam persistedParam = it.next(); 146 if (rule.getParam(persistedParam.getKey()) == null) { 147 it.remove(); 148 session 149 .createQuery("delete from " + ActiveRuleParam.class.getSimpleName() + " where ruleParam=:param") 150 .setParameter("param", persistedParam) 151 .executeUpdate(); 152 } 153 } 154 } 155 } 156 157 private void saveNewRules(Collection<Rule> rules, DatabaseSession session) { 158 for (Rule rule : rules) { 159 rule.setEnabled(true); 160 session.saveWithoutFlush(rule); 161 } 162 } 163 }