Skip to content

Commit

Permalink
Added support for describing archive layouts for composed archives, a…
Browse files Browse the repository at this point in the history
…ddresses #131 (#134)

* adding support for custom styling of composed archives.

* added tests and javadoc

* added nullcheck for layout in httpclient

* corrected test names

* added missing license header to ArchiveLayout
  • Loading branch information
tonycapone authored and aiham committed Sep 13, 2017
1 parent caf6cc7 commit 77f5c8a
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 11 deletions.
66 changes: 66 additions & 0 deletions src/main/java/com/opentok/ArchiveLayout.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/**
* OpenTok Java SDK
* Copyright (C) 2017 TokBox, Inc.
* http://www.tokbox.com
*
* Licensed under The MIT License (MIT). See LICENSE file for more information.
*/
package com.opentok;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonValue;

/**
* Represents a <a href="https://tokbox.com/developer/guides/archiving/layout-control.html">layout configuration</a>
* for a composed archive
*/
@JsonFormat(shape= JsonFormat.Shape.OBJECT)
public class ArchiveLayout {
private Type type;
private String stylesheet;

public ArchiveLayout(Type type, String stylesheet) {
this.type = type;
this.stylesheet = stylesheet;
}

public ArchiveLayout(Type type) {
this.type = type;
}

public enum Type {
PIP("pip"),
BESTFIT("bestFit"),
VERTICAL("verticalPresentation"),
HORIZONTAL("horizontalPresentation"),
CUSTOM("custom");

private String serialized;

private Type(String s) {
serialized = s;
}

@JsonValue
public String toString() {
return super.toString().toLowerCase();
}
}

public Type getType() {
return type;
}

public void setType(Type type) {
this.type = type;
}

public String getStylesheet() {
return stylesheet;
}

public void setStylesheet(String stylesheet) {
this.stylesheet = stylesheet;
}

}
27 changes: 27 additions & 0 deletions src/main/java/com/opentok/ArchiveProperties.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@ public class ArchiveProperties {
private boolean hasAudio;
private boolean hasVideo;
private OutputMode outputMode;
private ArchiveLayout layout;

private ArchiveProperties(Builder builder) {
this.name = builder.name;
this.hasAudio = builder.hasAudio;
this.hasVideo = builder.hasVideo;
this.outputMode = builder.outputMode;
this.layout = builder.layout;
}

/**
Expand All @@ -46,6 +48,7 @@ public static class Builder {
private boolean hasAudio = true;
private boolean hasVideo = true;
private OutputMode outputMode = OutputMode.COMPOSED;
private ArchiveLayout layout = new ArchiveLayout(ArchiveLayout.Type.BESTFIT);


/**
Expand Down Expand Up @@ -97,6 +100,18 @@ public Builder outputMode(OutputMode outputMode) {
return this;
}

/**
* Call this method to customize the layout for a composed archive
*
* @param layout An object of type {@link ArchiveLayout} .
*
* @return The ArchiveProperties.Builder object with the output mode setting.
*/
public Builder layout(ArchiveLayout layout){
this.layout = layout;
return this;
}

/**
* Builds the ArchiveProperties object.
*
Expand Down Expand Up @@ -133,6 +148,13 @@ public OutputMode outputMode() {
return outputMode;
}

/**
* Optionally set a custom layout (composed archives only)
*/
public ArchiveLayout layout() {
return layout;
}

/**
* Returns the archive properties as a Map.
*/
Expand All @@ -155,6 +177,11 @@ public Map<String, Collection<String>> toMap() {
valueList.add(outputMode.toString());
params.put("outputMode", valueList);

valueList = new ArrayList<String>();
valueList.add(layout.toString());
params.put("layout", valueList);


return params;
}

Expand Down
5 changes: 5 additions & 0 deletions src/main/java/com/opentok/Session.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.util.Random;
import java.util.stream.Collectors;

import com.opentok.exception.InvalidArgumentException;
import com.opentok.util.Crypto;
Expand Down Expand Up @@ -129,6 +130,10 @@ public String generateToken(TokenOptions tokenOptions) throws OpenTokException {
dataStringBuilder.append(nonce);
dataStringBuilder.append("&role=");
dataStringBuilder.append(role);
if(tokenOptions.getInitialLayoutClassList() != null ){
dataStringBuilder.append("&initial_layout_class_list=");
dataStringBuilder.append(tokenOptions.getInitialLayoutClassList().stream().collect(Collectors.joining(" ")));
}

double now = System.currentTimeMillis() / 1000L;
if (expireTime == 0) {
Expand Down
6 changes: 5 additions & 1 deletion src/main/java/com/opentok/util/HttpClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,11 @@ public String startArchive(String sessionId, ArchiveProperties properties)
requestJson.put("hasVideo", properties.hasVideo());
requestJson.put("hasAudio", properties.hasAudio());
requestJson.put("outputMode", properties.outputMode().toString());

if(properties.layout() != null) {
ObjectNode layout = requestJson.putObject("layout");
layout.put("type", properties.layout().getType().toString());
layout.put("stylesheet", properties.layout().getStylesheet());
}
if (properties.name() != null) {
requestJson.put("name", properties.name());
}
Expand Down
73 changes: 63 additions & 10 deletions src/test/java/com/opentok/test/OpenTokTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,8 @@
import com.github.tomakehurst.wiremock.client.WireMock;
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
import com.github.tomakehurst.wiremock.junit.WireMockRule;
import com.opentok.Archive;
import com.opentok.*;
import com.opentok.Archive.OutputMode;
import com.opentok.ArchiveList;
import com.opentok.ArchiveMode;
import com.opentok.ArchiveProperties;
import com.opentok.MediaMode;
import com.opentok.OpenTok;
import com.opentok.Role;
import com.opentok.Session;
import com.opentok.SessionProperties;
import com.opentok.TokenOptions;
import com.opentok.exception.InvalidArgumentException;
import com.opentok.exception.OpenTokException;
import org.apache.commons.lang.StringUtils;
Expand All @@ -38,6 +29,7 @@
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;

import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
Expand Down Expand Up @@ -259,6 +251,27 @@ public void testTokenDefault() throws
assertNotNull(tokenData.get("nonce"));
}

@Test
public void testTokenLayoutClass() throws
OpenTokException, UnsupportedEncodingException, NoSuchAlgorithmException,
SignatureException, InvalidKeyException {

int apiKey = 123456;
String apiSecret = "1234567890abcdef1234567890abcdef1234567890";
OpenTok opentok = new OpenTok(apiKey, apiSecret);
String sessionId = "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4";

String token = sdk.generateToken(sessionId, new TokenOptions.Builder()
.initialLayoutClassList(Arrays.asList("full", "focus"))
.build());

assertNotNull(token);
assertTrue(Helpers.verifyTokenSignature(token, apiSecret));

Map<String, String> tokenData = Helpers.decodeToken(token);
assertEquals("full focus", tokenData.get("initial_layout_class_list"));
}

@Test
public void testTokenRoles() throws
OpenTokException, UnsupportedEncodingException, NoSuchAlgorithmException,
Expand Down Expand Up @@ -702,6 +715,46 @@ public void testStartComposedArchive() throws OpenTokException {
Helpers.verifyUserAgent();
}

@Test
public void testStartComposedArchiveWithLayout() throws OpenTokException {
String sessionId = "SESSIONID";

stubFor(post(urlEqualTo(archivePath))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody("{\n" +
" \"createdAt\" : 1395183243556,\n" +
" \"duration\" : 0,\n" +
" \"id\" : \"30b3ebf1-ba36-4f5b-8def-6f70d9986fe9\",\n" +
" \"name\" : \"\",\n" +
" \"partnerId\" : 123456,\n" +
" \"reason\" : \"\",\n" +
" \"sessionId\" : \"SESSIONID\",\n" +
" \"size\" : 0,\n" +
" \"status\" : \"started\",\n" +
" \"url\" : null,\n" +
" \"outputMode\" : \"composed\"\n" +
" }")));
ArchiveProperties properties = new ArchiveProperties.Builder()
.outputMode(OutputMode.COMPOSED)
.layout(new ArchiveLayout(ArchiveLayout.Type.CUSTOM, "stream { position: absolute; }"))
.build();

Archive archive = sdk.startArchive(sessionId, properties);
assertNotNull(archive);
assertEquals(sessionId, archive.getSessionId());
assertNotNull(archive.getId());
assertEquals(OutputMode.COMPOSED, archive.getOutputMode());

verify(postRequestedFor(urlMatching(archivePath)));
// TODO: find a way to match JSON without caring about spacing
//.withRequestBody(matching(".*"+".*"))
assertTrue(Helpers.verifyTokenAuth(apiKey, apiSecret,
findAll(postRequestedFor(urlMatching(archivePath)))));
Helpers.verifyUserAgent();
}

@Test
public void testStartIndividualArchive() throws OpenTokException {
String sessionId = "SESSIONID";
Expand Down

0 comments on commit 77f5c8a

Please sign in to comment.