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 */
020package org.sonar.server.ui;
021
022import com.google.common.collect.ListMultimap;
023import com.google.common.collect.Lists;
024import org.slf4j.LoggerFactory;
025import org.sonar.api.CoreProperties;
026import org.sonar.api.config.License;
027import org.sonar.api.config.PropertyDefinitions;
028import org.sonar.api.config.Settings;
029import org.sonar.api.platform.ComponentContainer;
030import org.sonar.api.platform.PluginMetadata;
031import org.sonar.api.platform.PluginRepository;
032import org.sonar.api.profiles.ProfileExporter;
033import org.sonar.api.profiles.ProfileImporter;
034import org.sonar.api.resources.Language;
035import org.sonar.api.resources.ResourceType;
036import org.sonar.api.resources.ResourceTypes;
037import org.sonar.api.rules.RulePriority;
038import org.sonar.api.rules.RuleRepository;
039import org.sonar.api.utils.ValidationMessages;
040import org.sonar.api.web.*;
041import org.sonar.api.workflow.Review;
042import org.sonar.api.workflow.internal.DefaultReview;
043import org.sonar.api.workflow.internal.DefaultWorkflowContext;
044import org.sonar.api.workflow.screen.Screen;
045import org.sonar.core.i18n.RuleI18nManager;
046import org.sonar.core.persistence.Database;
047import org.sonar.core.persistence.DatabaseMigrator;
048import org.sonar.core.purge.PurgeDao;
049import org.sonar.core.resource.ResourceIndexerDao;
050import org.sonar.core.workflow.WorkflowEngine;
051import org.sonar.markdown.Markdown;
052import org.sonar.server.configuration.Backup;
053import org.sonar.server.configuration.ProfilesManager;
054import org.sonar.server.filters.Filter;
055import org.sonar.server.filters.FilterExecutor;
056import org.sonar.server.filters.FilterResult;
057import org.sonar.server.notifications.reviews.ReviewsNotificationManager;
058import org.sonar.server.platform.GlobalSettingsUpdater;
059import org.sonar.server.platform.Platform;
060import org.sonar.server.platform.ServerIdGenerator;
061import org.sonar.server.plugins.*;
062import org.sonar.server.rules.ProfilesConsole;
063import org.sonar.server.rules.RulesConsole;
064import org.sonar.updatecenter.common.Version;
065
066import javax.annotation.Nullable;
067import java.net.InetAddress;
068import java.sql.Connection;
069import java.util.Collection;
070import java.util.List;
071import java.util.Map;
072import java.util.Set;
073
074public final class JRubyFacade {
075
076  private static final JRubyFacade SINGLETON = new JRubyFacade();
077  private JRubyI18n i18n;
078
079  public static JRubyFacade getInstance() {
080    return SINGLETON;
081  }
082
083  public FilterResult executeFilter(Filter filter) {
084    return getContainer().getComponentByType(FilterExecutor.class).execute(filter);
085  }
086
087  public Collection<ResourceType> getResourceTypesForFilter() {
088    return getContainer().getComponentByType(ResourceTypes.class).getAll(ResourceTypes.AVAILABLE_FOR_FILTERS);
089  }
090
091  public Collection<ResourceType> getResourceTypes() {
092    return getContainer().getComponentByType(ResourceTypes.class).getAll();
093  }
094
095  public ResourceType getResourceType(String qualifier) {
096    return getContainer().getComponentByType(ResourceTypes.class).get(qualifier);
097  }
098
099  public String getResourceTypeStringProperty(String resourceTypeQualifier, String resourceTypeProperty) {
100    ResourceType resourceType = getResourceType(resourceTypeQualifier);
101    if (resourceType != null) {
102      return resourceType.getStringProperty(resourceTypeProperty);
103    }
104    return null;
105  }
106
107  public List<String> getQualifiersWithProperty(final String propertyKey) {
108    List<String> qualifiers = Lists.newArrayList();
109    for (ResourceType type : getResourceTypes()) {
110      if (type.getBooleanProperty(propertyKey) == Boolean.TRUE) {
111        qualifiers.add(type.getQualifier());
112      }
113    }
114    return qualifiers;
115  }
116
117  public Boolean getResourceTypeBooleanProperty(String resourceTypeQualifier, String resourceTypeProperty) {
118    ResourceType resourceType = getResourceType(resourceTypeQualifier);
119    if (resourceType != null) {
120      return resourceType.getBooleanProperty(resourceTypeProperty);
121    }
122    return null;
123  }
124
125  public Collection<String> getResourceLeavesQualifiers(String qualifier) {
126    return getContainer().getComponentByType(ResourceTypes.class).getLeavesQualifiers(qualifier);
127  }
128
129  public Collection<String> getResourceChildrenQualifiers(String qualifier) {
130    return getContainer().getComponentByType(ResourceTypes.class).getChildrenQualifiers(qualifier);
131  }
132
133  // UPDATE CENTER ------------------------------------------------------------
134
135  public void downloadPlugin(String pluginKey, String pluginVersion) {
136    getContainer().getComponentByType(PluginDownloader.class).download(pluginKey, Version.create(pluginVersion));
137  }
138
139  public void cancelPluginDownloads() {
140    getContainer().getComponentByType(PluginDownloader.class).cancelDownloads();
141  }
142
143  public List<String> getPluginDownloads() {
144    return getContainer().getComponentByType(PluginDownloader.class).getDownloads();
145  }
146
147  public void uninstallPlugin(String pluginKey) {
148    getContainer().getComponentByType(PluginDeployer.class).uninstall(pluginKey);
149  }
150
151  public void cancelPluginUninstalls() {
152    getContainer().getComponentByType(PluginDeployer.class).cancelUninstalls();
153  }
154
155  public List<String> getPluginUninstalls() {
156    return getContainer().getComponentByType(PluginDeployer.class).getUninstalls();
157  }
158
159  public UpdateCenterMatrix getUpdateCenterMatrix(boolean forceReload) {
160    return getContainer().getComponentByType(UpdateCenterMatrixFactory.class).getMatrix(forceReload);
161  }
162
163  // PLUGINS ------------------------------------------------------------------
164
165  public PropertyDefinitions getPropertyDefinitions() {
166    return getContainer().getComponentByType(PropertyDefinitions.class);
167  }
168
169  public boolean hasPlugin(String key) {
170    return getContainer().getComponentByType(PluginRepository.class).getPlugin(key) != null;
171  }
172
173  public Collection<PluginMetadata> getPluginsMetadata() {
174    return getContainer().getComponentByType(PluginRepository.class).getMetadata();
175  }
176
177  // SYNTAX HIGHLIGHTING ------------------------------------------------------
178
179  public String colorizeCode(String code, String language) {
180    try {
181      return getContainer().getComponentByType(CodeColorizers.class).toHtml(code, language);
182
183    } catch (Exception e) {
184      LoggerFactory.getLogger(getClass()).error("Can not highlight the code, language= " + language, e);
185      return code;
186    }
187  }
188
189  public static String markdownToHtml(String input) {
190    return Markdown.convertToHtml(input);
191  }
192
193  public List<ViewProxy<Widget>> getWidgets(String resourceScope, String resourceQualifier, String resourceLanguage, Object[] availableMeasures) {
194    return getContainer().getComponentByType(Views.class).getWidgets(resourceScope, resourceQualifier, resourceLanguage, (String[]) availableMeasures);
195  }
196
197  public List<ViewProxy<Widget>> getWidgets() {
198    return getContainer().getComponentByType(Views.class).getWidgets();
199  }
200
201  public ViewProxy<Widget> getWidget(String id) {
202    return getContainer().getComponentByType(Views.class).getWidget(id);
203  }
204
205  public List<ViewProxy<Page>> getPages(String section, String resourceScope, String resourceQualifier, String resourceLanguage, Object[] availableMeasures) {
206    return getContainer().getComponentByType(Views.class).getPages(section, resourceScope, resourceQualifier, resourceLanguage, (String[]) availableMeasures);
207  }
208
209  public List<ViewProxy<Page>> getResourceTabs() {
210    return getContainer().getComponentByType(Views.class).getPages(NavigationSection.RESOURCE_TAB, null, null, null, null);
211  }
212
213  public List<ViewProxy<Page>> getResourceTabs(String scope, String qualifier, String language, Object[] availableMeasures) {
214    return getContainer().getComponentByType(Views.class).getPages(NavigationSection.RESOURCE_TAB, scope, qualifier, language, (String[]) availableMeasures);
215  }
216
217  public List<ViewProxy<Page>> getResourceTabsForMetric(String scope, String qualifier, String language, Object[] availableMeasures, String metric) {
218    return getContainer().getComponentByType(Views.class).getPagesForMetric(NavigationSection.RESOURCE_TAB, scope, qualifier, language, (String[]) availableMeasures, metric);
219  }
220
221  public ViewProxy<Page> getPage(String id) {
222    return getContainer().getComponentByType(Views.class).getPage(id);
223  }
224
225  public Collection<RubyRailsWebservice> getRubyRailsWebservices() {
226    return getContainer().getComponentsByType(RubyRailsWebservice.class);
227  }
228
229  public Collection<Language> getLanguages() {
230    return getContainer().getComponentsByType(Language.class);
231  }
232
233  public Database getDatabase() {
234    return getContainer().getComponentByType(Database.class);
235  }
236
237  public boolean createDatabase() {
238    return getContainer().getComponentByType(DatabaseMigrator.class).createDatabase();
239  }
240
241  /* PROFILES CONSOLE : RULES AND METRIC THRESHOLDS */
242
243  public List<RuleRepository> getRuleRepositories() {
244    return getContainer().getComponentByType(RulesConsole.class).getRepositories();
245  }
246
247  public RuleRepository getRuleRepository(String repositoryKey) {
248    return getContainer().getComponentByType(RulesConsole.class).getRepository(repositoryKey);
249  }
250
251  public Set<RuleRepository> getRuleRepositoriesByLanguage(String languageKey) {
252    return getContainer().getComponentByType(RulesConsole.class).getRepositoriesByLanguage(languageKey);
253  }
254
255  public String backupProfile(int profileId) {
256    return getContainer().getComponentByType(ProfilesConsole.class).backupProfile(profileId);
257  }
258
259  public ValidationMessages restoreProfile(String xmlBackup, boolean deleteExisting) {
260    return getContainer().getComponentByType(ProfilesConsole.class).restoreProfile(xmlBackup, deleteExisting);
261  }
262
263  public List<ProfileExporter> getProfileExportersForLanguage(String language) {
264    return getContainer().getComponentByType(ProfilesConsole.class).getProfileExportersForLanguage(language);
265  }
266
267  public List<ProfileImporter> getProfileImportersForLanguage(String language) {
268    return getContainer().getComponentByType(ProfilesConsole.class).getProfileImportersForLanguage(language);
269  }
270
271  /**
272   * @throws IllegalArgumentException if no such exporter
273   */
274  public String exportProfile(int profileId, String exporterKey) {
275    return getContainer().getComponentByType(ProfilesConsole.class).exportProfile(profileId, exporterKey);
276  }
277
278  public ValidationMessages importProfile(String profileName, String language, String importerKey, String fileContent) {
279    return getContainer().getComponentByType(ProfilesConsole.class).importProfile(profileName, language, importerKey, fileContent);
280  }
281
282  public String getProfileExporterMimeType(String exporterKey) {
283    return getContainer().getComponentByType(ProfilesConsole.class).getProfileExporter(exporterKey).getMimeType();
284  }
285
286  public void renameProfile(int profileId, String newProfileName) {
287    getProfilesManager().renameProfile(profileId, newProfileName);
288  }
289
290  public void copyProfile(long profileId, String newProfileName) {
291    getProfilesManager().copyProfile((int) profileId, newProfileName);
292  }
293
294  public void deleteProfile(long profileId) {
295    getProfilesManager().deleteProfile((int) profileId);
296  }
297
298  public ValidationMessages changeParentProfile(int profileId, String parentName, String userName) {
299    return getProfilesManager().changeParentProfile(profileId, parentName, userName);
300  }
301
302  public void ruleActivated(int parentProfileId, int activeRuleId, String userName) {
303    getProfilesManager().activated(parentProfileId, activeRuleId, userName);
304  }
305
306  public void ruleParamChanged(int parentProfileId, int activeRuleId, String paramKey, String oldValue, String newValue, String userName) {
307    getProfilesManager().ruleParamChanged(parentProfileId, activeRuleId, paramKey, oldValue, newValue, userName);
308  }
309
310  public void ruleSeverityChanged(int parentProfileId, int activeRuleId, int oldSeverityId, int newSeverityId, String userName) {
311    getProfilesManager().ruleSeverityChanged(parentProfileId, activeRuleId, RulePriority.values()[oldSeverityId],
312        RulePriority.values()[newSeverityId], userName);
313  }
314
315  public void ruleDeactivated(int parentProfileId, int deactivatedRuleId, String userName) {
316    getProfilesManager().deactivated(parentProfileId, deactivatedRuleId, userName);
317  }
318
319  public void revertRule(int profileId, int activeRuleId, String userName) {
320    getProfilesManager().revert(profileId, activeRuleId, userName);
321  }
322
323  public List<Footer> getWebFooters() {
324    return getContainer().getComponentsByType(Footer.class);
325  }
326
327  public Backup getBackup() {
328    return getContainer().getComponentByType(Backup.class);
329  }
330
331  private ProfilesManager getProfilesManager() {
332    return getContainer().getComponentByType(ProfilesManager.class);
333  }
334
335  public void setGlobalProperty(String key, @Nullable String value) {
336    getContainer().getComponentByType(GlobalSettingsUpdater.class).setProperty(key, value);
337  }
338
339  public Settings getSettings() {
340    return getContainer().getComponentByType(Settings.class);
341  }
342
343  public String getConfigurationValue(String key) {
344    return getContainer().getComponentByType(Settings.class).getString(key);
345  }
346
347  public List<InetAddress> getValidInetAddressesForServerId() {
348    return getContainer().getComponentByType(ServerIdGenerator.class).getAvailableAddresses();
349  }
350
351  public String generateServerId(String organisation, String ipAddress) {
352    return getContainer().getComponentByType(ServerIdGenerator.class).generate(organisation, ipAddress);
353  }
354
355  public Connection getConnection() {
356    try {
357      return getContainer().getComponentByType(Database.class).getDataSource().getConnection();
358    } catch (Exception e) {
359      /* activerecord does not correctly manage exceptions when connection can not be opened. */
360      return null;
361    }
362  }
363
364  public Object getCoreComponentByClassname(String className) {
365    if (className == null) {
366      return null;
367    }
368
369    try {
370      Class<?> aClass = Class.forName(className);
371      return getContainer().getComponentByType(aClass);
372
373    } catch (ClassNotFoundException e) {
374      LoggerFactory.getLogger(getClass()).error("Component not found: " + className, e);
375      return null;
376    }
377  }
378
379  public Object getComponentByClassname(String pluginKey, String className) {
380    Object component = null;
381    ComponentContainer container = getContainer();
382    Class<?> componentClass = container.getComponentByType(DefaultServerPluginRepository.class).getClass(pluginKey, className);
383    if (componentClass != null) {
384      component = container.getComponentByType(componentClass);
385    }
386    return component;
387  }
388
389  public String getMessage(String rubyLocale, String key, String defaultValue, Object... parameters) {
390    if (i18n == null) {
391      i18n = getContainer().getComponentByType(JRubyI18n.class);
392    }
393    return i18n.message(rubyLocale, key, defaultValue, parameters);
394  }
395
396  public String getRuleName(String rubyLocale, String repositoryKey, String key) {
397    if (i18n == null) {
398      i18n = getContainer().getComponentByType(JRubyI18n.class);
399    }
400    return i18n.getRuleName(rubyLocale, repositoryKey, key);
401  }
402
403  public String getRuleDescription(String rubyLocale, String repositoryKey, String key) {
404    if (i18n == null) {
405      i18n = getContainer().getComponentByType(JRubyI18n.class);
406    }
407    return i18n.getRuleDescription(rubyLocale, repositoryKey, key);
408  }
409
410  public String getRuleParamDescription(String rubyLocale, String repositoryKey, String key, String paramKey) {
411    if (i18n == null) {
412      i18n = getContainer().getComponentByType(JRubyI18n.class);
413    }
414    return i18n.getRuleParamDescription(rubyLocale, repositoryKey, key, paramKey);
415  }
416
417  public List<RuleI18nManager.RuleKey> searchRuleName(String rubyLocale, String searchText) {
418    if (i18n == null) {
419      i18n = getContainer().getComponentByType(JRubyI18n.class);
420    }
421    return i18n.searchRuleName(rubyLocale, searchText);
422  }
423
424  public String getJsL10nDictionnary(String rubyLocale) {
425    if (i18n == null) {
426      i18n = getContainer().getComponentByType(JRubyI18n.class);
427    }
428    return i18n.getJsDictionnary(rubyLocale);
429  }
430
431  public void indexProjects() {
432    getContainer().getComponentByType(ResourceIndexerDao.class).indexProjects();
433  }
434
435  public void indexResource(long resourceId) {
436    getContainer().getComponentByType(ResourceIndexerDao.class).indexResource(resourceId);
437  }
438
439  public void deleteResourceTree(long rootProjectId) {
440    getContainer().getComponentByType(PurgeDao.class).deleteResourceTree(rootProjectId);
441  }
442
443  public void logError(String message) {
444    LoggerFactory.getLogger(getClass()).error(message);
445  }
446
447  public boolean hasSecretKey() {
448    return getContainer().getComponentByType(Settings.class).getEncryption().hasSecretKey();
449  }
450
451  public String encrypt(String clearText) {
452    return getContainer().getComponentByType(Settings.class).getEncryption().encrypt(clearText);
453  }
454
455  public String generateRandomSecretKey() {
456    return getContainer().getComponentByType(Settings.class).getEncryption().generateRandomSecretKey();
457  }
458
459  public License parseLicense(String base64) {
460    return License.readBase64(base64);
461  }
462
463  public String getServerHome() {
464    return getContainer().getComponentByType(Settings.class).getString(CoreProperties.SONAR_HOME);
465  }
466
467  public ReviewsNotificationManager getReviewsNotificationManager() {
468    return getContainer().getComponentByType(ReviewsNotificationManager.class);
469  }
470
471  public ComponentContainer getContainer() {
472    return Platform.getInstance().getContainer();
473  }
474
475  // REVIEWS ------------------------------------------------------------------
476
477  public List<Screen> listAvailableReviewScreens(Review review, DefaultWorkflowContext context) {
478    return getContainer().getComponentByType(WorkflowEngine.class).listAvailableScreens(review, context, true);
479  }
480
481  public ListMultimap<Long, Screen> listAvailableReviewsScreens(DefaultReview[] reviews, DefaultWorkflowContext context) {
482    return getContainer().getComponentByType(WorkflowEngine.class).listAvailableScreens(reviews, context, true);
483  }
484
485  public Screen getReviewScreen(String commandKey) {
486    return getContainer().getComponentByType(WorkflowEngine.class).getScreen(commandKey);
487  }
488
489  public void executeReviewCommand(String commandKey, DefaultReview review, DefaultWorkflowContext context, Map<String, String> parameters) {
490    try {
491      getContainer().getComponentByType(WorkflowEngine.class).execute(commandKey, review, context, parameters);
492    } catch (RuntimeException e) {
493      LoggerFactory.getLogger(JRubyFacade.class).error("Fail to execute command: " + commandKey + " on review " + review.getReviewId(), e);
494      throw e;
495    }
496  }
497}