openvidu-java-client: update to support 2.3.0

pull/87/merge
pabloFuente 2018-07-19 12:59:58 +02:00
parent 2a435db320
commit 7a48d52958
14 changed files with 823 additions and 69 deletions

View File

@ -84,6 +84,12 @@
<version>${version.json-simple}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
</dependencies>
<profiles>

View File

@ -0,0 +1,117 @@
/*
* (C) Copyright 2017-2018 OpenVidu (https://openvidu.io/)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package io.openvidu.java.client;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* See {@link io.openvidu.java.client.Session#getActiveConnections()}
*/
public class Connection {
private String connectionId;
private OpenViduRole role;
private String token;
private String serverData;
private String clientData;
protected Map<String, Publisher> publishers;
protected List<String> subscribers;
protected Connection(String connectionId, OpenViduRole role, String token, String serverData, String clientData,
Map<String, Publisher> publishers, List<String> subscribers) {
this.connectionId = connectionId;
this.role = role;
this.token = token;
this.serverData = serverData;
this.clientData = clientData;
this.publishers = publishers;
this.subscribers = subscribers;
}
/**
* Returns the identifier of the connection. You can call
* {@link io.openvidu.java.client.Session#forceDisconnect(String)} passing this
* property as parameter
*/
public String getConnectionId() {
return connectionId;
}
/**
* Returns the role of the connection
*/
public OpenViduRole getRole() {
return role;
}
/**
* Returns the token associated to the connection
*/
public String getToken() {
return token;
}
/**
* Returns the data associated to the connection on the server-side. This value
* is set with {@link io.openvidu.java.client.TokenOptions.Builder#data(String)}
* when calling {@link io.openvidu.java.client.Session#generateToken()}
*/
public String getServerData() {
return serverData;
}
/**
* Returns the data associated to the connection on the client-side. This value
* is set with second parameter of method <a href=
* "https://openvidu.io/api/openvidu-browser/classes/session.html#connect"
* target="_blank">Session.connect</a> in OpenVidu Browser
*/
public String getClientData() {
return clientData;
}
/**
* Returns the list of Publisher objects this particular Connection is
* publishing to the Session (each Publisher object has one Stream, uniquely
* identified by its <code>streamId</code>). You can call
* {@link io.openvidu.java.client.Session#forceUnpublish(Publisher)} passing any
* of this values as parameter
*/
public List<Publisher> getPublishers() {
return new ArrayList<>(this.publishers.values());
}
/**
* Returns the list of streams (their <code>streamId</code> properties) this
* particular Connection is subscribed to. Each one always corresponds to one
* Publisher of some other Connection: each string of the returned list must be
* equal to the returned value of some
* {@link io.openvidu.java.client.Publisher#getStreamId()}
*/
public List<String> getSubscribers() {
return this.subscribers;
}
protected void setSubscribers(List<String> subscribers) {
this.subscribers = subscribers;
}
}

View File

@ -17,6 +17,10 @@
package io.openvidu.java.client;
/**
* See
* {@link io.openvidu.java.client.SessionProperties.Builder#mediaMode(MediaMode)}
*/
public enum MediaMode {
/**
* <i>(not available yet)</i> The session will attempt to transmit streams

View File

@ -25,7 +25,13 @@ import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import javax.net.ssl.SSLContext;
@ -35,13 +41,14 @@ import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;
@ -49,16 +56,23 @@ import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class OpenVidu {
private static final Logger log = LoggerFactory.getLogger(OpenVidu.class);
private String urlOpenViduServer;
private String secret;
private HttpClient myHttpClient;
protected static Map<String, Session> activeSessions = new ConcurrentHashMap<>();
final static String API_RECORDINGS = "api/recordings";
final static String API_RECORDINGS_START = "/start";
final static String API_RECORDINGS_STOP = "/stop";
protected final static String API_SESSIONS = "api/sessions";
protected final static String API_TOKENS = "api/tokens";
protected final static String API_RECORDINGS = "api/recordings";
protected final static String API_RECORDINGS_START = "/start";
protected final static String API_RECORDINGS_STOP = "/stop";
/**
* @param urlOpenViduServer
@ -96,9 +110,13 @@ public class OpenVidu {
throw new RuntimeException(e);
}
this.myHttpClient = HttpClients.custom().setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.setSSLContext(sslContext).setDefaultCredentialsProvider(provider).build();
RequestConfig.Builder requestBuilder = RequestConfig.custom();
requestBuilder = requestBuilder.setConnectTimeout(30000);
requestBuilder = requestBuilder.setConnectionRequestTimeout(30000);
this.myHttpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestBuilder.build())
.setConnectionTimeToLive(30, TimeUnit.SECONDS).setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.setSSLContext(sslContext).setDefaultCredentialsProvider(provider).build();
}
/**
@ -111,6 +129,7 @@ public class OpenVidu {
*/
public Session createSession() throws OpenViduJavaClientException, OpenViduHttpException {
Session s = new Session(myHttpClient, urlOpenViduServer);
OpenVidu.activeSessions.put(s.getSessionId(), s);
return s;
}
@ -135,6 +154,7 @@ public class OpenVidu {
public Session createSession(SessionProperties properties)
throws OpenViduJavaClientException, OpenViduHttpException {
Session s = new Session(myHttpClient, urlOpenViduServer, properties);
OpenVidu.activeSessions.put(s.getSessionId(), s);
return s;
}
@ -193,11 +213,15 @@ public class OpenVidu {
throw new OpenViduJavaClientException(e2.getMessage(), e2.getCause());
}
int statusCode = response.getStatusLine().getStatusCode();
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
return new Recording(httpResponseToJson(response));
} else {
throw new OpenViduHttpException(statusCode);
try {
int statusCode = response.getStatusLine().getStatusCode();
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
return new Recording(httpResponseToJson(response));
} else {
throw new OpenViduHttpException(statusCode);
}
} finally {
EntityUtils.consumeQuietly(response.getEntity());
}
}
@ -300,11 +324,15 @@ public class OpenVidu {
throw new OpenViduJavaClientException(e.getMessage(), e.getCause());
}
int statusCode = response.getStatusLine().getStatusCode();
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
return new Recording(httpResponseToJson(response));
} else {
throw new OpenViduHttpException(statusCode);
try {
int statusCode = response.getStatusLine().getStatusCode();
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
return new Recording(httpResponseToJson(response));
} else {
throw new OpenViduHttpException(statusCode);
}
} finally {
EntityUtils.consumeQuietly(response.getEntity());
}
}
@ -332,11 +360,15 @@ public class OpenVidu {
throw new OpenViduJavaClientException(e.getMessage(), e.getCause());
}
int statusCode = response.getStatusLine().getStatusCode();
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
return new Recording(httpResponseToJson(response));
} else {
throw new OpenViduHttpException(statusCode);
try {
int statusCode = response.getStatusLine().getStatusCode();
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
return new Recording(httpResponseToJson(response));
} else {
throw new OpenViduHttpException(statusCode);
}
} finally {
EntityUtils.consumeQuietly(response.getEntity());
}
}
@ -358,17 +390,21 @@ public class OpenVidu {
throw new OpenViduJavaClientException(e.getMessage(), e.getCause());
}
int statusCode = response.getStatusLine().getStatusCode();
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
List<Recording> recordings = new ArrayList<>();
JSONObject json = httpResponseToJson(response);
JSONArray array = (JSONArray) json.get("items");
array.forEach(item -> {
recordings.add(new Recording((JSONObject) item));
});
return recordings;
} else {
throw new OpenViduHttpException(statusCode);
try {
int statusCode = response.getStatusLine().getStatusCode();
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
List<Recording> recordings = new ArrayList<>();
JSONObject json = httpResponseToJson(response);
JSONArray array = (JSONArray) json.get("items");
array.forEach(item -> {
recordings.add(new Recording((JSONObject) item));
});
return recordings;
} else {
throw new OpenViduHttpException(statusCode);
}
} finally {
EntityUtils.consumeQuietly(response.getEntity());
}
}
@ -399,9 +435,105 @@ public class OpenVidu {
throw new OpenViduJavaClientException(e.getMessage(), e.getCause());
}
int statusCode = response.getStatusLine().getStatusCode();
if (!(statusCode == org.apache.http.HttpStatus.SC_NO_CONTENT)) {
throw new OpenViduHttpException(statusCode);
try {
int statusCode = response.getStatusLine().getStatusCode();
if (!(statusCode == org.apache.http.HttpStatus.SC_NO_CONTENT)) {
throw new OpenViduHttpException(statusCode);
}
} finally {
EntityUtils.consumeQuietly(response.getEntity());
}
}
/**
* Returns the list of active sessions. <strong>This value will remain unchanged
* since the last time method {@link io.openvidu.java.client.OpenVidu#fetch()}
* was called</strong>. Exceptions to this rule are:
* <ul>
* <li>Calling {@link io.openvidu.java.client.Session#fetch()} updates that
* specific Session status</li>
* <li>Calling {@link io.openvidu.java.client.Session#close()} automatically
* removes the Session from the list of active Sessions</li>
* <li>Calling
* {@link io.openvidu.java.client.Session#forceDisconnect(Connection)}
* automatically updates the inner affected connections for that specific
* Session</li>
* <li>Calling {@link io.openvidu.java.client.Session#forceUnpublish(Publisher)}
* also automatically updates the inner affected connections for that specific
* Session</li>
* </ul>
* <br>
* To get the list of active sessions with their current actual value, you must
* call first {@link io.openvidu.java.client.OpenVidu#fetch()} and then
* {@link io.openvidu.java.client.OpenVidu#getActiveSessions()}
*/
public List<Session> getActiveSessions() {
return new ArrayList<>(OpenVidu.activeSessions.values());
}
/**
* Updates every property of every active Session with the current status they
* have in OpenVidu Server. After calling this method you can acces the updated
* list of active sessions by calling
* {@link io.openvidu.java.client.OpenVidu#getActiveSessions()}
*
* @throws OpenViduHttpException
* @throws OpenViduJavaClientException
*/
@SuppressWarnings("unchecked")
public boolean fetch() throws OpenViduJavaClientException, OpenViduHttpException {
HttpGet request = new HttpGet(this.urlOpenViduServer + API_SESSIONS);
HttpResponse response;
try {
response = myHttpClient.execute(request);
} catch (IOException e) {
throw new OpenViduJavaClientException(e.getMessage(), e.getCause());
}
try {
int statusCode = response.getStatusLine().getStatusCode();
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
JSONObject jsonSessions = httpResponseToJson(response);
JSONArray jsonArraySessions = (JSONArray) jsonSessions.get("content");
// Set to store fetched sessionIds and later remove closed sessions
Set<String> fetchedSessionIds = new HashSet<>();
// Boolean to store if any Session has changed
boolean hasChanged = false;
jsonArraySessions.forEach(session -> {
String sessionId = (String) ((JSONObject) session).get("sessionId");
fetchedSessionIds.add(sessionId);
OpenVidu.activeSessions.computeIfPresent(sessionId, (sId, s) -> {
String beforeJSON = s.toJson();
s = s.resetSessionWithJson((JSONObject) session);
String afterJSON = s.toJson();
log.info("Available session '{}' info fetched. Any change: {}", sessionId,
!beforeJSON.equals(afterJSON));
return s;
});
OpenVidu.activeSessions.computeIfAbsent(sessionId, sId -> {
log.info("New session '{}' fetched", sessionId);
return new Session((JSONObject) session);
});
});
// Remove closed sessions from activeSessions map
OpenVidu.activeSessions = OpenVidu.activeSessions.entrySet().stream().filter(entry -> {
if (fetchedSessionIds.contains(entry.getKey())) {
return true;
} else {
log.info("Removing closed session {}" + entry.getKey());
return false;
}
}).collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));
log.info("Active sessions info fetched: {}", OpenVidu.activeSessions.keySet());
return hasChanged;
} else {
throw new OpenViduHttpException(statusCode);
}
} finally {
EntityUtils.consumeQuietly(response.getEntity());
}
}

View File

@ -17,6 +17,9 @@
package io.openvidu.java.client;
/**
* See {@link io.openvidu.java.client.TokenOptions.Builder#role(OpenViduRole)}
*/
public enum OpenViduRole {
/**
@ -25,13 +28,16 @@ public enum OpenViduRole {
SUBSCRIBER,
/**
* SUBSCRIBER permissions + can publish their own Streams (call <code>Session.publish()</code>)
* SUBSCRIBER permissions + can publish their own Streams (call
* <code>Session.publish()</code>)
*/
PUBLISHER,
/**
* SUBSCRIBER + PUBLISHER permissions + can force the unpublishing or disconnection over a third-party Stream or Connection
* (call <code>Session.forceUnpublish()</code> and <code>Session.forceDisconnect()</code>)
* SUBSCRIBER + PUBLISHER permissions + can force the unpublishing or
* disconnection over a third-party Stream or Connection (call
* <code>Session.forceUnpublish()</code> and
* <code>Session.forceDisconnect()</code>)
*/
MODERATOR;
}

View File

@ -0,0 +1,122 @@
/*
* (C) Copyright 2017-2018 OpenVidu (https://openvidu.io/)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package io.openvidu.java.client;
import org.json.simple.JSONObject;
/**
* See {@link io.openvidu.java.client.Connection#getPublishers()}
*/
public class Publisher {
class MediaOptions {
protected MediaOptions(boolean hasAudio, boolean hasVideo, Boolean audioActive, Boolean videoActive,
Integer frameRate, String typeOfVideo, String videoDimensions) {
this.hasAudio = hasAudio;
this.hasVideo = hasVideo;
this.audioActive = audioActive;
this.videoActive = videoActive;
this.frameRate = frameRate;
this.typeOfVideo = typeOfVideo;
this.videoDimensions = videoDimensions;
}
boolean hasVideo;
boolean hasAudio;
Boolean audioActive;
Boolean videoActive;
Integer frameRate;
String typeOfVideo;
String videoDimensions;
}
private String streamId;
private MediaOptions mediaOptions;
public Publisher(String streamId, boolean hasAudio, boolean hasVideo, Object audioActive, Object videoActive,
Object frameRate, Object typeOfVideo, Object videoDimensions) {
this.streamId = streamId;
Boolean audioActiveAux = null;
Boolean videoActiveAux = null;
Integer frameRateAux = null;
String typeOfVideoAux = null;
String videoDimensionsAux = null;
if (hasAudio) {
audioActiveAux = (boolean) audioActive;
}
if (hasVideo) {
videoActiveAux = (boolean) videoActive;
if (frameRate != null) {
frameRateAux = ((Long) frameRate).intValue();
}
typeOfVideoAux = (String) typeOfVideo;
videoDimensionsAux = (String) videoDimensions;
}
this.mediaOptions = new MediaOptions(hasAudio, hasVideo, audioActiveAux, videoActiveAux, frameRateAux,
typeOfVideoAux, videoDimensionsAux);
}
public String getStreamId() {
return streamId;
}
public boolean hasVideo() {
return this.mediaOptions.hasVideo;
}
public boolean hasAudio() {
return this.mediaOptions.hasAudio;
}
public Boolean isAudioActive() {
return this.mediaOptions.audioActive;
}
public Boolean isVideoActive() {
return this.mediaOptions.videoActive;
}
public Integer getFrameRate() {
return this.mediaOptions.frameRate;
}
public String getTypeOfVideo() {
return this.mediaOptions.typeOfVideo;
}
public String getVideoDimensions() {
return this.mediaOptions.videoDimensions;
}
@SuppressWarnings("unchecked")
protected JSONObject toJson() {
JSONObject json = new JSONObject();
json.put("streamId", this.streamId);
json.put("hasAudio", this.hasAudio());
json.put("hasVideo", this.hasVideo());
json.put("audioActive", this.isAudioActive());
json.put("videoActive", this.isVideoActive());
json.put("frameRate", this.getFrameRate());
json.put("typeOfVideo", this.getTypeOfVideo());
json.put("videoDimensions", this.getVideoDimensions());
return json;
}
}

View File

@ -19,8 +19,14 @@ package io.openvidu.java.client;
import org.json.simple.JSONObject;
/**
* See {@link io.openvidu.java.client.OpenVidu#startRecording(String)}
*/
public class Recording {
/**
* See {@link io.openvidu.java.client.Recording#getStatus()}
*/
public enum Status {
/**

View File

@ -17,6 +17,12 @@
package io.openvidu.java.client;
/**
* See
* {@link io.openvidu.java.client.SessionProperties.Builder#defaultRecordingLayout(RecordingLayout)}
* and
* {@link io.openvidu.java.client.RecordingProperties.Builder#recordingLayout(RecordingLayout)}
*/
public enum RecordingLayout {
/**

View File

@ -17,6 +17,10 @@
package io.openvidu.java.client;
/**
* See
* {@link io.openvidu.java.client.SessionProperties.Builder#recordingMode(RecordingMode)}
*/
public enum RecordingMode {
/**

View File

@ -17,17 +17,24 @@
package io.openvidu.java.client;
/**
* See
* {@link io.openvidu.java.client.OpenVidu#startRecording(String, RecordingProperties)}
*/
public class RecordingProperties {
private String name;
private RecordingLayout recordingLayout;
private String customLayout;
/**
* Builder for {@link io.openvidu.java.client.RecordingProperties}
*/
public static class Builder {
private String name = "";
private RecordingLayout recordingLayout;
private String customLayout;
private String customLayout = "";
/**
* Builder for {@link io.openvidu.java.client.RecordingProperties}

View File

@ -19,33 +19,43 @@ package io.openvidu.java.client;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Session {
private static final Logger log = LoggerFactory.getLogger(Session.class);
private HttpClient httpClient;
private String urlOpenViduServer;
private String sessionId;
private SessionProperties properties;
final static String API_SESSIONS = "api/sessions";
final static String API_TOKENS = "api/tokens";
private Map<String, Connection> activeConnections = new ConcurrentHashMap<>();
private boolean recording = false;
protected Session(HttpClient httpClient, String urlOpenViduServer)
throws OpenViduJavaClientException, OpenViduHttpException {
this.httpClient = httpClient;
this.urlOpenViduServer = urlOpenViduServer;
this.properties = new SessionProperties();
this.properties = new SessionProperties.Builder().build();
this.getSessionIdHttp();
}
@ -57,6 +67,10 @@ public class Session {
this.getSessionIdHttp();
}
protected Session(JSONObject json) {
this.resetSessionWithJson(json);
}
/**
* Gets the unique identifier of the Session
*
@ -97,7 +111,7 @@ public class Session {
this.getSessionId();
}
HttpPost request = new HttpPost(this.urlOpenViduServer + API_TOKENS);
HttpPost request = new HttpPost(this.urlOpenViduServer + OpenVidu.API_TOKENS);
JSONObject json = new JSONObject();
json.put("session", this.sessionId);
@ -120,12 +134,17 @@ public class Session {
throw new OpenViduJavaClientException(e2.getMessage(), e2.getCause());
}
int statusCode = response.getStatusLine().getStatusCode();
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
System.out.println("Returning a TOKEN");
return (String) httpResponseToJson(response).get("id");
} else {
throw new OpenViduHttpException(statusCode);
try {
int statusCode = response.getStatusLine().getStatusCode();
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
String token = (String) httpResponseToJson(response).get("id");
log.info("Returning a TOKEN: {}", token);
return token;
} else {
throw new OpenViduHttpException(statusCode);
}
} finally {
EntityUtils.consumeQuietly(response.getEntity());
}
}
@ -137,7 +156,7 @@ public class Session {
* @throws OpenViduHttpException
*/
public void close() throws OpenViduJavaClientException, OpenViduHttpException {
HttpDelete request = new HttpDelete(this.urlOpenViduServer + API_SESSIONS + "/" + this.sessionId);
HttpDelete request = new HttpDelete(this.urlOpenViduServer + OpenVidu.API_SESSIONS + "/" + this.sessionId);
request.setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
HttpResponse response;
@ -147,14 +166,236 @@ public class Session {
throw new OpenViduJavaClientException(e.getMessage(), e.getCause());
}
int statusCode = response.getStatusLine().getStatusCode();
if ((statusCode == org.apache.http.HttpStatus.SC_NO_CONTENT)) {
System.out.println("Session closed");
} else {
throw new OpenViduHttpException(statusCode);
try {
int statusCode = response.getStatusLine().getStatusCode();
if ((statusCode == org.apache.http.HttpStatus.SC_NO_CONTENT)) {
OpenVidu.activeSessions.remove(this.sessionId);
log.info("Session {} closed", this.sessionId);
} else {
throw new OpenViduHttpException(statusCode);
}
} finally {
EntityUtils.consumeQuietly(response.getEntity());
}
}
/**
* Updates every property of the Session with the current status it has in
* OpenVidu Server. This is especially useful for getting the list of active
* connections to the Session
* ({@link io.openvidu.java.client.Session#getActiveConnections()}) and use
* those values to call
* {@link io.openvidu.java.client.Session#forceDisconnect(String)} or
* {@link io.openvidu.java.client.Session#forceUnpublish(String)}
*
* @return true if the Session status has changed with respect to the server,
* false if not. This applies to any property or sub-property of the
* object
*
* @throws OpenViduHttpException
* @throws OpenViduJavaClientException
*/
public boolean fetch() throws OpenViduJavaClientException, OpenViduHttpException {
String beforeJSON = this.toJson();
HttpGet request = new HttpGet(this.urlOpenViduServer + OpenVidu.API_SESSIONS + "/" + this.sessionId);
request.setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
HttpResponse response;
try {
response = httpClient.execute(request);
} catch (IOException e) {
throw new OpenViduJavaClientException(e.getMessage(), e.getCause());
}
try {
int statusCode = response.getStatusLine().getStatusCode();
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
this.resetSessionWithJson(httpResponseToJson(response));
String afterJSON = this.toJson();
boolean hasChanged = !beforeJSON.equals(afterJSON);
log.info("Session info fetched for session '{}'. Any change: {}", this.sessionId, hasChanged);
return hasChanged;
} else {
throw new OpenViduHttpException(statusCode);
}
} finally {
EntityUtils.consumeQuietly(response.getEntity());
}
}
/**
* Forces the user represented by <code>connection</code> to leave the session.
* OpenVidu Browser will trigger the proper events on the client-side
* (<code>streamDestroyed</code>, <code>connectionDestroyed</code>,
* <code>sessionDisconnected</code>) with reason set to
* "forceDisconnectByServer" <br>
*
* You can get <code>connection</code> parameter with
* {@link io.openvidu.java.client.Session#fetch()} and then
* {@link io.openvidu.java.client.Session#getActiveConnections()}
*
* @throws OpenViduJavaClientException
* @throws OpenViduHttpException
*/
public void forceDisconnect(Connection connection) throws OpenViduJavaClientException, OpenViduHttpException {
this.forceDisconnect(connection.getConnectionId());
}
/**
* Forces the user with Connection <code>connectionId</code> to leave the
* session. OpenVidu Browser will trigger the proper events on the client-side
* (<code>streamDestroyed</code>, <code>connectionDestroyed</code>,
* <code>sessionDisconnected</code>) with reason set to
* "forceDisconnectByServer" <br>
*
* You can get <code>connectionId</code> parameter with
* {@link io.openvidu.java.client.Session#fetch()} (use
* {@link io.openvidu.java.client.Connection#getConnectionId()} to get the
* `connectionId` you want)
*
* @throws OpenViduJavaClientException
* @throws OpenViduHttpException
*/
public void forceDisconnect(String connectionId) throws OpenViduJavaClientException, OpenViduHttpException {
HttpDelete request = new HttpDelete(
this.urlOpenViduServer + OpenVidu.API_SESSIONS + "/" + this.sessionId + "/connection/" + connectionId);
request.setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
HttpResponse response = null;
try {
response = httpClient.execute(request);
} catch (IOException e) {
throw new OpenViduJavaClientException(e.getMessage(), e.getCause());
}
try {
int statusCode = response.getStatusLine().getStatusCode();
if ((statusCode == org.apache.http.HttpStatus.SC_NO_CONTENT)) {
// Remove connection from activeConnections map
Connection connectionClosed = this.activeConnections.remove(connectionId);
// Remove every Publisher of the closed connection from every subscriber list of
// other connections
if (connectionClosed != null) {
for (Publisher publisher : connectionClosed.getPublishers()) {
this.removeSubscribersForPublisher(publisher);
}
} else {
log.warn(
"The closed connection wasn't fetched in OpenVidu Java Client. No changes in the collection of active connections of the Session");
}
log.info("Connection {} closed", connectionId);
} else {
throw new OpenViduHttpException(statusCode);
}
} finally
{
EntityUtils.consumeQuietly(response.getEntity());
}
}
/**
* Forces some user to unpublish a Stream. OpenVidu Browser will trigger the
* proper events on the client-side (<code>streamDestroyed</code>) with reason
* set to "forceUnpublishByServer".<br>
*
* You can get <code>publisher</code> parameter with
* {@link io.openvidu.java.client.Session#getActiveConnections()} and then for
* each Connection you can call
* {@link io.openvidu.java.client.Connection#getPublishers()}. Remember to call
* {@link io.openvidu.java.client.Session#fetch()} before to fetch the current
* actual properties of the Session from OpenVidu Server
*
* @throws OpenViduJavaClientException
* @throws OpenViduHttpException
*/
public void forceUnpublish(Publisher publisher) throws OpenViduJavaClientException, OpenViduHttpException {
this.forceUnpublish(publisher.getStreamId());
}
/**
* Forces some user to unpublish a Stream. OpenVidu Browser will trigger the
* proper events on the client-side (<code>streamDestroyed</code>) with reason
* set to "forceUnpublishByServer". <br>
*
* You can get <code>streamId</code> parameter with
* {@link io.openvidu.java.client.Session#getActiveConnections()} and then for
* each Connection you can call
* {@link io.openvidu.java.client.Connection#getPublishers()}. Finally
* {@link io.openvidu.java.client.Publisher#getStreamId()}) will give you the
* <code>streamId</code>. Remember to call
* {@link io.openvidu.java.client.Session#fetch()} before to fetch the current
* actual properties of the Session from OpenVidu Server
*
* @throws OpenViduJavaClientException
* @throws OpenViduHttpException
*/
public void forceUnpublish(String streamId) throws OpenViduJavaClientException, OpenViduHttpException {
HttpDelete request = new HttpDelete(
this.urlOpenViduServer + OpenVidu.API_SESSIONS + "/" + this.sessionId + "/stream/" + streamId);
request.setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
HttpResponse response;
try {
response = httpClient.execute(request);
} catch (IOException e) {
throw new OpenViduJavaClientException(e.getMessage(), e.getCause());
}
try {
int statusCode = response.getStatusLine().getStatusCode();
if ((statusCode == org.apache.http.HttpStatus.SC_NO_CONTENT)) {
for (Connection connection : this.activeConnections.values()) {
// Try to remove the Publisher from the Connection publishers collection
if (connection.publishers.remove(streamId) != null) {
continue;
}
// Try to remove the Publisher from the Connection subscribers collection
connection.subscribers.remove(streamId);
}
log.info("Stream {} unpublished", streamId);
} else {
throw new OpenViduHttpException(statusCode);
}
} finally {
EntityUtils.consumeQuietly(response.getEntity());
}
}
/**
* Returns the list of active connections to the session. <strong>This value
* will remain unchanged since the last time method
* {@link io.openvidu.java.client.Session#fetch()} was called</strong>.
* Exceptions to this rule are:
* <ul>
* <li>Calling {@link io.openvidu.java.client.Session#forceUnpublish(String)}
* updates each affected Connection status</li>
* <li>Calling {@link io.openvidu.java.client.Session#forceDisconnect(String)}
* updates each affected Connection status</li>
* </ul>
* <br>
* To get the list of active connections with their current actual value, you
* must call first {@link io.openvidu.java.client.Session#fetch()} and then
* {@link io.openvidu.java.client.Session#getActiveConnections()}
*/
public List<Connection> getActiveConnections() {
return new ArrayList<>(this.activeConnections.values());
}
/**
* Returns whether the session is being recorded or not. <strong>This value will
* be the same as the one that returned method
* {@link io.openvidu.java.client.Session#fetch()} the last time it was
* called.</strong>
*
* To get the current actual value, you must call first
* {@link io.openvidu.java.client.Session#fetch()} and then
* {@link io.openvidu.java.client.Session#isBeingRecorded()}
*/
public boolean isBeingRecorded() {
return this.recording;
}
/**
* Returns the properties defining the session
*/
@ -177,7 +418,7 @@ public class Session {
return;
}
HttpPost request = new HttpPost(this.urlOpenViduServer + API_SESSIONS);
HttpPost request = new HttpPost(this.urlOpenViduServer + OpenVidu.API_SESSIONS);
JSONObject json = new JSONObject();
json.put("mediaMode", properties.mediaMode().name());
@ -201,16 +442,20 @@ public class Session {
} catch (IOException e2) {
throw new OpenViduJavaClientException(e2.getMessage(), e2.getCause());
}
int statusCode = response.getStatusLine().getStatusCode();
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
System.out.println("Returning a SESSIONID");
String id = (String) httpResponseToJson(response).get("id");
this.sessionId = id;
} else if (statusCode == org.apache.http.HttpStatus.SC_CONFLICT) {
// 'customSessionId' already existed
this.sessionId = properties.customSessionId();
} else {
throw new OpenViduHttpException(statusCode);
try {
int statusCode = response.getStatusLine().getStatusCode();
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
String id = (String) httpResponseToJson(response).get("id");
log.info("Returning a SESSIONID: {}", id);
this.sessionId = id;
} else if (statusCode == org.apache.http.HttpStatus.SC_CONFLICT) {
// 'customSessionId' already existed
this.sessionId = properties.customSessionId();
} else {
throw new OpenViduHttpException(statusCode);
}
} finally {
EntityUtils.consumeQuietly(response.getEntity());
}
}
@ -225,4 +470,95 @@ public class Session {
return json;
}
private void removeSubscribersForPublisher(Publisher publisher) {
String streamId = publisher.getStreamId();
for (Connection connection : this.activeConnections.values()) {
connection.setSubscribers(connection.getSubscribers().stream()
.filter(subscriber -> !streamId.equals(subscriber)).collect(Collectors.toList()));
}
}
@SuppressWarnings("unchecked")
protected Session resetSessionWithJson(JSONObject json) {
this.sessionId = (String) json.get("sessionId");
this.recording = (boolean) json.get("recording");
SessionProperties.Builder builder = new SessionProperties.Builder()
.mediaMode(MediaMode.valueOf((String) json.get("mediaMode")))
.recordingMode(RecordingMode.valueOf((String) json.get("recordingMode")))
.defaultRecordingLayout(RecordingLayout.valueOf((String) json.get("defaultRecordingLayout")));
if (json.containsKey("defaultCustomLayout")) {
builder.defaultCustomLayout((String) json.get("defaultCustomLayout"));
}
if (this.properties != null && this.properties.customSessionId() != null) {
builder.customSessionId(this.properties.customSessionId());
}
this.properties = builder.build();
JSONArray jsonArrayConnections = (JSONArray) ((JSONObject) json.get("connections")).get("content");
this.activeConnections.clear();
jsonArrayConnections.forEach(connection -> {
JSONObject con = (JSONObject) connection;
Map<String, Publisher> publishers = new ConcurrentHashMap<>();
JSONArray jsonArrayPublishers = (JSONArray) con.get("publishers");
jsonArrayPublishers.forEach(publisher -> {
JSONObject pubJson = (JSONObject) publisher;
JSONObject mediaOptions = (JSONObject) pubJson.get("mediaOptions");
Publisher pub = new Publisher((String) pubJson.get("streamId"), (boolean) mediaOptions.get("hasAudio"),
(boolean) mediaOptions.get("hasVideo"), mediaOptions.get("audioActive"),
mediaOptions.get("videoActive"), mediaOptions.get("frameRate"), mediaOptions.get("typeOfVideo"),
mediaOptions.get("videoDimensions"));
publishers.put(pub.getStreamId(), pub);
});
List<String> subscribers = new ArrayList<>();
JSONArray jsonArraySubscribers = (JSONArray) con.get("subscribers");
jsonArraySubscribers.forEach(subscriber -> {
subscribers.add((String) ((JSONObject) subscriber).get("streamId"));
});
this.activeConnections.put((String) con.get("connectionId"),
new Connection((String) con.get("connectionId"), OpenViduRole.valueOf((String) con.get("role")),
(String) con.get("token"), (String) con.get("serverData"), (String) con.get("clientData"),
publishers, subscribers));
});
return this;
}
@SuppressWarnings("unchecked")
protected String toJson() {
JSONObject json = new JSONObject();
json.put("sessionId", this.sessionId);
json.put("customSessionId", this.properties.customSessionId());
json.put("recording", this.recording);
json.put("mediaMode", this.properties.mediaMode());
json.put("recordingMode", this.properties.recordingMode());
json.put("defaultRecordingLayout", this.properties.defaultRecordingLayout());
json.put("defaultCustomLayout", this.properties.defaultCustomLayout());
JSONObject connections = new JSONObject();
connections.put("numberOfElements", this.getActiveConnections().size());
JSONArray jsonArrayConnections = new JSONArray();
this.getActiveConnections().forEach(con -> {
JSONObject c = new JSONObject();
c.put("connectionId", con.getConnectionId());
c.put("role", con.getRole());
c.put("token", con.getToken());
c.put("clientData", con.getClientData());
c.put("serverData", con.getServerData());
JSONArray pubs = new JSONArray();
con.getPublishers().forEach(p -> {
pubs.add(p.toJson());
});
JSONArray subs = new JSONArray();
con.getSubscribers().forEach(s -> {
subs.add(s);
});
c.put("publishers", pubs);
c.put("subscribers", subs);
jsonArrayConnections.add(c);
});
connections.put("content", jsonArrayConnections);
json.put("connections", connections);
return json.toJSONString();
}
}

View File

@ -17,6 +17,9 @@
package io.openvidu.java.client;
/**
* See {@link io.openvidu.java.client.OpenVidu#createSession(SessionProperties)}
*/
public class SessionProperties {
private MediaMode mediaMode;

View File

@ -17,6 +17,9 @@
package io.openvidu.java.client;
/**
* See {@link io.openvidu.java.client.Session#generateToken(TokenOptions)}
*/
public class TokenOptions {
private String data;

View File

@ -358,8 +358,10 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
if (this.sessionEvents.sessionDisconnected) {
this.session.on('sessionDisconnected', (event: SessionDisconnectedEvent) => {
this.updateEventList('sessionDisconnected', 'No data');
this.session = null;
this.OV = null;
this.subscribers = [];
delete this.publisher;
delete this.session;
delete this.OV;
});
}
}