All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.sonar.server.property.ws.IndexAction Maven / Gradle / Ivy
/*
* SonarQube
* Copyright (C) 2009-2018 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.property.ws;
import com.google.common.base.Splitter;
import com.google.common.collect.Multimap;
import com.google.common.collect.Ordering;
import com.google.common.collect.TreeMultimap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.sonar.api.config.PropertyDefinition;
import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.property.PropertyDto;
import org.sonar.server.user.UserSession;
import org.sonar.server.ws.WsAction;
import static org.apache.commons.lang.StringUtils.isEmpty;
import static org.sonar.api.PropertyType.PROPERTY_SET;
import static org.sonar.api.web.UserRole.ADMIN;
import static org.sonar.server.setting.ws.SettingsWsSupport.DOT_LICENSE;
import static org.sonar.server.setting.ws.SettingsWsSupport.DOT_SECURED;
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
public class IndexAction implements WsAction {
private static final Splitter DOT_SPLITTER = Splitter.on(".").omitEmptyStrings();
private static final Splitter COMMA_SPLITTER = Splitter.on(",");
private static final String COMMA_ENCODED_VALUE = "%2C";
public static final String PARAM_ID = "id";
public static final String PARAM_COMPONENT = "resource";
public static final String PARAM_FORMAT = "format";
private final DbClient dbClient;
private final UserSession userSession;
private final PropertyDefinitions propertyDefinitions;
public IndexAction(DbClient dbClient, UserSession userSession, PropertyDefinitions propertyDefinitions) {
this.dbClient = dbClient;
this.userSession = userSession;
this.propertyDefinitions = propertyDefinitions;
}
@Override
public void define(WebService.NewController context) {
WebService.NewAction action = context.createAction("index")
.setDescription("This web service is deprecated, please use api/settings/values instead.")
.setDeprecatedSince("6.3")
.setResponseExample(getClass().getResource("index-example.json"))
.setSince("2.6")
.setHandler(this);
action.createParam(PARAM_ID)
.setDescription("Setting key")
.setExampleValue("sonar.test.inclusions");
action.createParam(PARAM_COMPONENT)
.setDescription("Component key or database id")
.setExampleValue(KEY_PROJECT_EXAMPLE_001);
action.createParam(PARAM_FORMAT)
.setDescription("Only json response format is available")
.setPossibleValues("json");
}
@Override
public void handle(Request request, Response response) throws Exception {
request.param(PARAM_FORMAT);
JsonWriter json = response.newJsonWriter();
json.beginArray();
doHandle(json, request);
json.endArray();
json.close();
}
private void doHandle(JsonWriter json, Request request) {
try (DbSession dbSession = dbClient.openSession(true)) {
Optional component = loadComponent(dbSession, request);
String key = request.param(PARAM_ID);
List propertyDtos = loadProperties(dbSession, component, Optional.ofNullable(key));
new ResponseBuilder(propertyDtos).build(json);
}
}
private Optional loadComponent(DbSession dbSession, Request request) {
String component = request.param(PARAM_COMPONENT);
if (component == null) {
return Optional.empty();
}
return loadComponent(dbSession, component);
}
private Optional loadComponent(DbSession dbSession, String component) {
try {
Long componentId = Long.parseLong(component);
return Optional.ofNullable(dbClient.componentDao().selectById(dbSession, componentId).orNull());
} catch (NumberFormatException e) {
return Optional.ofNullable(dbClient.componentDao().selectByKey(dbSession, component).orNull());
}
}
private List loadProperties(DbSession dbSession, Optional component, Optional key) {
// List of settings must be kept in the following orders : default -> global -> component
List propertyDtos = new ArrayList<>();
propertyDtos.addAll(loadDefaultSettings(key));
propertyDtos.addAll(loadGlobalSettings(dbSession, key));
component.ifPresent(componentDto -> propertyDtos.addAll(loadComponentSettings(dbSession, key, componentDto).values()));
return propertyDtos.stream().filter(isVisible(component)).collect(Collectors.toList());
}
Predicate isVisible(Optional component) {
return propertyDto -> !propertyDto.getKey().endsWith(DOT_SECURED)
|| hasAdminPermission(component)
|| (propertyDto.getKey().contains(DOT_LICENSE) && userSession.isLoggedIn());
}
private boolean hasAdminPermission(Optional component) {
return component
.map(c -> userSession.hasComponentPermission(ADMIN, c))
.orElse(userSession.isSystemAdministrator());
}
private List loadGlobalSettings(DbSession dbSession, Optional key) {
if (key.isPresent()) {
return dbClient.propertiesDao().selectGlobalPropertiesByKeys(dbSession, Collections.singleton(key.get()));
}
return dbClient.propertiesDao().selectGlobalProperties(dbSession);
}
/**
* Return list of propertyDto by component uuid, sorted from project to lowest module
*/
private Multimap loadComponentSettings(DbSession dbSession, Optional key, ComponentDto component) {
List componentUuids = DOT_SPLITTER.splitToList(component.moduleUuidPath());
List componentDtos = dbClient.componentDao().selectByUuids(dbSession, componentUuids);
Set componentIds = componentDtos.stream().map(ComponentDto::getId).collect(Collectors.toSet());
Map uuidsById = componentDtos.stream().collect(Collectors.toMap(ComponentDto::getId, ComponentDto::uuid));
List properties = key.isPresent() ? dbClient.propertiesDao().selectPropertiesByKeysAndComponentIds(dbSession, Collections.singleton(key.get()), componentIds)
: dbClient.propertiesDao().selectPropertiesByComponentIds(dbSession, componentIds);
Multimap propertyDtosByUuid = TreeMultimap.create(Ordering.explicit(componentUuids), Ordering.arbitrary());
for (PropertyDto propertyDto : properties) {
Long componentId = propertyDto.getResourceId();
String componentUuid = uuidsById.get(componentId);
propertyDtosByUuid.put(componentUuid, propertyDto);
}
return propertyDtosByUuid;
}
private List loadDefaultSettings(Optional key) {
return propertyDefinitions.getAll().stream()
.filter(definition -> !key.isPresent() || key.get().equals(definition.key()))
.filter(defaultProperty -> !isEmpty(defaultProperty.defaultValue()))
.map(definition -> new PropertyDto().setKey(definition.key()).setValue(definition.defaultValue()))
.collect(Collectors.toList());
}
private class ResponseBuilder {
private final List propertyDtos;
private final Map propertiesByKey = new HashMap<>();
ResponseBuilder(List propertyDtos) {
this.propertyDtos = propertyDtos;
}
void build(JsonWriter json) {
processSettings();
propertiesByKey.values().forEach(property -> {
json.beginObject()
.prop("key", property.key)
.prop("value", property.value);
if (!property.values.isEmpty()) {
json.name("values").beginArray().values(property.values).endArray();
}
json.endObject();
});
}
private void processSettings() {
propertyDtos.forEach(setting -> {
Property property = createProperty(setting.getKey());
setValue(setting, property);
});
}
private Property createProperty(String key) {
return propertiesByKey.computeIfAbsent(key, k -> new Property(key));
}
private void setValue(PropertyDto propertyDto, Property property) {
String value = propertyDto.getValue();
property.setValue(value);
PropertyDefinition definition = propertyDefinitions.get(propertyDto.getKey());
if (definition != null && (definition.multiValues() || definition.type().equals(PROPERTY_SET))) {
property.setValues(createValues(value));
}
}
private List createValues(String value) {
return COMMA_SPLITTER.splitToList(value).stream().map(v -> v.replace(COMMA_ENCODED_VALUE, ",")).collect(Collectors.toList());
}
}
private static class Property {
private final String key;
private String value;
private List values = new ArrayList<>();
public Property(String key) {
this.key = key;
}
public Property setValue(String value) {
this.value = value;
return this;
}
public Property setValues(List values) {
this.values = values;
return this;
}
}
}