Skip to content

Commit

Permalink
PLUGINAPI-42 Introduce framework agnostic types for Http extensions
Browse files Browse the repository at this point in the history
- Use new types for identity providers, deprecate javax methods
- Introduce HttpFilter class and deprecate ServletFilter which is using javax.servlet.*
- Add new methods required by filters in SonarQube
- Deprecate javax.servlet usage in org.sonar.api.security package

Co-authored-by: Eric Giffon <[email protected]>
Co-authored-by: Alain Kermis <[email protected]>
Co-authored-by: Antoine Vinot <[email protected]>
Co-authored-by: Jacek Poreda <[email protected]>
  • Loading branch information
4 people committed Apr 21, 2023
1 parent f2fff9a commit 42ca0a6
Show file tree
Hide file tree
Showing 20 changed files with 1,091 additions and 21 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
## 9.16

* Extension point `org.sonar.api.resources.Language` now supports `filenamePatterns` to detect files' language based on more complex filename patterns than only filename extensions.
* Usage of `javax-servlet-api` is now deprecated in favor of custom, framework agnostic API:
* Replace ~~`org.sonar.api.web.ServletFilter`~~ by `org.sonar.api.server.web.HttpFilter`
* Replace ~~`javax.servlet.http.HttpServletRequest`~~ by `org.sonar.api.server.http.HttpRequest`
* Replace ~~`javax.servlet.http.HttpServletResponse`~~ by `org.sonar.api.server.http.HttpResponse`
* Other added classes: `org.sonar.api.web.FilterChain`, `org.sonar.api.web.UrlPattern` and `org.sonar.api.server.http.Cookie`

## 9.15

Expand All @@ -12,4 +17,4 @@
* Utility classes used to test logs have been moved to a separate artifact `org.sonarsource.api.plugin:sonar-plugin-api-test-fixtures` and moved to a new package:
* `org.sonar.api.utils.log.LogTester` &rarr; `org.sonar.api.testfixtures.log.LogTester`
* `org.sonar.api.utils.log.LogTesterJUnit5` &rarr; `org.sonar.api.testfixtures.log.LogTesterJUnit5`
* **Breaking change for tests**: the default log level when using `LogTester` is now `INFO`. This is consistent with the default behavior of Sonar products. If you want to assert `DEBUG` or `TRACE` logs in your tests, you should first change the log level by using for example `logTester.setLevel(Level.DEBUG)`.
* **Breaking change for tests**: the default log level when using `LogTester` is now `INFO`. This is consistent with the default behavior of Sonar products. If you want to assert `DEBUG` or `TRACE` logs in your tests, you should first change the log level by using for example `logTester.setLevel(Level.DEBUG)`.
2 changes: 1 addition & 1 deletion plugin-api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ dependencies {
implementation project(':check-api')

compileOnly libs.jsr305
compileOnly libs.servlet.api
compileOnly libs.javax.servlet.api

testImplementation libs.junit4
testImplementation libs.junit5
Expand Down
21 changes: 19 additions & 2 deletions plugin-api/src/main/java/org/sonar/api/security/Authenticator.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import javax.servlet.http.HttpServletRequest;
import org.sonar.api.ExtensionPoint;
import org.sonar.api.server.ServerSide;
import org.sonar.api.server.http.HttpRequest;

import static java.util.Objects.requireNonNull;

Expand All @@ -44,12 +45,17 @@ public static final class Context {
private String username;
private String password;
private HttpServletRequest request;
private HttpRequest httpRequest;

public Context(@Nullable String username, @Nullable String password, HttpServletRequest request) {
/**
* This class is not meant to be instantiated by plugins, except for tests.
*/
public Context(@Nullable String username, @Nullable String password, HttpRequest httpRequest, HttpServletRequest request) {
requireNonNull(request);
this.request = request;
this.username = username;
this.password = password;
this.httpRequest = httpRequest;
this.request = request;
}

/**
Expand All @@ -66,8 +72,19 @@ public String getPassword() {
return password;
}

/**
* @deprecated since 9.16. Use {@link #getHttpRequest()} instead.
*/
@Deprecated(since = "9.16", forRemoval = true)
public HttpServletRequest getRequest() {
return request;
}

/**
* @since 9.16
*/
public HttpRequest getHttpRequest() {
return httpRequest;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.Collection;
import javax.annotation.CheckForNull;
import javax.servlet.http.HttpServletRequest;
import org.sonar.api.server.http.HttpRequest;

/**
* Note that prefix "do" for names of methods is reserved for future enhancements, thus should not be used in subclasses.
Expand All @@ -46,18 +47,34 @@ public Collection<String> doGetGroups(Context context) {
public static final class Context {
private String username;
private HttpServletRequest request;
private HttpRequest httpRequest;

public Context(String username, HttpServletRequest request) {
/**
* This class is not meant to be instantiated by plugins, except for tests.
*/
public Context(String username, HttpRequest httpRequest, HttpServletRequest request) {
this.username = username;
this.httpRequest = httpRequest;
this.request = request;
}

public String getUsername() {
return username;
}

/**
* @deprecated since 9.16. Use {@link #getHttpRequest()} instead.
*/
@Deprecated(since = "9.16", forRemoval = true)
public HttpServletRequest getRequest() {
return request;
}

/**
* @since 9.16
*/
public HttpRequest getHttpRequest() {
return httpRequest;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import org.sonar.api.server.http.HttpRequest;

/**
* Note that prefix "do" for names of methods is reserved for future enhancements, thus should not be used in subclasses.
Expand All @@ -43,18 +44,34 @@ public UserDetails doGetUserDetails(Context context) {
public static final class Context {
private String username;
private HttpServletRequest request;
private HttpRequest httpRequest;

public Context(@Nullable String username, HttpServletRequest request) {
/**
* This class is not meant to be instantiated by plugins, except for tests.
*/
public Context(@Nullable String username, HttpRequest httpRequest, HttpServletRequest request) {
this.username = username;
this.httpRequest = httpRequest;
this.request = request;
}

public String getUsername() {
return username;
}

/**
* @deprecated since 9.16. Use {@link #getHttpRequest()} instead.
*/
@Deprecated(since = "9.16", forRemoval = true)
public HttpServletRequest getRequest() {
return request;
}

/**
* @since 9.16
*/
public HttpRequest getHttpRequest() {
return httpRequest;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.sonar.api.server.http.HttpRequest;
import org.sonar.api.server.http.HttpResponse;

/**
* @since 5.4
Expand All @@ -35,16 +37,36 @@ public interface BaseIdentityProvider extends IdentityProvider {

interface Context {

/**
* Get the received HTTP request.
*
* @since 9.16
*/
HttpRequest getHttpRequest();

/**
* Get the HTTP response to send.
*
* @since 9.16
*/
HttpResponse getHttpResponse();

/**
* Get the received HTTP request.
* Note - {@code getRequest().getSession()} must not be used in order to support
* future clustering of web servers without stateful server sessions.
*
* @deprecated since 9.16. Use {@link #getHttpRequest()} instead.
*/
@Deprecated(since = "9.16", forRemoval = true)
HttpServletRequest getRequest();

/**
* Get the HTTP response to send
*
* @deprecated since 9.16. Use {@link #getHttpResponse()} instead.
*/
@Deprecated(since = "9.16", forRemoval = true)
HttpServletResponse getResponse();

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.sonar.api.server.http.HttpRequest;
import org.sonar.api.server.http.HttpResponse;

/**
* @since 5.4
Expand All @@ -45,16 +47,36 @@ interface OAuth2Context {
*/
String getCallbackUrl();

/**
* Get the received HTTP request.
*
* @since 9.16
*/
HttpRequest getHttpRequest();

/**
* Get the HTTP response to send.
*
* @since 9.16
*/
HttpResponse getHttpResponse();

/**
* Get the received HTTP request.
* Note - {@code getRequest().getSession()} must not be used in order to support
* future clustering of web servers without stateful server sessions.
*
* @deprecated since 9.16. Use {@link #getHttpRequest()} instead.
*/
@Deprecated(since = "9.16", forRemoval = true)
HttpServletRequest getRequest();

/**
* Get the HTTP response to send
*
* @deprecated since 9.16. Use {@link #getHttpResponse()} instead.
*/
@Deprecated(since = "9.16", forRemoval = true)
HttpServletResponse getResponse();
}

Expand Down
69 changes: 69 additions & 0 deletions plugin-api/src/main/java/org/sonar/api/server/http/Cookie.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Sonar Plugin API
* 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.api.server.http;

/**
* Framework-agnostic definition of a cookie.
* Creates a cookie, a small amount of information sent by a servlet to
* a Web browser, saved by the browser, and later sent back to the server.
* A cookie's value can uniquely
* identify a client, so cookies are commonly used for session management.
*
* @since 9.16
**/
public interface Cookie {

/**
* Returns the name of the cookie. The name cannot be changed after
* creation.
*/
String getName();

/**
* Gets the current value of this Cookie.
*/
String getValue();

/**
* Returns the path on the server
* to which the browser returns this cookie. The
* cookie is visible to all subpaths on the server.
*/
String getPath();

/**
* Returns <code>true</code> if the browser is sending cookies
* only over a secure protocol, or <code>false</code> if the
* browser can send cookies using any protocol.
*/
boolean isSecure();

/**
* Checks whether this Cookie has been marked as <i>HttpOnly</i>.
*/
boolean isHttpOnly();

/**
* Gets the maximum age in seconds of this Cookie.
*/
int getMaxAge();


}
Loading

0 comments on commit 42ca0a6

Please sign in to comment.