3 * Copyright (C) 2009-2024 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.scanner.repository.language;
22 import com.google.gson.Gson;
23 import java.io.Reader;
24 import java.util.Collection;
25 import java.util.HashMap;
26 import java.util.List;
28 import java.util.function.Function;
29 import java.util.stream.Collectors;
30 import javax.annotation.CheckForNull;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33 import org.sonar.api.Startable;
34 import org.sonar.api.config.Configuration;
35 import org.sonar.api.resources.Languages;
36 import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
37 import org.sonarqube.ws.client.GetRequest;
40 * Languages repository using {@link Languages}
43 public class DefaultLanguagesRepository implements LanguagesRepository, Startable {
44 private static final Logger LOG = LoggerFactory.getLogger(DefaultLanguagesRepository.class);
45 private static final String LANGUAGES_WS_URL = "/api/languages/list";
46 private static final Map<String, String> PROPERTY_FRAGMENT_MAP = Map.of(
53 private final Map<String, Language> languages = new HashMap<>();
54 private final DefaultScannerWsClient wsClient;
55 private final Configuration properties;
57 public DefaultLanguagesRepository(DefaultScannerWsClient wsClient, Configuration properties) {
58 this.wsClient = wsClient;
59 this.properties = properties;
64 GetRequest getRequest = new GetRequest(LANGUAGES_WS_URL);
65 LanguagesWSResponse response;
66 try (Reader reader = wsClient.call(getRequest).contentReader()) {
67 response = new Gson().fromJson(reader, LanguagesWSResponse.class);
68 } catch (Exception e) {
69 throw new IllegalStateException("Fail to parse response of " + LANGUAGES_WS_URL, e);
72 languages.putAll(response.languages.stream()
73 .map(this::populateFileSuffixesAndPatterns)
74 .collect(Collectors.toMap(Language::key, Function.identity())));
77 private Language populateFileSuffixesAndPatterns(SupportedLanguageDto lang) {
78 String propertyFragment = PROPERTY_FRAGMENT_MAP.getOrDefault(lang.getKey(), lang.getKey());
79 lang.setFileSuffixes(properties.getStringArray(String.format("sonar.%s.file.suffixes", propertyFragment)));
80 lang.setFilenamePatterns(properties.getStringArray(String.format("sonar.%s.file.patterns", propertyFragment)));
81 if (lang.filenamePatterns() == null && lang.getFileSuffixes() == null) {
82 LOG.debug("Language '{}' cannot be detected as it has neither suffixes nor patterns.", lang.getName());
84 return new Language(lang);
87 private String[] getFileSuffixes(String languageKey) {
88 String propName = String.format("sonar.%s.file.suffixes", PROPERTY_FRAGMENT_MAP.getOrDefault(languageKey, languageKey));
89 return properties.getStringArray(propName);
97 public Language get(String languageKey) {
98 return languages.get(languageKey);
102 * Get list of all supported languages.
105 public Collection<Language> all() {
106 return languages.values();
114 private static class LanguagesWSResponse {
115 List<SupportedLanguageDto> languages;