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.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          if (exporter == null) {
114            throw new IllegalArgumentException("No such exporter");
115          }
116          Writer writer = new StringWriter();
117          exporter.exportProfile(profile, writer);
118          return writer.toString();
119        }
120        return null;
121      }
122    
123      /**
124       * Important : the ruby controller has already create the profile
125       */
126      public ValidationMessages importProfile(String profileName, String language, String importerKey, String profileDefinition) {
127        ValidationMessages messages = ValidationMessages.create();
128        ProfileImporter importer = getProfileImporter(importerKey);
129        RulesProfile profile = importer.importProfile(new StringReader(profileDefinition), messages);
130        if (!messages.hasErrors()) {
131          DatabaseSession session = sessionFactory.getSession();
132          RulesProfile persistedProfile = session.getSingleResult(RulesProfile.class, "name", profileName, "language", language);
133          for (ActiveRule activeRule : profile.getActiveRules()) {
134            ActiveRule persistedActiveRule = persistedProfile.activateRule(activeRule.getRule(), activeRule.getSeverity());
135            for (ActiveRuleParam activeRuleParam : activeRule.getActiveRuleParams()) {
136              persistedActiveRule.setParameter(activeRuleParam.getKey(), activeRuleParam.getValue());
137            }
138          }
139          session.saveWithoutFlush(persistedProfile);
140          session.commit();
141        }
142        return messages;
143      }
144    
145      public ProfileExporter getProfileExporter(String exporterKey) {
146        for (ProfileExporter exporter : exporters) {
147          if (StringUtils.equals(exporterKey, exporter.getKey())) {
148            return exporter;
149          }
150        }
151        return null;
152      }
153    
154      public ProfileImporter getProfileImporter(String exporterKey) {
155        for (ProfileImporter importer : importers) {
156          if (StringUtils.equals(exporterKey, importer.getKey())) {
157            return importer;
158          }
159        }
160        return null;
161      }
162    }