diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Archive.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Archive.java new file mode 100644 index 00000000..8eb316c3 --- /dev/null +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Archive.java @@ -0,0 +1,81 @@ +package io.openvidu.java.client; + +import org.json.simple.JSONObject; + +public class Archive { + + public enum Status { + starting, // The recording is starting (cannot be stopped) + started, // The recording has started and is going on + stopped, // The recording has finished OK + available, // The recording is available for downloading. This status is reached for all + // stopped recordings if property 'openvidu.recording.free-access' is true + failed; // The recording has failed + } + + private Archive.Status status; + + private String id; + private String name; + private String sessionId; + private long createdAt; // milliseconds (UNIX Epoch time) + private long size = 0; // bytes + private double duration = 0; // seconds + private String url; + private boolean hasAudio = true; + private boolean hasVideo = true; + + public Archive(JSONObject json) { + this.id = (String) json.get("id"); + this.name = (String) json.get("name"); + this.sessionId = (String) json.get("sessionId"); + this.createdAt = (long) json.get("createdAt"); + this.size = (long) json.get("size"); + this.duration = (double) json.get("duration"); + this.url = (String) json.get("url"); + this.hasAudio = (boolean) json.get("hasAudio"); + this.hasVideo = (boolean) json.get("hasVideo"); + this.status = Archive.Status.valueOf((String) json.get("status")); + } + + public Archive.Status getStatus() { + return status; + } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public String getSessionId() { + return sessionId; + } + + public long getCreatedAt() { + return createdAt; + } + + public long getSize() { + return size; + } + + public double getDuration() { + return duration; + } + + public String getUrl() { + return url; + } + + public boolean hasAudio() { + return hasAudio; + } + + public boolean hasVideo() { + return hasVideo; + } + +} diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java index 9bed7c42..46a4dcaa 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java @@ -1,18 +1,38 @@ package io.openvidu.java.client; +import java.io.IOException; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; +import javax.net.ssl.SSLContext; + +import org.apache.http.HttpHeaders; +import org.apache.http.HttpResponse; 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.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.conn.ssl.TrustSelfSignedStrategy; +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.ssl.SSLContextBuilder; +import org.apache.http.ssl.TrustStrategy; +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 io.openvidu.java.client.OpenViduException.Code; public class OpenVidu { @@ -20,51 +40,155 @@ public class OpenVidu { private String secret; private HttpClient myHttpClient; - public OpenVidu(String urlOpenViduServer, String secret) { - - this.urlOpenViduServer = urlOpenViduServer; - - if (!this.urlOpenViduServer.endsWith("/")){ - this.urlOpenViduServer += "/"; - } + final static String API_RECORDINGS = "api/recordings"; + final static String API_RECORDINGS_START = "/start"; + final static String API_RECORDINGS_STOP = "/stop"; - this.secret = secret; - - CredentialsProvider provider = new BasicCredentialsProvider(); - UsernamePasswordCredentials credentials = new UsernamePasswordCredentials("OPENVIDUAPP", this.secret); - provider.setCredentials(AuthScope.ANY, credentials); - - SSLContextBuilder builder = new SSLContextBuilder(); - try { - builder.loadTrustMaterial(null, new TrustSelfSignedStrategy()); - SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build(), - SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); - /*SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( - builder.build());*/ - this.myHttpClient = HttpClients.custom().setSSLSocketFactory( - sslsf).setDefaultCredentialsProvider(provider).build(); - } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + public OpenVidu(String urlOpenViduServer, String secret) { + + this.urlOpenViduServer = urlOpenViduServer; + + if (!this.urlOpenViduServer.endsWith("/")) { + this.urlOpenViduServer += "/"; + } + + this.secret = secret; + + TrustStrategy trustStrategy = new TrustStrategy() { + @Override + public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException { + return true; } - } - - public Session createSession() throws OpenViduException { - Session s = new Session(myHttpClient, urlOpenViduServer); - return s; - } - - public Session createSession(SessionProperties properties) throws OpenViduException { - Session s = new Session(myHttpClient, urlOpenViduServer, properties); - return s; - } - - public void startRecording(String sessionId) { - // TODO: REST POST to start recording in OpenVidu Server - } - - public void stopRecording(String sessionId) { - // TODO: REST POST to end recording in OpenVidu Server - } - + }; + + CredentialsProvider provider = new BasicCredentialsProvider(); + UsernamePasswordCredentials credentials = new UsernamePasswordCredentials("OPENVIDUAPP", this.secret); + provider.setCredentials(AuthScope.ANY, credentials); + + SSLContext sslContext; + + try { + sslContext = new SSLContextBuilder().loadTrustMaterial(null, trustStrategy).build(); + } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) { + throw new RuntimeException(e); + } + + this.myHttpClient = HttpClients.custom().setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) + .setSSLContext(sslContext).setDefaultCredentialsProvider(provider).build(); + + } + + public Session createSession() throws OpenViduException { + Session s = new Session(myHttpClient, urlOpenViduServer); + return s; + } + + public Session createSession(SessionProperties properties) throws OpenViduException { + Session s = new Session(myHttpClient, urlOpenViduServer, properties); + return s; + } + + @SuppressWarnings("unchecked") + public Archive startRecording(String sessionId) throws OpenViduException { + try { + HttpPost request = new HttpPost(this.urlOpenViduServer + API_RECORDINGS + API_RECORDINGS_START); + + JSONObject json = new JSONObject(); + json.put("session", sessionId); + StringEntity params = new StringEntity(json.toString()); + + request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json"); + request.setEntity(params); + + HttpResponse response = myHttpClient.execute(request); + + int statusCode = response.getStatusLine().getStatusCode(); + if ((statusCode == org.apache.http.HttpStatus.SC_OK)) { + return new Archive(OpenVidu.httpResponseToJson(response)); + } else { + throw new OpenViduException(Code.RECORDING_START_ERROR_CODE, Integer.toString(statusCode)); + } + } catch (Exception e) { + throw new OpenViduException(Code.RECORDING_START_ERROR_CODE, + "Unable to start recording for session '" + sessionId + "': " + e.getMessage()); + } + } + + public Archive stopRecording(String recordingId) throws OpenViduException { + try { + HttpPost request = new HttpPost( + this.urlOpenViduServer + API_RECORDINGS + API_RECORDINGS_STOP + "/" + recordingId); + HttpResponse response = myHttpClient.execute(request); + + int statusCode = response.getStatusLine().getStatusCode(); + if ((statusCode == org.apache.http.HttpStatus.SC_OK)) { + return new Archive(OpenVidu.httpResponseToJson(response)); + } else { + throw new OpenViduException(Code.RECORDING_STOP_ERROR_CODE, Integer.toString(statusCode)); + } + } catch (Exception e) { + throw new OpenViduException(Code.RECORDING_STOP_ERROR_CODE, + "Unable to stop recording '" + recordingId + "': " + e.getMessage()); + } + } + + public Archive getRecording(String recordingId) throws OpenViduException { + try { + HttpGet request = new HttpGet(this.urlOpenViduServer + API_RECORDINGS + "/" + recordingId); + HttpResponse response = myHttpClient.execute(request); + + int statusCode = response.getStatusLine().getStatusCode(); + if ((statusCode == org.apache.http.HttpStatus.SC_OK)) { + return new Archive(OpenVidu.httpResponseToJson(response)); + } else { + throw new OpenViduException(Code.RECORDING_LIST_ERROR_CODE, Integer.toString(statusCode)); + } + } catch (Exception e) { + throw new OpenViduException(Code.RECORDING_LIST_ERROR_CODE, "Unable to get recording '" + recordingId + "': " + e.getMessage()); + } + } + + @SuppressWarnings("unchecked") + public List listRecordings() throws OpenViduException { + try { + HttpGet request = new HttpGet(this.urlOpenViduServer + API_RECORDINGS); + HttpResponse response = myHttpClient.execute(request); + + int statusCode = response.getStatusLine().getStatusCode(); + if ((statusCode == org.apache.http.HttpStatus.SC_OK)) { + List archives = new ArrayList<>(); + JSONObject json = OpenVidu.httpResponseToJson(response); + JSONArray array = (JSONArray) json.get("items"); + array.forEach(item -> { + archives.add(new Archive((JSONObject) item)); + }); + return archives; + } else { + throw new OpenViduException(Code.RECORDING_LIST_ERROR_CODE, Integer.toString(statusCode)); + } + } catch (Exception e) { + throw new OpenViduException(Code.RECORDING_LIST_ERROR_CODE, "Unable to list recordings: " + e.getMessage()); + } + } + + public void deleteRecording(String recordingId) throws OpenViduException { + try { + HttpDelete request = new HttpDelete(this.urlOpenViduServer + API_RECORDINGS + "/" + recordingId); + HttpResponse response = myHttpClient.execute(request); + + int statusCode = response.getStatusLine().getStatusCode(); + if (!(statusCode == org.apache.http.HttpStatus.SC_NO_CONTENT)) { + throw new OpenViduException(Code.RECORDING_DELETE_ERROR_CODE, Integer.toString(statusCode)); + } + } catch (Exception e) { + throw new OpenViduException(Code.RECORDING_DELETE_ERROR_CODE, + "Unable to delete recording '" + recordingId + "': " + e.getMessage()); + } + } + + public static JSONObject httpResponseToJson(HttpResponse response) throws ParseException, IOException { + JSONParser parser = new JSONParser(); + return (JSONObject) parser.parse(EntityUtils.toString(response.getEntity())); + } + } diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenViduException.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenViduException.java index 0b3e7d6e..156d3164 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenViduException.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenViduException.java @@ -18,60 +18,64 @@ package io.openvidu.java.client; public class OpenViduException extends RuntimeException { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - public static enum Code { - GENERIC_ERROR_CODE(999), + public static enum Code { + GENERIC_ERROR_CODE(999), - TRANSPORT_ERROR_CODE(803), TRANSPORT_RESPONSE_ERROR_CODE(802), TRANSPORT_REQUEST_ERROR_CODE( - 801), + TRANSPORT_ERROR_CODE(803), TRANSPORT_RESPONSE_ERROR_CODE(802), TRANSPORT_REQUEST_ERROR_CODE(801), - MEDIA_MUTE_ERROR_CODE(307), MEDIA_NOT_A_WEB_ENDPOINT_ERROR_CODE( - 306), MEDIA_RTP_ENDPOINT_ERROR_CODE(305), MEDIA_WEBRTC_ENDPOINT_ERROR_CODE( - 304), MEDIA_ENDPOINT_ERROR_CODE( - 303), MEDIA_SDP_ERROR_CODE(302), MEDIA_GENERIC_ERROR_CODE(301), + MEDIA_MUTE_ERROR_CODE(307), MEDIA_NOT_A_WEB_ENDPOINT_ERROR_CODE(306), MEDIA_RTP_ENDPOINT_ERROR_CODE( + 305), MEDIA_WEBRTC_ENDPOINT_ERROR_CODE( + 304), MEDIA_ENDPOINT_ERROR_CODE(303), MEDIA_SDP_ERROR_CODE(302), MEDIA_GENERIC_ERROR_CODE(301), - ROOM_CANNOT_BE_CREATED_ERROR_CODE(204), ROOM_CLOSED_ERROR_CODE(203), ROOM_NOT_FOUND_ERROR_CODE( - 202), ROOM_GENERIC_ERROR_CODE(201), + ROOM_CANNOT_BE_CREATED_ERROR_CODE(204), ROOM_CLOSED_ERROR_CODE(203), ROOM_NOT_FOUND_ERROR_CODE( + 202), ROOM_GENERIC_ERROR_CODE(201), - USER_NOT_STREAMING_ERROR_CODE(105), EXISTING_USER_IN_ROOM_ERROR_CODE( - 104), USER_CLOSED_ERROR_CODE( - 103), USER_NOT_FOUND_ERROR_CODE(102), USER_GENERIC_ERROR_CODE(101), - - USER_UNAUTHORIZED_ERROR_CODE(401), ROLE_NOT_FOUND_ERROR_CODE(402), - SESSIONID_CANNOT_BE_CREATED_ERROR_CODE(403), TOKEN_CANNOT_BE_CREATED_ERROR_CODE(404), - - USER_METADATA_FORMAT_INVALID_ERROR_CODE(500); + USER_NOT_STREAMING_ERROR_CODE(105), EXISTING_USER_IN_ROOM_ERROR_CODE(104), USER_CLOSED_ERROR_CODE( + 103), USER_NOT_FOUND_ERROR_CODE(102), USER_GENERIC_ERROR_CODE(101), - private int value; + USER_UNAUTHORIZED_ERROR_CODE(401), ROLE_NOT_FOUND_ERROR_CODE(402), SESSIONID_CANNOT_BE_CREATED_ERROR_CODE( + 403), TOKEN_CANNOT_BE_CREATED_ERROR_CODE(404), - private Code(int value) { - this.value = value; - } + USER_METADATA_FORMAT_INVALID_ERROR_CODE(500), - public int getValue() { - return this.value; - } - } + SIGNAL_FORMAT_INVALID_ERROR_CODE(600), SIGNAL_TO_INVALID_ERROR_CODE(601), SIGNAL_MESSAGE_INVALID_ERROR_CODE( + 602), - private Code code = Code.GENERIC_ERROR_CODE; + RECORDING_FILE_EMPTY_ERROR(707), RECORDING_DELETE_ERROR_CODE(706), RECORDING_LIST_ERROR_CODE( + 705), RECORDING_STOP_ERROR_CODE(704), RECORDING_START_ERROR_CODE( + 703), RECORDING_REPORT_ERROR_CODE(702), RECORDING_COMPLETION_ERROR_CODE(701); - public OpenViduException(Code code, String message) { - super(message); - this.code = code; - } + private int value; - public Code getCode() { - return code; - } + private Code(int value) { + this.value = value; + } - public int getCodeValue() { - return code.getValue(); - } + public int getValue() { + return this.value; + } + } - @Override - public String toString() { - return "Code: " + getCodeValue() + " " + super.toString(); - } + private Code code = Code.GENERIC_ERROR_CODE; + + public OpenViduException(Code code, String message) { + super(message); + this.code = code; + } + + public Code getCode() { + return code; + } + + public int getCodeValue() { + return code.getValue(); + } + + @Override + public String toString() { + return "Code: " + getCodeValue() + " " + super.toString(); + } } diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java index d027c98f..48576048 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java @@ -1,16 +1,11 @@ package io.openvidu.java.client; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; - +import org.apache.http.HttpHeaders; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; import io.openvidu.java.client.OpenViduException.Code; @@ -20,6 +15,9 @@ public class Session { private String urlOpenViduServer; private String sessionId; private SessionProperties properties; + + final static String API_SESSIONS = "api/sessions"; + final static String API_TOKENS = "api/tokens"; protected Session(HttpClient httpClient, String urlOpenViduServer) throws OpenViduException { this.httpClient = httpClient; @@ -35,6 +33,7 @@ public class Session { this.sessionId = this.getSessionId(); } + @SuppressWarnings("unchecked") public String getSessionId() throws OpenViduException { if (this.hasSessionId()) { @@ -42,15 +41,15 @@ public class Session { } try { + HttpPost request = new HttpPost(this.urlOpenViduServer + API_SESSIONS); JSONObject json = new JSONObject(); - json.put("archiveMode", properties.archiveMode().name()); json.put("archiveLayout", properties.archiveLayout().name()); + json.put("archiveMode", properties.archiveMode().name()); json.put("mediaMode", properties.mediaMode().name()); - - HttpPost request = new HttpPost(this.urlOpenViduServer + "api/sessions"); StringEntity params = new StringEntity(json.toString()); - request.addHeader("content-type", "application/json"); + + request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json"); request.setEntity(params); HttpResponse response = httpClient.execute(request); @@ -58,7 +57,7 @@ public class Session { if ((statusCode == org.apache.http.HttpStatus.SC_OK)) { System.out.println("Returning a SESSIONID"); String id = ""; - id = this.httpResponseToString(response); + id = (String) OpenVidu.httpResponseToJson(response).get("id"); this.sessionId = id; return id; } else { @@ -75,6 +74,7 @@ public class Session { return this.generateToken(new TokenOptions.Builder().role(OpenViduRole.PUBLISHER).build()); } + @SuppressWarnings("unchecked") public String generateToken(TokenOptions tokenOptions) throws OpenViduException { if (!this.hasSessionId()) { @@ -82,15 +82,15 @@ public class Session { } try { - + HttpPost request = new HttpPost(this.urlOpenViduServer + API_TOKENS); + JSONObject json = new JSONObject(); json.put("session", this.sessionId); json.put("role", tokenOptions.getRole().name()); json.put("data", tokenOptions.getData()); - - HttpPost request = new HttpPost(this.urlOpenViduServer + "api/tokens"); StringEntity params = new StringEntity(json.toString()); - request.addHeader("content-type", "application/json"); + + request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json"); request.setEntity(params); HttpResponse response = httpClient.execute(request); @@ -98,7 +98,7 @@ public class Session { int statusCode = response.getStatusLine().getStatusCode(); if ((statusCode == org.apache.http.HttpStatus.SC_OK)) { System.out.println("Returning a TOKEN"); - return this.httpResponseToString(response); + return (String) OpenVidu.httpResponseToJson(response).get("id"); } else { throw new OpenViduException(Code.TOKEN_CANNOT_BE_CREATED_ERROR_CODE, Integer.toString(statusCode)); } @@ -118,17 +118,6 @@ public class Session { return this.sessionId; } - private String httpResponseToString(HttpResponse response) throws IOException, ParseException { - BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); - StringBuffer buf = new StringBuffer(); - String line = ""; - while ((line = rd.readLine()) != null) { - buf.append(line); - } - JSONParser parser = new JSONParser(); - return ((String) ((JSONObject) parser.parse(buf.toString())).get("id")); - } - private boolean hasSessionId() { return (this.sessionId != null && !this.sessionId.isEmpty()); }