001 /*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2008-2011 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 org.apache.commons.lang.StringUtils;
024 import org.slf4j.Logger;
025 import org.slf4j.LoggerFactory;
026 import org.sonar.api.database.DatabaseSession;
027 import org.sonar.api.profiles.ProfileDefinition;
028 import org.sonar.api.profiles.RulesProfile;
029 import org.sonar.api.rules.*;
030 import org.sonar.api.utils.TimeProfiler;
031 import org.sonar.api.utils.ValidationMessages;
032 import org.sonar.jpa.session.DatabaseSessionFactory;
033
034 import java.util.ArrayList;
035 import java.util.Arrays;
036 import java.util.List;
037
038 public final class RegisterProvidedProfiles {
039
040 private static final Logger LOGGER = LoggerFactory.getLogger(RegisterProvidedProfiles.class);
041
042 private DatabaseSessionFactory sessionFactory;
043 private List<ProfileDefinition> definitions = Lists.newArrayList();
044 private RuleFinder ruleFinder;
045
046 public RegisterProvidedProfiles(RuleFinder ruleFinder, DatabaseSessionFactory sessionFactory,// NOSONAR the parameter registerRulesBefore is unused must be declared for execution order of tasks
047 RegisterRules registerRulesBefore,
048 ProfileDefinition[] definitions) {
049 this.ruleFinder = ruleFinder;
050 this.sessionFactory = sessionFactory;
051 this.definitions.addAll(Arrays.asList(definitions));
052 }
053
054 public RegisterProvidedProfiles(RuleFinder ruleFinder, DatabaseSessionFactory sessionFactory,// NOSONAR the parameter registerRulesBefore is unused must be declared for execution order of tasks
055 RegisterRules registerRulesBefore) {
056 this.ruleFinder = ruleFinder;
057 this.sessionFactory = sessionFactory;
058 }
059
060 public void start() {
061 TimeProfiler profiler = new TimeProfiler().start("Load provided profiles");
062
063 List<RulesProfile> profiles = createProfiles();
064 DatabaseSession session = sessionFactory.getSession();
065 cleanProvidedProfiles(profiles, session);
066 saveProvidedProfiles(profiles, session);
067 session.commit();
068 profiler.stop();
069 }
070
071 List<RulesProfile> createProfiles() {
072 List<RulesProfile> result = Lists.newArrayList();
073 for (ProfileDefinition definition : definitions) {
074 ValidationMessages validation = ValidationMessages.create();
075 RulesProfile profile = definition.createProfile(validation);
076 validation.log(LOGGER);
077 if (profile != null && !validation.hasErrors()) {
078 result.add(profile);
079 }
080 }
081 return result;
082 }
083
084 void cleanProvidedProfiles(List<RulesProfile> profiles, DatabaseSession session) {
085 TimeProfiler profiler = new TimeProfiler().start("Clean provided profiles");
086 List<RulesProfile> existingProfiles = session.getResults(RulesProfile.class, "provided", true);
087 for (RulesProfile existingProfile : existingProfiles) {
088 boolean isDeprecated = true;
089 for (RulesProfile profile : profiles) {
090 if (StringUtils.equals(existingProfile.getName(), profile.getName()) && StringUtils.equals(existingProfile.getLanguage(), profile.getLanguage())) {
091 isDeprecated = false;
092 break;
093 }
094 }
095 if (isDeprecated) {
096 session.removeWithoutFlush(existingProfile);
097 } else {
098 for (ActiveRule activeRule : existingProfile.getActiveRules()) {
099 session.removeWithoutFlush(activeRule);
100 }
101 existingProfile.setActiveRules(new ArrayList<ActiveRule>());
102 session.saveWithoutFlush(existingProfile);
103 }
104 }
105 profiler.stop();
106 }
107
108 void saveProvidedProfiles(List<RulesProfile> profiles, DatabaseSession session) {
109 for (RulesProfile profile : profiles) {
110 TimeProfiler profiler = new TimeProfiler().start("Save profile " + profile);
111 RulesProfile persistedProfile = findOrCreate(profile.getName(), profile.getLanguage(), session);
112
113 for (ActiveRule activeRule : profile.getActiveRules()) {
114 Rule rule = getPersistedRule(activeRule);
115 ActiveRule persistedRule = persistedProfile.activateRule(rule, activeRule.getSeverity());
116 for (RuleParam param : rule.getParams()) {
117 String value = StringUtils.defaultString(activeRule.getParameter(param.getKey()), param.getDefaultValue());
118 if (value != null) {
119 persistedRule.setParameter(param.getKey(), value);
120 }
121 }
122 }
123
124 session.saveWithoutFlush(persistedProfile);
125 profiler.stop();
126 }
127
128 }
129
130 Rule getPersistedRule(ActiveRule activeRule) {
131 Rule rule = activeRule.getRule();
132 if (rule != null && rule.getId() == null) {
133 if (rule.getKey() != null) {
134 rule = ruleFinder.findByKey(rule.getRepositoryKey(), rule.getKey());
135
136 } else if (rule.getConfigKey() != null) {
137 rule = ruleFinder.find(RuleQuery.create().withRepositoryKey(rule.getRepositoryKey()).withConfigKey(rule.getConfigKey()));
138 }
139 }
140 return rule;
141 }
142
143 private RulesProfile findOrCreate(String name, String language, DatabaseSession session) {
144 RulesProfile profile = session.getSingleResult(RulesProfile.class, "name", name, "language", language);
145 if (profile == null) {
146 profile = RulesProfile.create(name, language);
147 profile.setProvided(true);
148 profile.setDefaultProfile(false);
149 }
150 return profile;
151 }
152
153 }