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.rules;
021    
022    import org.apache.commons.lang.ArrayUtils;
023    import org.apache.commons.lang.StringUtils;
024    import org.sonar.api.ServerComponent;
025    import org.sonar.api.database.DatabaseSession;
026    import org.sonar.api.profiles.*;
027    import org.sonar.api.rules.ActiveRule;
028    import org.sonar.api.rules.ActiveRuleParam;
029    import org.sonar.api.utils.ValidationMessages;
030    import org.sonar.jpa.session.DatabaseSessionFactory;
031    
032    import java.io.StringReader;
033    import java.io.StringWriter;
034    import java.io.Writer;
035    import java.util.ArrayList;
036    import java.util.Arrays;
037    import java.util.List;
038    
039    public final class ProfilesConsole implements ServerComponent {
040    
041      private DatabaseSessionFactory sessionFactory;
042      private XMLProfileParser xmlProfileParser;
043      private XMLProfileSerializer xmlProfileSerializer;
044      private List<ProfileExporter> exporters = new ArrayList<ProfileExporter>();
045      private List<ProfileImporter> importers = new ArrayList<ProfileImporter>();
046    
047      public ProfilesConsole(DatabaseSessionFactory sessionFactory, XMLProfileParser xmlProfileParser, XMLProfileSerializer xmlProfileSerializer,
048                             ProfileExporter[] exporters,
049                             ProfileImporter[] importers) {
050        this.xmlProfileParser = xmlProfileParser;
051        this.xmlProfileSerializer = xmlProfileSerializer;
052        this.sessionFactory = sessionFactory;
053        this.exporters.addAll(Arrays.asList(exporters));
054        this.importers.addAll(Arrays.asList(importers));
055      }
056    
057      public String backupProfile(int profileId) {
058        DatabaseSession session = sessionFactory.getSession();
059        RulesProfile profile = loadProfile(session, profileId);
060        if (profile != null) {
061          Writer writer = new StringWriter();
062          xmlProfileSerializer.write(profile, writer);
063          return writer.toString();
064        }
065        return null;
066      }
067    
068      public ValidationMessages restoreProfile(String xmlBackup) {
069        ValidationMessages messages = ValidationMessages.create();
070        RulesProfile profile = xmlProfileParser.parse(new StringReader(xmlBackup), messages);
071        if (profile != null) {
072          DatabaseSession session = sessionFactory.getSession();
073          RulesProfile existingProfile = session.getSingleResult(RulesProfile.class, "name", profile.getName(), "language", profile.getLanguage());
074          if (existingProfile != null) {
075            messages.addErrorText("The profile " + profile + " already exists. Please delete it before restoring.");
076          } else if (!messages.hasErrors()) {
077            session.saveWithoutFlush(profile);
078            session.commit();
079          }
080        }
081        return messages;
082      }
083    
084      private RulesProfile loadProfile(DatabaseSession session, int profileId) {
085        return session.getSingleResult(RulesProfile.class, "id", profileId);
086      }
087    
088      public List<ProfileExporter> getProfileExportersForLanguage(String language) {
089        List<ProfileExporter> result = new ArrayList<ProfileExporter>();
090        for (ProfileExporter exporter : exporters) {
091          if (exporter.getSupportedLanguages() == null || exporter.getSupportedLanguages().length == 0 || ArrayUtils.contains(exporter.getSupportedLanguages(), language)) {
092            result.add(exporter);
093          }
094        }
095        return result;
096      }
097    
098      public List<ProfileImporter> getProfileImportersForLanguage(String language) {
099        List<ProfileImporter> result = new ArrayList<ProfileImporter>();
100        for (ProfileImporter importer : importers) {
101          if (importer.getSupportedLanguages() == null || importer.getSupportedLanguages().length == 0 || ArrayUtils.contains(importer.getSupportedLanguages(), language)) {
102            result.add(importer);
103          }
104        }
105        return result;
106      }
107    
108      public String exportProfile(int profileId, String exporterKey) {
109        DatabaseSession session = sessionFactory.getSession();
110        RulesProfile profile = loadProfile(session, profileId);
111        if (profile != null) {
112          ProfileExporter exporter = getProfileExporter(exporterKey);
113          Writer writer = new StringWriter();
114          exporter.exportProfile(profile, writer);
115          return writer.toString();
116        }
117        return null;
118      }
119    
120      /**
121       * Important : the ruby controller has already create the profile
122       */
123      public ValidationMessages importProfile(String profileName, String language, String importerKey, String profileDefinition) {
124        ValidationMessages messages = ValidationMessages.create();
125        ProfileImporter importer = getProfileImporter(importerKey);
126        RulesProfile profile = importer.importProfile(new StringReader(profileDefinition), messages);
127        if (!messages.hasErrors()) {
128          DatabaseSession session = sessionFactory.getSession();
129          RulesProfile persistedProfile = session.getSingleResult(RulesProfile.class, "name", profileName, "language", language);
130          for (ActiveRule activeRule : profile.getActiveRules()) {
131            ActiveRule persistedActiveRule = persistedProfile.activateRule(activeRule.getRule(), activeRule.getSeverity());
132            for (ActiveRuleParam activeRuleParam : activeRule.getActiveRuleParams()) {
133              persistedActiveRule.setParameter(activeRuleParam.getKey(), activeRuleParam.getValue());
134            }
135          }
136          session.saveWithoutFlush(persistedProfile);
137          session.commit();
138        }
139        return messages;
140      }
141    
142      public ProfileExporter getProfileExporter(String exporterKey) {
143        for (ProfileExporter exporter : exporters) {
144          if (StringUtils.equals(exporterKey, exporter.getKey())) {
145            return exporter;
146          }
147        }
148        return null;
149      }
150    
151      public ProfileImporter getProfileImporter(String exporterKey) {
152        for (ProfileImporter importer : importers) {
153          if (StringUtils.equals(exporterKey, importer.getKey())) {
154            return importer;
155          }
156        }
157        return null;
158      }
159    }