@@ -158,6 +158,7 @@ subprojects { | |||
ext { | |||
protobufVersion = '3.21.12' | |||
springVersion = '5.3.23' | |||
} | |||
sonar { | |||
@@ -329,6 +330,7 @@ subprojects { | |||
dependency('org.mockito:mockito-core:5.0.0') { | |||
exclude 'org.hamcrest:hamcrest-core' | |||
} | |||
dependency "org.springframework:spring-test:${springVersion}" | |||
dependency 'org.mybatis:mybatis:3.5.11' | |||
dependencySet(group: 'org.slf4j', version: '2.0.6') { | |||
entry 'jcl-over-slf4j' | |||
@@ -341,9 +343,13 @@ subprojects { | |||
dependency 'org.simpleframework:simple:5.1.6' | |||
dependency 'org.sonarsource.orchestrator:sonar-orchestrator:3.40.0.183' | |||
dependency 'org.sonarsource.update-center:sonar-update-center-common:1.29.0.1000' | |||
dependency('org.springframework:spring-context:5.3.23') { | |||
dependency("org.springframework:spring-context:${springVersion}") { | |||
exclude 'commons-logging:commons-logging' | |||
} | |||
dependency ("org.springframework:spring-webmvc:${springVersion}") { | |||
exclude 'commons-logging:commons-logging' | |||
} | |||
dependency 'org.springdoc:springdoc-openapi-ui:1.6.14' | |||
dependency 'org.subethamail:subethasmtp:3.1.7' | |||
dependency 'org.yaml:snakeyaml:1.33' | |||
@@ -1,17 +0,0 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<beans xmlns="http://www.springframework.org/schema/beans" | |||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xmlns:context="http://www.springframework.org/schema/context" | |||
xmlns:mvc="http://www.springframework.org/schema/mvc" | |||
xsi:schemaLocation="http://www.springframework.org/schema/beans | |||
http://www.springframework.org/schema/beans/spring-beans.xsd | |||
http://www.springframework.org/schema/context | |||
http://www.springframework.org/schema/context/spring-context.xsd | |||
http://www.springframework.org/schema/mvc | |||
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> | |||
<context:annotation-config/> | |||
<context:component-scan base-package="org.sonar.server.v2"/> | |||
<mvc:annotation-driven /> | |||
</beans> |
@@ -6,14 +6,16 @@ sonarqube { | |||
dependencies { | |||
// please keep the list grouped by configuration and ordered by name | |||
api 'org.springframework:spring-webmvc:5.3.23' | |||
api 'org.springdoc:springdoc-openapi-ui' | |||
api 'org.springframework:spring-webmvc' | |||
api project(':server:sonar-db-dao') | |||
// We are not suppose to have a v1 dependency. The ideal would be to have another common module between webapi and webapi-v2 but that needs a lot of refactoring. | |||
api project(':server:sonar-webserver-webapi') | |||
testImplementation 'org.mockito:mockito-core' | |||
testImplementation 'org.springframework:spring-test:5.3.23' | |||
testImplementation 'org.springframework:spring-test' | |||
testImplementation testFixtures(project(':server:sonar-server-common')) | |||
@@ -1,48 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2023 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.v2; | |||
import java.util.List; | |||
import java.util.stream.Collectors; | |||
import org.sonar.api.utils.log.Logger; | |||
import org.sonar.api.utils.log.Loggers; | |||
import org.springframework.context.ApplicationContext; | |||
import org.springframework.context.ApplicationListener; | |||
import org.springframework.context.event.ContextRefreshedEvent; | |||
import org.springframework.stereotype.Component; | |||
import org.springframework.web.servlet.handler.AbstractHandlerMethodMapping; | |||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; | |||
@Component | |||
public class LogComponent implements ApplicationListener<ContextRefreshedEvent> { | |||
private static final Logger LOGGER = Loggers.get(LogComponent.class); | |||
@Override | |||
public void onApplicationEvent(ContextRefreshedEvent event) { | |||
ApplicationContext applicationContext = event.getApplicationContext(); | |||
List<Integer> isUseless = applicationContext.getBeansOfType(RequestMappingHandlerMapping.class).values().stream() | |||
.map(AbstractHandlerMethodMapping::getHandlerMethods) | |||
.map(d->{ | |||
d.forEach((e, c)-> LOGGER.info("Registered endpoint: "+e.getName()+" "+e.getDirectPaths()+" "+e)); | |||
return 1; | |||
}) | |||
.collect(Collectors.toList()); | |||
} | |||
} |
@@ -20,18 +20,39 @@ | |||
package org.sonar.server.v2.common; | |||
import java.util.Optional; | |||
import org.sonar.server.exceptions.ForbiddenException; | |||
import org.sonar.server.exceptions.ServerException; | |||
import org.sonar.server.exceptions.UnauthorizedException; | |||
import org.springframework.http.HttpStatus; | |||
import org.springframework.http.ResponseEntity; | |||
import org.springframework.web.bind.annotation.ExceptionHandler; | |||
import org.springframework.web.bind.annotation.ResponseStatus; | |||
import org.springframework.web.bind.annotation.RestControllerAdvice; | |||
@RestControllerAdvice | |||
public class RestResponseEntityExceptionHandler { | |||
@ExceptionHandler(IllegalStateException.class) | |||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) | |||
protected ResponseEntity<Object> handleIllegalStateException(IllegalStateException illegalStateException) { | |||
return new ResponseEntity<>(illegalStateException.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); | |||
} | |||
@ExceptionHandler(ForbiddenException.class) | |||
@ResponseStatus(HttpStatus.FORBIDDEN) | |||
protected ResponseEntity<Object> handleForbiddenException(ForbiddenException forbiddenException) { | |||
return handleServerException(forbiddenException); | |||
} | |||
@ExceptionHandler(UnauthorizedException.class) | |||
@ResponseStatus(HttpStatus.UNAUTHORIZED) | |||
protected ResponseEntity<Object> handleUnauthorizedException(UnauthorizedException unauthorizedException) { | |||
return handleServerException(unauthorizedException); | |||
} | |||
@ExceptionHandler(ServerException.class) | |||
protected ResponseEntity<Object> handleServerException(ServerException serverException) { | |||
return new ResponseEntity<>(serverException.getMessage(), Optional.ofNullable(HttpStatus.resolve(serverException.httpCode())).orElse(HttpStatus.INTERNAL_SERVER_ERROR)); | |||
} | |||
} |
@@ -19,13 +19,19 @@ | |||
*/ | |||
package org.sonar.server.v2.config; | |||
import io.swagger.v3.oas.models.OpenAPI; | |||
import io.swagger.v3.oas.models.info.Info; | |||
import org.sonar.server.v2.common.RestResponseEntityExceptionHandler; | |||
import org.springframework.context.annotation.Bean; | |||
import org.springframework.context.annotation.ComponentScan; | |||
import org.springframework.context.annotation.Configuration; | |||
import org.springframework.context.annotation.PropertySource; | |||
import org.springframework.web.servlet.config.annotation.EnableWebMvc; | |||
@Configuration | |||
@EnableWebMvc | |||
@ComponentScan(basePackages = {"org.springdoc"}) | |||
@PropertySource("classpath:springdoc.properties") | |||
public class CommonWebConfig { | |||
@Bean | |||
@@ -33,4 +39,15 @@ public class CommonWebConfig { | |||
return new RestResponseEntityExceptionHandler(); | |||
} | |||
@Bean | |||
public OpenAPI customOpenAPI() { | |||
return new OpenAPI() | |||
.info( | |||
new Info() | |||
.title("SonarQube Web API") | |||
.version("0.0.1 alpha") | |||
.description("Documentation of SonarQube Web API") | |||
); | |||
} | |||
} |
@@ -0,0 +1 @@ | |||
springdoc.api-docs.path=/api-docs |
@@ -13,12 +13,6 @@ dependencies { | |||
api 'io.prometheus:simpleclient_common' | |||
api 'io.prometheus:simpleclient_servlet' | |||
api 'org.springframework:spring-webmvc:5.3.23' | |||
api 'org.springframework:spring-web:5.3.23' | |||
api 'org.springframework:spring-context:5.3.23' | |||
api 'org.springframework:spring-core:5.3.23' | |||
testImplementation 'org.springframework:spring-test:5.3.23' | |||
api project(':server:sonar-ce-common') | |||
api project(':server:sonar-ce-task') | |||
api project(':server:sonar-db-dao') |
@@ -31,7 +31,6 @@ import org.sonar.api.utils.log.Loggers; | |||
import org.sonar.api.utils.log.Profiler; | |||
import org.sonar.core.platform.ExtensionContainer; | |||
import org.sonar.core.platform.SpringComponentContainer; | |||
import org.sonar.server.platform.web.ApiV2Servlet; | |||
import org.sonar.server.app.ProcessCommandWrapper; | |||
import org.sonar.server.platform.db.migration.version.DatabaseVersion; | |||
import org.sonar.server.platform.platformlevel.PlatformLevel; | |||
@@ -41,7 +40,7 @@ import org.sonar.server.platform.platformlevel.PlatformLevel3; | |||
import org.sonar.server.platform.platformlevel.PlatformLevel4; | |||
import org.sonar.server.platform.platformlevel.PlatformLevelSafeMode; | |||
import org.sonar.server.platform.platformlevel.PlatformLevelStartup; | |||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; | |||
import org.sonar.server.platform.web.ApiV2Servlet; | |||
import static org.sonar.process.ProcessId.WEB_SERVER; | |||
@@ -63,12 +62,11 @@ public class PlatformImpl implements Platform { | |||
private PlatformLevel level3 = null; | |||
private PlatformLevel level4 = null; | |||
private PlatformLevel currentLevel = null; | |||
private AnnotationConfigWebApplicationContext springMvcContext = null; | |||
private boolean dbConnected = false; | |||
private boolean started = false; | |||
private final List<Object> level4AddedComponents = new ArrayList<>(); | |||
private final Profiler profiler = Profiler.createIfTrace(Loggers.get(PlatformImpl.class)); | |||
private ApiV2Servlet servlet; | |||
private ApiV2Servlet servlet = null; | |||
public static PlatformImpl getInstance() { | |||
return INSTANCE; |
@@ -43,7 +43,7 @@ jar.enabled = false | |||
shadowJar { | |||
archiveBaseName = 'sonar-application' | |||
archiveClassifier = null | |||
mergeServiceFiles('META-INF/spring.*') | |||
mergeServiceFiles() | |||
manifest { | |||
attributes('Main-Class': 'org.sonar.application.App') | |||
} | |||
@@ -309,7 +309,7 @@ task zip(type: Zip, dependsOn: [configurations.compileClasspath, downloadElastic | |||
// Check the size of the archive | |||
zip.doLast { | |||
def minLength = 320000000 | |||
def maxLength = 345000000 | |||
def maxLength = 355000000 | |||
def length = archiveFile.get().asFile.length() | |||
if (length < minLength) |