
com.aimmac23.hub.videostorage.BasicWebDAVStore Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of selenium-video-node Show documentation
Show all versions of selenium-video-node Show documentation
Selenium Grid plugin that records videos of running tests
package com.aimmac23.hub.videostorage;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.apache.http.Header;
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.HttpClientBuilder;
/**
* A plugin to store videos on a WebDAV server. It only uses HTTP GET, PUT and HEAD - not any
* WebDAV-specific extensions. Supports SSL, and optionally username/password authentication.
*
* Use this plugin when:
*
* - You don't want your Selenium Hub server to be in charge of storage
* - You may want to make the videos integrate with another system
* - You don't want the Hub to forget about videos over restarts
*
*
* @author Alasdair Macmillan
*
*/
public class BasicWebDAVStore implements IVideoStore {
private static final Logger log = Logger.getLogger(BasicWebDAVStore.class.getName());
private boolean useSSL = false;
private String username;
private String password;
private HttpHost remoteHost;
private HttpClient client;
private URL url;
private HttpClientContext clientContext;
public BasicWebDAVStore() throws Exception {
String urlString = System.getProperty("webdav.url");
if(urlString == null) {
throw new IllegalStateException("System property 'webdav.url' not defined - cannot use " +
this.getClass().getName());
}
url = new URL(urlString);
String protocol = url.getProtocol().toLowerCase();
if("https".equals(protocol)) {
useSSL = true;
}
username = System.getProperty("webdav.username");
password = System.getProperty("webdav.password");
if(username != null && password == null) {
log.warning("'webdav.username' set without 'webdav.password' - Video uploading will probably not work");
}
int port;
if(url.getPort() != -1) {
port = url.getPort();
}
else if(useSSL) {
port = 443;
}
else {
port = 80;
}
remoteHost = new HttpHost(url.getHost(), port, useSSL ? "https" : "http");
BasicCredentialsProvider credentials = new BasicCredentialsProvider();
if(username != null) {
credentials.setCredentials(new AuthScope(remoteHost), new UsernamePasswordCredentials(username, password));
}
HttpClientBuilder builder = HttpClientBuilder.create();
if(useSSL) {
builder.setSslcontext(new SSLContextBuilder().useSSL().build());
}
client = builder.setDefaultCredentialsProvider(credentials).build();
clientContext = createClientContext(remoteHost, credentials);
}
/**
* The Apache HTTP client makes it as hard as possible to eagerly send auth credentials to remote hosts for
* security reasons. We have to do this because we are streaming the video file to upload, so we cannot
* send a second HTTP PUT with credentials.
*
* @param host - the remote host we are connecting to
* @param credentials - an object possibly holding HTTP credentials
* @return A Context object that the HTTP client should use for connection-specific properties (clone before use)
*/
private HttpClientContext createClientContext(HttpHost host, BasicCredentialsProvider credentials) {
HttpClientContext context = HttpClientContext.create();
AuthCache authCache = new BasicAuthCache();
BasicScheme basicAuth = new BasicScheme();
context.setAuthCache(authCache);
authCache.put(host, basicAuth);
context.setCredentialsProvider(credentials);
context.setAuthCache(authCache);
return context;
}
@Override
public void storeVideo(InputStream videoStream, long contentLength, String mimeType,
String sessionId, SessionInfoBean infoBean) throws Exception {
HttpPut request = new HttpPut(url.toExternalForm() + "/" + sessionId + ".webm");
request.setEntity(new InputStreamEntity(videoStream, contentLength, ContentType.create(mimeType)));
try {
HttpResponse response = client.execute(remoteHost, request, new HttpClientContext(clientContext));
int statusCode = response.getStatusLine().getStatusCode();
if(statusCode != HttpStatus.SC_OK && statusCode != HttpStatus.SC_NO_CONTENT && statusCode != HttpStatus.SC_CREATED) {
throw new HttpException("Could not upload video - response code: " + statusCode +
" reason: " + response.getStatusLine().getReasonPhrase());
}
log.info("Successfully uploaded video for session: " + sessionId);
}
finally {
request.releaseConnection();
}
}
@Override
public WebDAVDownloadContext retrieveVideo(String sessionId) throws Exception {
HttpGet request = new HttpGet(url.toExternalForm() + "/" + sessionId + ".webm");
HttpResponse response = client.execute(remoteHost, request);
int statusCode = response.getStatusLine().getStatusCode();
if(statusCode == HttpStatus.SC_NOT_FOUND) {
return new WebDAVDownloadContext(request, response, false, false);
}
if(statusCode != HttpStatus.SC_OK) {
throw new HttpException("Could not retrieve video - for session: " + sessionId +
" response code: " + statusCode +
" reason: " + response.getStatusLine().getReasonPhrase());
}
log.info("Got video for session: " + sessionId);
return new WebDAVDownloadContext(request, response, true, false);
}
@Override
public StoredVideoInfoContext getVideoInformation(String sessionId)
throws Exception {
HttpHead request = new HttpHead(url.toExternalForm() + "/" + sessionId + ".webm");
HttpResponse response = client.execute(remoteHost, request);
int statusCode = response.getStatusLine().getStatusCode();
if(statusCode == HttpStatus.SC_NOT_FOUND) {
return new WebDAVDownloadContext(request, response, false, true);
}
if(statusCode == HttpStatus.SC_OK) {
return new WebDAVDownloadContext(request, response, true, true);
}
throw new IllegalStateException("Unknown status when fetching video information for session: " + sessionId);
}
@Override
public String getVideoStoreTypeIdentifier() {
return "WEBDAV";
}
private static class WebDAVDownloadContext implements StoredVideoDownloadContext, StoredVideoInfoContext {
private HttpRequestBase request;
private HttpResponse response;
private boolean videoFound;
private boolean isHeadRequest;
public WebDAVDownloadContext(HttpRequestBase request, HttpResponse response, boolean videoFound, boolean isHeadRequest) {
this.request = request;
this.response = response;
this.videoFound = videoFound;
this.isHeadRequest = isHeadRequest;
}
@Override
public boolean isVideoFound() {
return videoFound;
}
@Override
public InputStream getStream() throws IOException {
if(isHeadRequest) {
throw new IllegalStateException("Cannot retrieve video with an HTTP HEAD request");
}
if(videoFound) {
return response.getEntity().getContent();
}
return null;
}
@Override
public Long getContentLengthIfKnown() {
Header contentLength = response.getFirstHeader("Content-Length");
if(contentLength != null) {
return new Long(contentLength.getValue());
}
return null;
}
@Override
public void close() {
request.releaseConnection();
}
@Override
public Map additionalInformation() {
Map info = new HashMap();
try {
info.put("url", request.getURI().toURL().toExternalForm());
} catch (MalformedURLException e) {
e.printStackTrace();
}
return info;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy