From 3353cd14e5983f1efffdf476e23836340be5a5d8 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 11 Nov 2025 16:37:11 +0100 Subject: [PATCH] openvidu-server: remove deprecations and warnings --- openvidu-java-client/pom.xml | 12 +- .../io/openvidu/java/client/TokenOptions.java | 2 + .../server/config/OpenviduConfig.java | 169 +++++++++++------- .../java/io/openvidu/server/core/Token.java | 5 +- .../openvidu/server/core/TokenGenerator.java | 6 +- .../kurento/core/KurentoParticipant.java | 4 +- .../kurento/core/KurentoSessionManager.java | 8 +- .../io/openvidu/server/kurento/kms/Kms.java | 12 +- .../server/kurento/kms/KmsManager.java | 6 +- .../recording/RecorderEndpointWrapper.java | 9 +- .../server/rest/SessionRestController.java | 53 ++++-- .../io/openvidu/server/rpc/RpcHandler.java | 6 +- .../server/utils/RandomIdGenerator.java | 36 ++++ ...blicRecordingsSecurityIntegrationTest.java | 6 +- ...OpenViduServerSecurityIntegrationTest.java | 6 +- 15 files changed, 213 insertions(+), 127 deletions(-) create mode 100644 openvidu-server/src/main/java/io/openvidu/server/utils/RandomIdGenerator.java diff --git a/openvidu-java-client/pom.xml b/openvidu-java-client/pom.xml index 81ce7b9b6..d7a40b715 100644 --- a/openvidu-java-client/pom.xml +++ b/openvidu-java-client/pom.xml @@ -86,17 +86,17 @@ the same as in the parent pom.xml nonetheless --> 2.0.17 - - org.junit.jupiter - junit-jupiter-api - 5.11.4 - test - commons-validator commons-validator 1.10.0 + + org.junit.jupiter + junit-jupiter-api + 5.14.1 + test + diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/TokenOptions.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/TokenOptions.java index 253074142..edb050a28 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/TokenOptions.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/TokenOptions.java @@ -24,6 +24,7 @@ import com.google.gson.JsonObject; * @deprecated Use {@link io.openvidu.java.client.ConnectionProperties * ConnectionProperties} instead */ +@Deprecated public class TokenOptions { private OpenViduRole role; @@ -34,6 +35,7 @@ public class TokenOptions { * @deprecated Use {@link io.openvidu.java.client.ConnectionProperties.Builder * ConnectionProperties.Builder} instead */ + @Deprecated public static class Builder { private OpenViduRole role = OpenViduRole.PUBLISHER; diff --git a/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java b/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java index b2d1bf93a..77ce4b67e 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java +++ b/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java @@ -22,19 +22,16 @@ import java.io.IOException; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; -import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; -import java.net.URL; import java.net.UnknownHostException; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -678,8 +675,9 @@ public class OpenviduConfig { if (coturnIp == null || this.coturnIp.isEmpty()) { try { - this.coturnIp = new URL(this.getFinalUrl()).getHost(); - } catch (MalformedURLException e) { + URI finalUri = new URI(this.getFinalUrl()); + this.coturnIp = finalUri.getHost(); + } catch (URISyntaxException e) { log.error("Can't get Domain name from OpenVidu public Url: " + e.getMessage()); } } @@ -945,7 +943,8 @@ public class OpenviduConfig { } } - protected Integer asOptionalIntegerBetweenRanges(String property, Range... ranges) { + @SafeVarargs + protected final Integer asOptionalIntegerBetweenRanges(String property, Range... ranges) { try { String value = getValue(property); if (value == null || value.isEmpty()) { @@ -1087,12 +1086,17 @@ public class OpenviduConfig { public URI checkWebsocketUri(String uri) throws Exception { try { - if (!StringUtils.startsWithAny(uri, "ws://", "wss://")) { + if (!(uri.startsWith("ws://") || uri.startsWith("wss://"))) { throw new Exception("WebSocket protocol not found"); } String parsedUri = uri.replaceAll("^ws://", "http://").replaceAll("^wss://", "https://"); - return new URL(parsedUri).toURI(); - } catch (Exception e) { + URI parsed = new URI(parsedUri); + String scheme = parsed.getScheme(); + if (!"http".equalsIgnoreCase(scheme) && !"https".equalsIgnoreCase(scheme)) { + throw new Exception("Unsupported protocol " + scheme); + } + return parsed; + } catch (URISyntaxException e) { throw new RuntimeException( "URI '" + uri + "' has not a valid WebSocket endpoint format: " + e.getMessage()); } @@ -1100,8 +1104,14 @@ public class OpenviduConfig { protected void checkUrl(String url) throws Exception { try { - new URL(url).toURI(); - } catch (MalformedURLException | URISyntaxException e) { + URI uri = new URI(url); + if (uri.getScheme() == null || uri.getScheme().isEmpty()) { + throw new Exception("Missing URL scheme"); + } + if (uri.getHost() == null || uri.getHost().isEmpty()) { + throw new Exception("Missing URL host"); + } + } catch (URISyntaxException e) { throw new Exception("String '" + url + "' has not a valid URL format: " + e.getMessage()); } } @@ -1283,30 +1293,37 @@ public class OpenviduConfig { if (RecordingLayout.CUSTOM.equals(recordingProperties.recordingLayout())) { String layout = recordingProperties.customLayout(); if (!layout.isEmpty()) { + URI layoutUri = null; try { - URL url = new URL(layout); - log.info("\"customLayout\" property has a URL format ({}). Using it to connect to custom layout", - url.toString()); - return processCustomLayoutUrlFormat(url, sessionId); - } catch (MalformedURLException e) { - String layoutPath = this.getOpenviduRecordingCustomLayout() + layout; - layoutPath = layoutPath.endsWith("/") ? layoutPath : (layoutPath + "/"); + layoutUri = new URI(layout); + } catch (URISyntaxException e) { + layoutUri = null; + } + boolean layoutIsAbsoluteUrl = layoutUri != null && layoutUri.getScheme() != null + && layoutUri.getHost() != null; + if (layoutIsAbsoluteUrl) { log.info( - "\"customLayout\" property is defined as \"{}\". Using a different custom layout than the default one. Expected path: {}", - layout, layoutPath + "index.html"); - try { - final File indexHtml = new File(layoutPath + "index.html"); - if (!indexHtml.exists()) { - throw new IOException(); - } - log.info("Custom layout path \"{}\" is valid. Found file {}", layout, - indexHtml.getAbsolutePath()); - } catch (IOException e1) { - final String error = "Custom layout path " + layout + " is not valid. Expected file " - + layoutPath + "index.html to exist and be readable"; - log.error(error); - throw new OpenViduException(Code.RECORDING_PATH_NOT_VALID, error); + "\"customLayout\" property has a URL format ({}). Using it to connect to custom layout", + layoutUri.toString()); + return processCustomLayoutUrlFormat(layoutUri, sessionId); + } + String layoutPath = this.getOpenviduRecordingCustomLayout() + layout; + layoutPath = layoutPath.endsWith("/") ? layoutPath : (layoutPath + "/"); + log.info( + "\"customLayout\" property is defined as \"{}\". Using a different custom layout than the default one. Expected path: {}", + layout, layoutPath + "index.html"); + try { + final File indexHtml = new File(layoutPath + "index.html"); + if (!indexHtml.exists()) { + throw new IOException(); } + log.info("Custom layout path \"{}\" is valid. Found file {}", layout, + indexHtml.getAbsolutePath()); + } catch (IOException e1) { + final String error = "Custom layout path " + layout + " is not valid. Expected file " + + layoutPath + "index.html to exist and be readable"; + log.error(error); + throw new OpenViduException(Code.RECORDING_PATH_NOT_VALID, error); } } } @@ -1340,8 +1357,12 @@ public class OpenviduConfig { layout = recordingProperties.recordingLayout().name().toLowerCase().replaceAll("_", "-"); int port = startsWithHttp ? 80 : 443; try { - port = new URL(this.getFinalUrl()).getPort(); - } catch (MalformedURLException e) { + URI finalUri = new URI(this.getFinalUrl()); + int uriPort = finalUri.getPort(); + if (uriPort != -1) { + port = uriPort; + } + } catch (URISyntaxException e) { log.error(e.getMessage()); } String defaultPathForDefaultLayout = recordingComposedUrlDefined ? "" @@ -1354,53 +1375,63 @@ public class OpenviduConfig { return finalUrl; } - private String processCustomLayoutUrlFormat(URL url, String shortSessionId) { - String finalUrl = url.getProtocol() + "://" + url.getAuthority(); - if (!url.getPath().isEmpty()) { - finalUrl += url.getPath(); + private String processCustomLayoutUrlFormat(URI url, String shortSessionId) { + StringBuilder finalUrl = new StringBuilder(); + String scheme = url.getScheme(); + if (scheme != null && !scheme.isEmpty()) { + finalUrl.append(scheme).append("://"); } - finalUrl = finalUrl.endsWith("/") ? finalUrl.substring(0, finalUrl.length() - 1) : finalUrl; - if (url.getQuery() != null) { - URI uri; - try { - uri = url.toURI(); - finalUrl += "?"; - } catch (URISyntaxException e) { - String error = "\"customLayout\" property has URL format and query params (" + url.toString() - + "), but does not comply with RFC2396 URI format"; - log.error(error); - throw new OpenViduException(Code.RECORDING_PATH_NOT_VALID, error); - } - List params = URLEncodedUtils.parse(uri, Charset.forName("UTF-8")); - Iterator it = params.iterator(); + String authority = url.getRawAuthority(); + if (authority != null) { + finalUrl.append(authority); + } + String path = url.getRawPath(); + if (path != null && !path.isEmpty()) { + finalUrl.append(path); + } + int length = finalUrl.length(); + if (length > 0 && finalUrl.charAt(length - 1) == '/') { + finalUrl.deleteCharAt(length - 1); + } + String query = url.getRawQuery(); + if (query != null) { + finalUrl.append('?'); + List params = URLEncodedUtils.parse(url, StandardCharsets.UTF_8); boolean hasSessionId = false; boolean hasSecret = false; - while (it.hasNext()) { - NameValuePair param = it.next(); - finalUrl += param.getName() + "=" + param.getValue(); - if (it.hasNext()) { - finalUrl += "&"; + for (int i = 0; i < params.size(); i++) { + NameValuePair param = params.get(i); + finalUrl.append(param.getName()).append('=').append(param.getValue()); + if (i < params.size() - 1) { + finalUrl.append('&'); } - if (!hasSessionId) { - hasSessionId = param.getName().equals("sessionId"); + if (!hasSessionId && "sessionId".equals(param.getName())) { + hasSessionId = true; } - if (!hasSecret) { - hasSecret = param.getName().equals("secret"); + if (!hasSecret && "secret".equals(param.getName())) { + hasSecret = true; } } + boolean hasAppendedParams = !params.isEmpty(); if (!hasSessionId) { - finalUrl += "&sessionId=" + shortSessionId; + if (hasAppendedParams) { + finalUrl.append('&'); + } + finalUrl.append("sessionId=").append(shortSessionId); + hasAppendedParams = true; } if (!hasSecret) { - finalUrl += "&secret=" + this.getOpenViduSecret(); + if (hasAppendedParams) { + finalUrl.append('&'); + } + finalUrl.append("secret=").append(this.getOpenViduSecret()); } } - - if (url.getRef() != null) { - finalUrl += "#" + url.getRef(); + String fragment = url.getRawFragment(); + if (fragment != null) { + finalUrl.append('#').append(fragment); } - - return finalUrl; + return finalUrl.toString(); } } diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java index 37aa9b523..52b27f169 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java @@ -20,8 +20,6 @@ package io.openvidu.server.core; import java.net.MalformedURLException; import java.util.List; -import org.apache.commons.lang3.RandomStringUtils; - import com.google.gson.JsonArray; import com.google.gson.JsonNull; import com.google.gson.JsonObject; @@ -33,6 +31,7 @@ import io.openvidu.java.client.KurentoOptions; import io.openvidu.java.client.OpenViduRole; import io.openvidu.server.core.Participant.ParticipantStatus; import io.openvidu.server.coturn.TurnCredentials; +import io.openvidu.server.utils.RandomIdGenerator; public class Token { @@ -43,7 +42,7 @@ public class Token { private TurnCredentials turnCredentials; private String connectionId = IdentifierPrefixes.PARTICIPANT_PUBLIC_ID - + RandomStringUtils.randomAlphabetic(1).toUpperCase() + RandomStringUtils.randomAlphanumeric(9); + + RandomIdGenerator.alphabetic(1).toUpperCase() + RandomIdGenerator.alphanumeric(9); public Token(String token, String sessionId, ConnectionProperties connectionProperties, TurnCredentials turnCredentials) { diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java b/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java index ef615a7b5..c5ed6a3a2 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java @@ -17,7 +17,6 @@ package io.openvidu.server.core; -import org.apache.commons.lang3.RandomStringUtils; import org.springframework.beans.factory.annotation.Autowired; import io.openvidu.java.client.ConnectionProperties; @@ -30,6 +29,7 @@ import io.openvidu.server.config.OpenviduBuildInfo; import io.openvidu.server.config.OpenviduConfig; import io.openvidu.server.coturn.CoturnCredentialsService; import io.openvidu.server.coturn.TurnCredentials; +import io.openvidu.server.utils.RandomIdGenerator; import java.util.List; @@ -48,8 +48,8 @@ public class TokenGenerator { KurentoOptions kurentoOptions, List customIceServers) throws Exception { String token = OpenViduServer.wsUrl; token += "?sessionId=" + sessionId; - token += "&token=" + IdentifierPrefixes.TOKEN_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase() - + RandomStringUtils.randomAlphanumeric(15); + token += "&token=" + IdentifierPrefixes.TOKEN_ID + RandomIdGenerator.alphabetic(1).toUpperCase() + + RandomIdGenerator.alphanumeric(15); TurnCredentials turnCredentials = coturnCredentialsService.createUser(); ConnectionProperties.Builder connectionPropertiesBuilder = new ConnectionProperties.Builder() .type(ConnectionType.WEBRTC).data(serverMetadata).record(record).role(role) diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java index add645eb3..5e84ea282 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java @@ -27,7 +27,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.function.Function; -import org.apache.commons.lang3.RandomStringUtils; import org.kurento.client.Continuation; import org.kurento.client.Endpoint; import org.kurento.client.ErrorEvent; @@ -57,6 +56,7 @@ import io.openvidu.server.kurento.endpoint.MediaEndpoint; import io.openvidu.server.kurento.endpoint.PublisherEndpoint; import io.openvidu.server.kurento.endpoint.SubscriberEndpoint; import io.openvidu.server.recording.service.RecordingManager; +import io.openvidu.server.utils.RandomIdGenerator; import io.openvidu.server.utils.RemoteOperationUtils; public class KurentoParticipant extends Participant { @@ -436,7 +436,7 @@ public class KurentoParticipant extends Participant { public String generateStreamId(MediaOptions mediaOptions) { String type = mediaOptions.hasVideo() ? mediaOptions.getTypeOfVideo() : "MICRO"; return IdentifierPrefixes.STREAM_ID + type.substring(0, Math.min(type.length(), 3)) + "_" - + RandomStringUtils.randomAlphabetic(1).toUpperCase() + RandomStringUtils.randomAlphanumeric(3) + "_" + + RandomIdGenerator.alphabetic(1).toUpperCase() + RandomIdGenerator.alphanumeric(3) + "_" + this.getParticipantPublicId(); } diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java index 49efaefbe..d979e8219 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java @@ -30,7 +30,6 @@ import java.util.concurrent.TimeUnit; import jakarta.annotation.PreDestroy; -import org.apache.commons.lang3.RandomStringUtils; import org.kurento.client.GenericMediaElement; import org.kurento.client.GenericMediaEvent; import org.kurento.client.IceCandidate; @@ -77,6 +76,7 @@ import io.openvidu.server.kurento.kms.KmsManager; import io.openvidu.server.rpc.RpcHandler; import io.openvidu.server.utils.GeoLocation; import io.openvidu.server.utils.JsonUtils; +import io.openvidu.server.utils.RandomIdGenerator; import io.openvidu.server.utils.RecordingUtils; import io.openvidu.server.utils.SDPMunging; @@ -1169,15 +1169,15 @@ public class KurentoSessionManager extends SessionManager { } String rtspConnectionId = kMediaOptions.getTypeOfVideo() + "_" + protocol + "_" - + RandomStringUtils.randomAlphanumeric(4).toUpperCase() + "_" + uri.getHost() + + RandomIdGenerator.alphanumeric(4).toUpperCase() + "_" + uri.getHost() + (uri.getPort() != -1 ? (":" + uri.getPort()) : "") + uri.getPath(); rtspConnectionId = rtspConnectionId.replace("/", "_").replace("-", "").replace(".", "_").replace(":", "_"); rtspConnectionId = IdentifierPrefixes.IPCAM_ID + rtspConnectionId; // Store a "fake" participant for the IpCam connection this.newInsecureParticipant(rtspConnectionId); - String token = IdentifierPrefixes.TOKEN_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase() - + RandomStringUtils.randomAlphanumeric(15); + String token = IdentifierPrefixes.TOKEN_ID + RandomIdGenerator.alphabetic(1).toUpperCase() + + RandomIdGenerator.alphanumeric(15); this.newTokenForInsecureUser(session, token, connectionProperties, null); final Token tokenObj = session.consumeToken(token); diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/Kms.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/Kms.java index 74825a532..3c42f9aa6 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/Kms.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/Kms.java @@ -17,8 +17,8 @@ package io.openvidu.server.kurento.kms; -import java.net.MalformedURLException; -import java.net.URL; +import java.net.URI; +import java.net.URISyntaxException; import java.util.Collection; import java.util.HashSet; import java.util.Map; @@ -82,13 +82,13 @@ public class Kms { this.uri = props.getUri(); String parsedUri = uri.replaceAll("^ws://", "http://").replaceAll("^wss://", "https://"); - URL url = null; try { - url = new URL(parsedUri); - } catch (MalformedURLException e) { + URI url = new URI(parsedUri); + this.ip = url.getHost(); + } catch (URISyntaxException e) { log.error(e.getMessage()); + this.ip = null; } - this.ip = url.getHost(); this.loadManager = loadManager; this.kmsManager = kmsManager; diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/KmsManager.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/KmsManager.java index 572c3435b..619e948a9 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/KmsManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/KmsManager.java @@ -32,7 +32,6 @@ import java.util.stream.Collectors; import jakarta.annotation.PostConstruct; -import org.apache.commons.lang3.RandomStringUtils; import org.kurento.client.KurentoClient; import org.kurento.commons.exception.KurentoException; import org.kurento.jsonrpc.JsonRpcClientClosedException; @@ -53,6 +52,7 @@ import io.openvidu.server.core.SessionEventsHandler; import io.openvidu.server.core.SessionManager; import io.openvidu.server.kurento.core.KurentoSession; import io.openvidu.server.utils.MediaNodeManager; +import io.openvidu.server.utils.RandomIdGenerator; import io.openvidu.server.utils.RemoteOperationUtils; import io.openvidu.server.utils.UpdatableTimerTask; @@ -408,8 +408,8 @@ public abstract class KmsManager { } public static String generateKmsId() { - return IdentifierPrefixes.MEDIA_NODE_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase() - + RandomStringUtils.randomAlphanumeric(7); + return IdentifierPrefixes.MEDIA_NODE_ID + RandomIdGenerator.alphabetic(1).toUpperCase() + + RandomIdGenerator.alphanumeric(7); } public void nodeCrashedHandler(Kms kms, boolean mustRemoveMediaNode) { diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/RecorderEndpointWrapper.java b/openvidu-server/src/main/java/io/openvidu/server/recording/RecorderEndpointWrapper.java index 76b7c5240..04259f47c 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/RecorderEndpointWrapper.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/RecorderEndpointWrapper.java @@ -17,7 +17,6 @@ package io.openvidu.server.recording; -import org.apache.commons.lang3.StringUtils; import org.kurento.client.RecorderEndpoint; import com.google.gson.JsonObject; @@ -61,8 +60,12 @@ public class RecorderEndpointWrapper { public RecorderEndpointWrapper(JsonObject json, String fileExtension) { String nameAux = json.get("name").getAsString(); - // If the name includes the extension, remove it - this.name = StringUtils.removeEnd(nameAux, fileExtension); + // If the name includes the extension, remove it without relying on deprecated helpers + if (fileExtension != null && !fileExtension.isEmpty() && nameAux.endsWith(fileExtension)) { + this.name = nameAux.substring(0, nameAux.length() - fileExtension.length()); + } else { + this.name = nameAux; + } this.fileExtension = fileExtension; this.connectionId = json.get("connectionId").getAsString(); this.streamId = json.get("streamId").getAsString(); diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java index b9f3653ec..a72b2b1ab 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java @@ -28,7 +28,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.stream.Collectors; -import org.apache.commons.lang3.RandomStringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -70,6 +69,7 @@ import io.openvidu.server.core.Token; import io.openvidu.server.kurento.core.KurentoMediaOptions; import io.openvidu.server.recording.Recording; import io.openvidu.server.recording.service.RecordingManager; +import io.openvidu.server.utils.RandomIdGenerator; import io.openvidu.server.utils.RestUtils; /** @@ -149,8 +149,8 @@ public class SessionRestController { } } } else { - sessionId = IdentifierPrefixes.SESSION_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase() - + RandomStringUtils.randomAlphanumeric(9); + sessionId = IdentifierPrefixes.SESSION_ID + RandomIdGenerator.alphabetic(1).toUpperCase() + + RandomIdGenerator.alphanumeric(9); } Session sessionNotActive = sessionManager.storeSessionNotActive(sessionId, sessionProperties); @@ -288,13 +288,13 @@ public class SessionRestController { HttpStatus.BAD_REQUEST); } switch (connectionProperties.getType()) { - case WEBRTC: - return this.newWebrtcConnection(session, connectionProperties); - case IPCAM: - return this.newIpcamConnection(session, connectionProperties); - default: - return SessionRestController.generateErrorResponse("Wrong type parameter", - "/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST); + case WEBRTC: + return this.newWebrtcConnection(session, connectionProperties); + case IPCAM: + return this.newIpcamConnection(session, connectionProperties); + default: + return SessionRestController.generateErrorResponse("Wrong type parameter", + "/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST); } } @@ -652,11 +652,26 @@ public class SessionRestController { String sessionId; String type; - ArrayList to; + List to = null; String data; try { sessionId = (String) params.get("session"); - to = (ArrayList) params.get("to"); + Object toParam = params.get("to"); + if (toParam instanceof List rawList) { + List target = new ArrayList<>(rawList.size()); + for (Object element : rawList) { + if (element == null) { + target.add(null); + } else if (element instanceof String stringValue) { + target.add(stringValue); + } else { + throw new ClassCastException("Expected String elements in 'to' parameter"); + } + } + to = target; + } else if (toParam != null) { + throw new ClassCastException("Expected 'to' parameter to be a list"); + } type = (String) params.get("type"); data = (String) params.get("data"); } catch (ClassCastException e) { @@ -814,13 +829,13 @@ public class SessionRestController { builder = builder.forcedVideoCodec(forcedVideoCodec); if (forcedVideoCodec == VideoCodec.MEDIA_SERVER_PREFERRED) { switch (openviduConfig.getMediaServer()) { - case mediasoup: - builder = builder.forcedVideoCodecResolved(VideoCodec.NONE); - break; - case kurento: - default: - builder = builder.forcedVideoCodecResolved(VideoCodec.VP8); - break; + case mediasoup: + builder = builder.forcedVideoCodecResolved(VideoCodec.NONE); + break; + case kurento: + default: + builder = builder.forcedVideoCodecResolved(VideoCodec.VP8); + break; } } else { builder = builder.forcedVideoCodecResolved(forcedVideoCodec); diff --git a/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java b/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java index c3165880b..3a0c3ebf9 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java @@ -27,7 +27,6 @@ import java.util.concurrent.ConcurrentMap; import jakarta.annotation.PostConstruct; import jakarta.servlet.http.HttpSession; -import org.apache.commons.lang3.RandomStringUtils; import org.apache.maven.artifact.versioning.DefaultArtifactVersion; import org.kurento.jsonrpc.DefaultJsonRpcHandler; import org.kurento.jsonrpc.Session; @@ -60,6 +59,7 @@ import io.openvidu.server.core.SessionManager; import io.openvidu.server.core.Token; import io.openvidu.server.utils.GeoLocation; import io.openvidu.server.utils.GeoLocationByIp; +import io.openvidu.server.utils.RandomIdGenerator; import io.openvidu.server.utils.VersionComparator; import io.openvidu.server.utils.VersionComparator.VersionMismatchException; @@ -283,8 +283,8 @@ public class RpcHandler extends DefaultJsonRpcHandler { sessionManager.newInsecureParticipant(participantPrivateId); - token = IdentifierPrefixes.TOKEN_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase() - + RandomStringUtils.randomAlphanumeric(15); + token = IdentifierPrefixes.TOKEN_ID + RandomIdGenerator.alphabetic(1).toUpperCase() + + RandomIdGenerator.alphanumeric(15); ConnectionProperties connectionProperties = new ConnectionProperties.Builder().type(ConnectionType.WEBRTC) .role(OpenViduRole.SUBSCRIBER).build(); diff --git a/openvidu-server/src/main/java/io/openvidu/server/utils/RandomIdGenerator.java b/openvidu-server/src/main/java/io/openvidu/server/utils/RandomIdGenerator.java new file mode 100644 index 000000000..0c05ca59f --- /dev/null +++ b/openvidu-server/src/main/java/io/openvidu/server/utils/RandomIdGenerator.java @@ -0,0 +1,36 @@ +package io.openvidu.server.utils; + +import java.util.concurrent.ThreadLocalRandom; + +/** + * Utility methods for generating short random identifiers without relying on + * deprecated Apache Commons Lang helpers. + */ +public final class RandomIdGenerator { + + private static final char[] ALPHABETIC = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray(); + private static final char[] ALPHANUMERIC = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray(); + + private RandomIdGenerator() { + } + + public static String alphabetic(int length) { + return generate(length, ALPHABETIC); + } + + public static String alphanumeric(int length) { + return generate(length, ALPHANUMERIC); + } + + private static String generate(int length, char[] alphabet) { + if (length < 0) { + throw new IllegalArgumentException("Length must be non-negative"); + } + char[] result = new char[length]; + ThreadLocalRandom random = ThreadLocalRandom.current(); + for (int i = 0; i < length; i++) { + result[i] = alphabet[random.nextInt(alphabet.length)]; + } + return new String(result); + } +} diff --git a/openvidu-server/src/test/java/io/openvidu/server/test/integration/OpenViduServerPublicRecordingsSecurityIntegrationTest.java b/openvidu-server/src/test/java/io/openvidu/server/test/integration/OpenViduServerPublicRecordingsSecurityIntegrationTest.java index c0594fe64..f656a4179 100644 --- a/openvidu-server/src/test/java/io/openvidu/server/test/integration/OpenViduServerPublicRecordingsSecurityIntegrationTest.java +++ b/openvidu-server/src/test/java/io/openvidu/server/test/integration/OpenViduServerPublicRecordingsSecurityIntegrationTest.java @@ -32,13 +32,13 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import io.openvidu.server.core.SessionManager; import io.openvidu.server.recording.service.RecordingManager; @@ -57,10 +57,10 @@ class OpenViduServerPublicRecordingsSecurityIntegrationTest { @Autowired private MockMvc mockMvc; - @MockBean + @MockitoBean private SessionManager sessionManager; - @MockBean + @MockitoBean private RecordingManager recordingManager; @BeforeEach diff --git a/openvidu-server/src/test/java/io/openvidu/server/test/integration/OpenViduServerSecurityIntegrationTest.java b/openvidu-server/src/test/java/io/openvidu/server/test/integration/OpenViduServerSecurityIntegrationTest.java index 2cf1f8a9d..023cbf324 100644 --- a/openvidu-server/src/test/java/io/openvidu/server/test/integration/OpenViduServerSecurityIntegrationTest.java +++ b/openvidu-server/src/test/java/io/openvidu/server/test/integration/OpenViduServerSecurityIntegrationTest.java @@ -37,7 +37,6 @@ import org.junit.jupiter.params.provider.MethodSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; @@ -47,6 +46,7 @@ import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import io.openvidu.server.core.SessionManager; import io.openvidu.server.recording.service.RecordingManager; @@ -65,10 +65,10 @@ class OpenViduServerSecurityIntegrationTest { @Autowired private MockMvc mockMvc; - @MockBean + @MockitoBean private SessionManager sessionManager; - @MockBean + @MockitoBean private RecordingManager recordingManager; @BeforeEach