Newer
Older
/**
* ======================================================
* OpenBIS Data Store Server facade internal code (DO NOT USE!!!)
* ======================================================
*/
function _DataStoreServerInternal(datastoreUrlOrNull, httpServerUri){
this.init(datastoreUrlOrNull, httpServerUri);
}
_DataStoreServerInternal.prototype.init = function(datastoreUrlOrNull, httpServerUri){
this.datastoreUrl = this.normalizeUrl(datastoreUrlOrNull, httpServerUri);
this.httpServerUri = httpServerUri;
}
_DataStoreServerInternal.prototype.log = function(msg){
if(console){
console.log(msg);
}
}
_DataStoreServerInternal.prototype.normalizeUrl = function(openbisUrlOrNull, httpServerUri){
var parts = this.parseUri(window.location);
if(openbisUrlOrNull){
var openbisParts = this.parseUri(openbisUrlOrNull);
for(openbisPartName in openbisParts){
var openbisPartValue = openbisParts[openbisPartName];
if(openbisPartValue){
parts[openbisPartName] = openbisPartValue;
}
}
}
return parts.protocol + "://" + parts.authority + httpServerUri;
}
_DataStoreServerInternal.prototype.getUrlForMethod = function(method) {
return this.datastoreUrl + "?method=" + method;
}
_DataStoreServerInternal.prototype.jsonRequestData = function(params) {
return JSON.stringify(params);
}
_DataStoreServerInternal.prototype.sendHttpRequest = function(httpMethod, contentType, url, data, callback) {
const xhr = new XMLHttpRequest();
xhr.open(httpMethod, url);
xhr.responseType = "blob";
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
const status = xhr.status;
Adam Laskowski
committed
if (status >= 200 && status < 300) {
const response = xhr.response
const contentType = this.getResponseHeader('content-type');
switch (contentType) {
case 'text/plain':
// Fall through.
case 'application/json':
response.text().then((blobResponse) => callback(blobResponse))
.catch((error) => alert(error));
break;
case 'application/octet-stream':
callback(response);
break;
default:
throw new Error("Client error HTTP response. Unsupported content-type received.");
}
Adam Laskowski
committed
} else if(status >= 400 && status < 500) {
let response = JSON.parse(xhr.responseText);
alert(response.error[1].message);
} else if(status >= 500 && status < 600) {
let response = JSON.parse(xhr.responseText);
alert(response.error[1].message);
} else {
alert("ERROR: " + xhr.responseText);
}
}
};
Adam Laskowski
committed
xhr.send(data);
}
Adam Laskowski
committed
_DataStoreServerInternal.prototype.buildGetUrl = function(queryParams) {
const queryString = Object.keys(queryParams)
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(queryParams[key])}`)
.join('&');
return `${this.datastoreUrl}?${queryString}`;
}
// Functions for working with cookies (see http://www.quirksmode.org/js/cookies.html)
_DataStoreServerInternal.prototype.createCookie = function(name,value,days) {
if (days) {
var date = new Date();
date.setTime(date.getTime()+(days*24*60*60*1000));
var expires = "; expires="+date.toGMTString();
}
else var expires = "";
document.cookie = name+"="+value+expires+"; path=/";
}
_DataStoreServerInternal.prototype.readCookie = function(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
}
return null;
}
_DataStoreServerInternal.prototype.eraseCookie = function(name) {
this.createCookie(name,"",-1);
}
// parseUri 1.2.2 (c) Steven Levithan <stevenlevithan.com> MIT License (see http://blog.stevenlevithan.com/archives/parseuri)
_DataStoreServerInternal.prototype.parseUri = function(str) {
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
var options = {
strictMode: false,
key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
q: {
name: "queryKey",
parser: /(?:^|&)([^&=]*)=?([^&]*)/g
},
parser: {
strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
}
};
var o = options,
m = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
uri = {},
i = 14;
while (i--) uri[o.key[i]] = m[i] || "";
uri[o.q.name] = {};
uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
if ($1) uri[o.q.name][$1] = $2;
});
return uri;
}
/** Helper method for checking response from DSS server */
function parseJsonResponse(rawResponse, action) {
let response = JSON.parse(rawResponse);
if(response.error){
alert(response.error[1].message);
}else{
action(response);
}
}
/**
* ===============
* DSS facade
* ===============
*
* The facade provides access to the DSS methods
*
*/
function DataStoreServer(datastoreUrlOrNull, httpServerUri) {
this._internal = new _DataStoreServerInternal(datastoreUrlOrNull, httpServerUri);
}
/**
* ==================================================================================
* ch.ethz.sis.afsapi.api.AuthenticationAPI methods
* ==================================================================================
*/
/**
* Stores the current session in a cookie.
*
* @method
*/
DataStoreServer.prototype.rememberSession = function() {
this._internal.createCookie('dataStoreServer', this.getSession(), 1);
}
/**
* Removes the current session from a cookie.
*
* @method
*/
DataStoreServer.prototype.forgetSession = function() {
this._internal.eraseCookie('dataStoreServer');
}
/**
* Restores the current session from a cookie.
*
* @method
*/
DataStoreServer.prototype.restoreSession = function() {
this._internal.sessionToken = this._internal.readCookie('dataStoreServer');
}
/**
* Sets the current session.
*
* @method
*/
DataStoreServer.prototype.useSession = function(sessionToken){
this._internal.sessionToken = sessionToken;
}
/**
* Returns the current session.
*
* @method
*/
DataStoreServer.prototype.getSession = function(){
return this._internal.sessionToken;
}
Adam Laskowski
committed
/**
* Sets interactiveSessionKey.
*
* @method
*/
DataStoreServer.prototype.setInteractiveSessionKey = function(interactiveSessionKey){
Adam Laskowski
committed
this._internal.interactiveSessionKey = interactiveSessionKey;
}
/**
* Returns the current session.
*
* @method
*/
DataStoreServer.prototype.getInteractiveSessionKey = function(){
Adam Laskowski
committed
return this._internal.interactiveSessionKey;
}
/**
* Sets transactionManagerKey.
*
* @method
*/
DataStoreServer.prototype.setTransactionManagerKey = function(transactionManagerKey){
Adam Laskowski
committed
this._internal.transactionManagerKey = transactionManagerKey;
}
/**
* Returns the current session.
*
* @method
*/
DataStoreServer.prototype.getTransactionManagerKey = function(){
Adam Laskowski
committed
return this._internal.transactionManagerKey;
}
DataStoreServer.prototype.fillCommonParameters = function(params) {
Adam Laskowski
committed
if(this.getSession()) {
params["sessionToken"] = this.getSession();
}
if(this.getInteractiveSessionKey()) {
params["interactiveSessionKey"] = this.getInteractiveSessionKey();
}
if(this.getTransactionManagerKey()) {
params["transactionManagerKey"] = this.getTransactionManagerKey();
}
return params;
}
const encodeParams = p => Object.entries(p).map(kv => kv.map(encodeURIComponent).join("=")).join("&");
/**
* Log into DSS.
*
* @method
*/
DataStoreServer.prototype.login = function(userId, userPassword, action) {
Adam Laskowski
committed
var datastoreObj = this
const data = this.fillCommonParameters({
"method": "login",
"userId": userId,
"password": userPassword
});
this._internal.sendHttpRequest(
"POST",
"application/octet-stream",
Adam Laskowski
committed
this._internal.datastoreUrl,
encodeParams(data),
function(loginResponse) {
datastoreObj._internal.sessionToken = loginResponse;
datastoreObj.rememberSession();
action(loginResponse);
}
);
}
/**
* Checks whether the current session is still active.
*
*/
DataStoreServer.prototype.isSessionValid = function(action) {
Adam Laskowski
committed
const data = this.fillCommonParameters({"method":"isSessionValid"});
this._internal.sendHttpRequest(
"GET",
"application/octet-stream",
Adam Laskowski
committed
this._internal.datastoreUrl,
encodeParams(data),
(response) => parseJsonResponse(response, action)
);
}else{
action({ result : false })
}
}
/**
* Restores the current session from a cookie and executes
* the specified action if the session is still active.
*
* @see restoreSession()
* @see isSessionActive()
* @method
*/
DataStoreServer.prototype.ifRestoredSessionActive = function(action) {
this.restoreSession();
this.isSessionValid(function(data) { if (data.result) action(data) });
}
/**
* Log out of DSS.
*
* @method
*/
DataStoreServer.prototype.logout = function(action) {
this.forgetSession();
if(this.getSession()){
Adam Laskowski
committed
const data = this.fillCommonParameters({"method":"logout"});
this._internal.sendHttpRequest(
"POST",
"application/octet-stream",
Adam Laskowski
committed
this._internal.datastoreUrl,
encodeParams(data),
(response) => parseJsonResponse(response, action)
);
}else if(action){
action({ result : null });
}
}
/**
* ==================================================================================
* ch.ethz.sis.afsapi.api.OperationsAPI methods
* ==================================================================================
*/
/**
* List files in the DSS for given owner and source
*/
DataStoreServer.prototype.list = function(owner, source, recursively, action){
Adam Laskowski
committed
const data = this.fillCommonParameters({
"method": "list",
"owner" : owner,
"source": source,
Adam Laskowski
committed
"recursively": recursively
});
this._internal.sendHttpRequest(
"GET",
"application/octet-stream",
this._internal.buildGetUrl(data),
{},
(response) => parseJsonResponse(response, action)
);
}
/**
* Read the contents of selected file
* @param {str} owner owner of the file
* @param {str} source path to file
* @param {int} offset offset from whoch to start reading
* @param {int} limit how many characters to read
* @param {*} action post-processing action
*/
DataStoreServer.prototype.read = function(owner, source, offset, limit, action){
Adam Laskowski
committed
const data = this.fillCommonParameters({
"method": "read",
"owner" : owner,
"source": source,
"offset": offset,
Adam Laskowski
committed
"limit": limit
});
this._internal.sendHttpRequest(
"GET",
"application/octet-stream",
this._internal.buildGetUrl(data),
{},
(response) => action(response)
);
Adam Laskowski
committed
/** Helper function to convert string md5Hash into an array. */
function hex2a(hexx) {
var hex = hexx.toString(); //force conversion
var str = '';
for (var i = 0; i < hex.length; i += 2)
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
return str;
}
/**
* Write data to file (or create it)
* @param {str} owner owner of the file
* @param {str} source path to file
* @param {int} offset offset from which to start writing
* @param {str} data data to write
* @param {*} action post-processing action
*/
DataStoreServer.prototype.write = function(owner, source, offset, data, action){
Adam Laskowski
committed
const params = this.fillCommonParameters({
"method": "write",
"owner" : owner,
"source": source,
"offset": offset,
"data": btoa(data),
"md5Hash": btoa(hex2a(md5(data))),
});
this._internal.sendHttpRequest(
"POST",
"application/octet-stream",
Adam Laskowski
committed
this._internal.datastoreUrl,
encodeParams(params),
(response) => action(response)
);
}
/**
* Delete file from the DSS
* @param {str} owner owner of the file
* @param {str} source path to file
* @param {*} action post-processing action
*/
DataStoreServer.prototype.delete = function(owner, source, action){
Adam Laskowski
committed
const data = this.fillCommonParameters({
"method": "delete",
"owner" : owner,
"source": source
});
this._internal.sendHttpRequest(
"DELETE",
"application/octet-stream",
Adam Laskowski
committed
this._internal.datastoreUrl,
encodeParams(data),
(response) => action(response)
);
}
/**
* Copy file within DSS
*/
DataStoreServer.prototype.copy = function(sourceOwner, source, targetOwner, target, action){
Adam Laskowski
committed
const data = this.fillCommonParameters({
"method": "copy",
"sourceOwner" : sourceOwner,
"source": source,
"targetOwner": targetOwner,
"target" : target
});
this._internal.sendHttpRequest(
"POST",
"application/octet-stream",
Adam Laskowski
committed
this._internal.datastoreUrl,
encodeParams(data),
(response) => action(response)
);
}
/**
* Move file within DSS
*/
DataStoreServer.prototype.move = function(sourceOwner, source, targetOwner, target, action){
Adam Laskowski
committed
const data = this.fillCommonParameters({
"method": "move",
"sourceOwner" : sourceOwner,
"source": source,
"targetOwner": targetOwner,
"target" : target
});
this._internal.sendHttpRequest(
"POST",
"application/octet-stream",
Adam Laskowski
committed
this._internal.datastoreUrl,
encodeParams(data),
(response) => action(response)
);
/**
* Create a file/directory within DSS
*/
DataStoreServer.prototype.create = function(owner, source, directory, action){
const data = this.fillCommonParameters({
"method": "create",
"owner" : owner,
"source": source,
"directory": directory
});
this._internal.sendHttpRequest(
"POST",
"application/octet-stream",
this._internal.datastoreUrl,
encodeParams(data),
(response) => action(response)
);
}
/**
* ==================================================================================
* ch.ethz.sis.afsapi.api.TwoPhaseTransactionAPI methods
* ==================================================================================
*/
DataStoreServer.prototype.begin = function(transactionId, action){
Adam Laskowski
committed
const data = this.fillCommonParameters({
"method": "begin",
"transactionId" : transactionId
});
this._internal.sendHttpRequest(
"POST",
"application/octet-stream",
Adam Laskowski
committed
this._internal.datastoreUrl,
encodeParams(data),
(response) => action(response)
);
}
DataStoreServer.prototype.prepare = function(action){
Adam Laskowski
committed
const data = this.fillCommonParameters({
"method": "prepare"
});
this._internal.sendHttpRequest(
"POST",
"application/octet-stream",
Adam Laskowski
committed
this._internal.datastoreUrl,
encodeParams(data),
(response) => action(response)
);
}
DataStoreServer.prototype.commit = function(action){
Adam Laskowski
committed
const data = this.fillCommonParameters({
"method": "commit"
});
this._internal.sendHttpRequest(
"POST",
"application/octet-stream",
Adam Laskowski
committed
this._internal.datastoreUrl,
encodeParams(data),
(response) => action(response)
);
}
DataStoreServer.prototype.rollback = function(action){
Adam Laskowski
committed
const data = this.fillCommonParameters({
"method": "rollback"
});
this._internal.sendHttpRequest(
"POST",
"application/octet-stream",
Adam Laskowski
committed
this._internal.datastoreUrl,
encodeParams(data),
(response) => action(response)
);
}
DataStoreServer.prototype.recover = function(action){
Adam Laskowski
committed
const data = this.fillCommonParameters({
"method": "recover"
});
this._internal.sendHttpRequest(
"POST",
"application/octet-stream",
Adam Laskowski
committed
this._internal.datastoreUrl,
encodeParams(data),
(response) => action(response)
);
}