Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 34 additions & 8 deletions src/main/java/com/coveo/pushapiclient/PlatformClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public class PlatformClient {
private final String organizationId;
private final ApiCore api;
private final PlatformUrl platformUrl;
private String[] userAgents;

/**
* Construct a PlatformClient
Expand Down Expand Up @@ -570,13 +571,12 @@ private String[] getAuthorizationHeader() {
}

private String[] getContentTypeApplicationJSONHeader() {
MavenXpp3Reader reader = new MavenXpp3Reader();
String version = "";
try {
Model model = reader.read(new FileReader("pom.xml"));
version = model.getVersion();
} catch (Exception e) {
version = "Not-Available";
StringBuilder userAgentValue = new StringBuilder();
String sdkVersion = getSdkVersion();
userAgentValue.append(String.format("CoveoSDKJava/%s", sdkVersion));

if (userAgents != null && userAgents.length > 0) {
userAgentValue.append(" ").append(String.join(" ", userAgents));
}

return new String[] {
Expand All @@ -585,10 +585,20 @@ private String[] getContentTypeApplicationJSONHeader() {
"Accept",
"application/json",
"User-Agent",
String.format("CoveoSDKJava/%s", version)
userAgentValue.toString()
};
}

private String getSdkVersion() {
MavenXpp3Reader reader = new MavenXpp3Reader();
try {
Model model = reader.read(new FileReader("pom.xml"));
return model.getVersion();
} catch (Exception e) {
return "Not-Available";
}
}

private String[] getAes256Header() {
return new String[] {"x-amz-server-side-encryption", "AES256"};
}
Expand All @@ -600,4 +610,20 @@ private String[] getContentTypeApplicationOctetStreamHeader() {
private String toJSON(HashMap<String, Object> hashMap) {
return new Gson().toJson(hashMap, new TypeToken<HashMap<String, Object>>() {}.getType());
}

public String[] getUserAgents() {
return userAgents;
}

public void setUserAgents(String[] userAgents) {
if (!validUserAgents(userAgents)) {
throw new IllegalArgumentException("Invalid user agents");
}
this.userAgents = userAgents;
}

protected boolean validUserAgents(String[] userAgents) {
String pattern = "^.+/v(\\d+(\\.\\d+){0,2})$";
return Arrays.stream(userAgents).allMatch(agent -> agent.matches(pattern));
}
}
35 changes: 34 additions & 1 deletion src/main/java/com/coveo/pushapiclient/StreamService.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,22 @@ public class StreamService {
private String streamId;
private DocumentUploadQueue queue;

/**
* Creates a service to stream your documents to the provided source by interacting with the
* Stream API.
*
* <p>To perform <a href="https://docs.coveo.com/en/l62e0540">full document updates or
* deletions</a>, use the {@UpdateStreamService}, since pushing documents with the
* {@StreamService} is equivalent to triggering a full source rebuild. The {@StreamService} can
* also be used for an initial catalog upload.
*
* @param source The source to which you want to send your documents.
* @param userAgents The user agent to use for the requests.
*/
public StreamService(StreamEnabledSource source, String[] userAgents) {
this(source, new BackoffOptionsBuilder().build(), userAgents);
}

/**
* Creates a service to stream your documents to the provided source by interacting with the
* Stream API.
Expand Down Expand Up @@ -42,6 +58,23 @@ public StreamService(StreamEnabledSource source) {
* @param options The configuration options for exponential backoff.
*/
public StreamService(StreamEnabledSource source, BackoffOptions options) {
this(source, options, null);
}

/**
* Creates a service to stream your documents to the provided source by interacting with the
* Stream API.
*
* <p>To perform <a href="https://docs.coveo.com/en/l62e0540">full document updates or
* deletions</a>, use the {@UpdateStreamService}, since pushing documents with the
* {@StreamService} is equivalent to triggering a full source rebuild. The {@StreamService} can
* also be used for an initial catalog upload.
*
* @param source The source to which you want to send your documents.
* @param options The configuration options for exponential backoff.
* @param userAgents The user agent to use for the requests.
*/
public StreamService(StreamEnabledSource source, BackoffOptions options, String[] userAgents) {
String apiKey = source.getApiKey();
String organizationId = source.getOrganizationId();
PlatformUrl platformUrl = source.getPlatformUrl();
Expand All @@ -51,7 +84,7 @@ public StreamService(StreamEnabledSource source, BackoffOptions options) {
this.source = source;
this.queue = new DocumentUploadQueue(uploader);
this.platformClient = new PlatformClient(apiKey, organizationId, platformUrl, options);

platformClient.setUserAgents(userAgents);
this.service = new StreamServiceInternal(this.source, this.queue, this.platformClient, logger);
}

Expand Down
33 changes: 33 additions & 0 deletions src/main/java/com/coveo/pushapiclient/UpdateStreamService.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,21 @@ public class UpdateStreamService {

private FileContainer fileContainer;

/**
* Creates a service to stream your documents to the provided source by interacting with the
* Stream API. This provides the ability to incrementally add, update, or delete documents via a
* stream.
*
* <p>To perform <a href="https://docs.coveo.com/en/lb4a0344">a full source rebuild</a>, use the
* {@StreamService}
*
* @param source The source to which you want to send your documents.
* @param userAgents The user agent to use for the requests.
*/
public UpdateStreamService(StreamEnabledSource source, String[] userAgents) {
this(source, new BackoffOptionsBuilder().build(), userAgents);
}

/**
* Creates a service to stream your documents to the provided source by interacting with the
* Stream API. This provides the ability to incrementally add, update, or delete documents via a
Expand All @@ -40,10 +55,28 @@ public UpdateStreamService(StreamEnabledSource source) {
* @param options The configuration options for exponential backoff.
*/
public UpdateStreamService(StreamEnabledSource source, BackoffOptions options) {
this(source, options, null);
}

/**
* Creates a service to stream your documents to the provided source by interacting with the
* Stream API. This provides the ability to incrementally add, update, or delete documents via a
* stream.
*
* <p>To perform <a href="https://docs.coveo.com/en/lb4a0344">a full source rebuild</a>, use the
* {@StreamService}
*
* @param source The source to which you want to send your documents.
* @param options The configuration options for exponential backoff.
* @param userAgents The user agent to use for the requests.
*/
public UpdateStreamService(
StreamEnabledSource source, BackoffOptions options, String[] userAgents) {
Logger logger = LogManager.getLogger(UpdateStreamService.class);
this.platformClient =
new PlatformClient(
source.getApiKey(), source.getOrganizationId(), source.getPlatformUrl(), options);
this.platformClient.setUserAgents(userAgents);
this.updateStreamServiceInternal =
new UpdateStreamServiceInternal(
source,
Expand Down
54 changes: 54 additions & 0 deletions src/test/java/com/coveo/pushapiclient/PlatformClientTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,17 @@
import static org.mockito.Mockito.verify;

import com.google.gson.Gson;
import java.io.FileReader;
import java.io.IOException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
Expand All @@ -39,6 +43,10 @@ public void assertApplicationJsonHeader() {
assertTrue(this.argument.getValue().headers().map().get("Accept").contains("application/json"));
}

public void assertUserAgentHeader(String userAgentValue) {
assertTrue(this.argument.getValue().headers().map().get("User-Agent").contains(userAgentValue));
}

public SecurityIdentityModel securityIdentityModel() {
return new SecurityIdentityModel(identityModels(), identityModel(), identityModels());
}
Expand Down Expand Up @@ -472,4 +480,50 @@ public void testDeleteDocument() throws IOException, InterruptedException {
assertApplicationJsonHeader();
assertAuthorizationHeader();
}

@Test
public void testCorrectUserAgentHeader()
throws IOException, InterruptedException, XmlPullParserException {
String[] userAgents = {"MyAgent/v1", "MyAgent/v2.1", "MyAgent/v3.1.1"};
String version = getVersionFromPom();
String defaultAgent = String.format("CoveoSDKJava/%s", version);
String[] userAgentsWithDefault = new String[userAgents.length + 1];
userAgentsWithDefault[0] = defaultAgent;
System.arraycopy(userAgents, 0, userAgentsWithDefault, 1, userAgents.length);

client.setUserAgents(userAgents);
client.createSource("the_name", SourceType.PUSH, SourceVisibility.SECURED);
verify(httpClient)
.send(argument.capture(), any(HttpResponse.BodyHandlers.ofString().getClass()));

assertUserAgentHeader(String.join(" ", userAgentsWithDefault));
}

@Test
public void testDefaultUserAgentHeader()
throws IOException, InterruptedException, XmlPullParserException {
client.createSource("the_name", SourceType.PUSH, SourceVisibility.SECURED);
verify(httpClient)
.send(argument.capture(), any(HttpResponse.BodyHandlers.ofString().getClass()));
String version = getVersionFromPom();
assertUserAgentHeader(String.format("CoveoSDKJava/%s", version));
}

@Test(expected = IllegalArgumentException.class)
public void testInvalidHeaderValue() {
String[] userAgents = {"MyAgent/v1", "MyAgent/v2.1", "MyAgent/v3.1.1", "invalidHeaderValue"};
client.setUserAgents(userAgents);
}

@Test(expected = IllegalArgumentException.class)
public void testInvalidSemanticVersionHeaderValue() {
String[] userAgents = {"MyAgent/v1.1.1.1"};
client.setUserAgents(userAgents);
}

private String getVersionFromPom() throws IOException, XmlPullParserException {
MavenXpp3Reader reader = new MavenXpp3Reader();
Model model = reader.read(new FileReader("pom.xml"));
return model.getVersion();
}
}