Commit c9ec180f authored by Tristan Cavelier's avatar Tristan Cavelier

Replicate storage and index storage completed.

parent d851fe95
...@@ -108,6 +108,6 @@ module.exports = function(grunt) { ...@@ -108,6 +108,6 @@ module.exports = function(grunt) {
}); });
// Default task. // Default task.
grunt.registerTask('default', 'concat lint min qunit'); grunt.registerTask('default', 'concat lint min');
}; };
...@@ -18,6 +18,8 @@ module.exports = function(grunt) { ...@@ -18,6 +18,8 @@ module.exports = function(grunt) {
'<file_strip_banner:../../src/<%= pkg.name %>/localstorage.js>', '<file_strip_banner:../../src/<%= pkg.name %>/localstorage.js>',
'<file_strip_banner:../../src/<%= pkg.name %>/davstorage.js>', '<file_strip_banner:../../src/<%= pkg.name %>/davstorage.js>',
'<file_strip_banner:../../src/<%= pkg.name %>/replicatestorage.js>', '<file_strip_banner:../../src/<%= pkg.name %>/replicatestorage.js>',
'<file_strip_banner:../../src/<%= pkg.name %>/indexstorage.js>',
'<file_strip_banner:../../src/<%= pkg.name %>/cryptstorage.js>',
'<file_strip_banner:../../src/<%= pkg.name %>/outro.js>'], '<file_strip_banner:../../src/<%= pkg.name %>/outro.js>'],
dest: '../../lib/jio/<%= pkg.name %>.js' dest: '../../lib/jio/<%= pkg.name %>.js'
} }
......
/*! JIO - v0.1.0 - 2012-06-14 /*! JIO - v0.1.0 - 2012-06-15
* Copyright (c) 2012 Nexedi; Licensed */ * Copyright (c) 2012 Nexedi; Licensed */
var jio = (function () { var jio = (function () {
...@@ -150,8 +150,19 @@ var storageHandler = function(spec, my) { ...@@ -150,8 +150,19 @@ var storageHandler = function(spec, my) {
my = my || {}; my = my || {};
var that = storage( spec, my ); var that = storage( spec, my );
that.newCommand = function (method, spec) {
var o = spec || {};
o.label = method;
return command (o, my);
};
that.newStorage = function (spec) {
var o = spec || {};
return jioNamespace.storage (o, my);
};
that.addJob = function (storage,command) { that.addJob = function (storage,command) {
my.jobManager.addJob ( job({storage:storage, command:command}), my ); my.jobManager.addJob ( job({storage:storage, command:command}, my) );
}; };
return that; return that;
...@@ -278,15 +289,27 @@ var command = function(spec, my) { ...@@ -278,15 +289,27 @@ var command = function(spec, my) {
}; };
that.onResponseDo = function (fun) { that.onResponseDo = function (fun) {
priv.respond = fun; if (fun) {
priv.respond = fun;
} else {
return priv.respond;
}
}; };
that.onDoneDo = function (fun) { that.onDoneDo = function (fun) {
priv.done = fun; if (fun) {
priv.done = fun;
} else {
return priv.done;
}
}; };
that.onFailDo = function (fun) { that.onFailDo = function (fun) {
priv.fail = fun; if (fun) {
priv.fail = fun;
} else {
return priv.fail;
}
}; };
that.onEndDo = function (fun) { that.onEndDo = function (fun) {
...@@ -308,17 +331,40 @@ var command = function(spec, my) { ...@@ -308,17 +331,40 @@ var command = function(spec, my) {
tried:priv.tried, tried:priv.tried,
max_retry:priv.max_retry, max_retry:priv.max_retry,
path:priv.path, path:priv.path,
option:priv.option}; option:that.cloneOption()};
}; };
/**
* Is the command can be restored by another JIO : yes.
* @method canBeRestored
* @return {boolean} true
*/
that.canBeRestored = function() { that.canBeRestored = function() {
return true; return true;
}; };
/**
* Clones the command and returns it.
* @method clone
* @return {object} The cloned command.
*/
that.clone = function () { that.clone = function () {
return command(that.serialized(), my); return command(that.serialized(), my);
}; };
/**
* Clones the command options and returns the clone version.
* @method cloneOption
* @return {object} The clone of the command options.
*/
that.cloneOption = function () {
var k, o = {};
for (k in priv.option) {
o[k] = priv.option[k];
}
return o;
};
return that; return that;
}; };
...@@ -474,6 +520,10 @@ var jobStatus = function(spec, my) { ...@@ -474,6 +520,10 @@ var jobStatus = function(spec, my) {
return false; return false;
}; };
that.isDone = function() {
return false;
};
return that; return that;
}; };
...@@ -493,6 +543,10 @@ var doneStatus = function(spec, my) { ...@@ -493,6 +543,10 @@ var doneStatus = function(spec, my) {
that.canRestart = function() { that.canRestart = function() {
return false; return false;
}; };
that.isDone = function() {
return true;
};
return that; return that;
}; };
...@@ -998,7 +1052,7 @@ var jobManager = (function(spec, my) { ...@@ -998,7 +1052,7 @@ var jobManager = (function(spec, my) {
priv.job_a = []; priv.job_a = [];
my.jobManager = that; my.jobManager = that;
my.jobIdHandler = that; my.jobIdHandler = jobIdHandler;
// Methods // // Methods //
/** /**
...@@ -1471,7 +1525,6 @@ var jobRules = (function(spec, my) { ...@@ -1471,7 +1525,6 @@ var jobRules = (function(spec, my) {
my.jobManager = jobManager; my.jobManager = jobManager;
my.jobIdHandler = jobIdHandler; my.jobIdHandler = jobIdHandler;
priv.storage = jioNamespace.storage(spec, my); priv.storage = jioNamespace.storage(spec, my);
// initialize // // initialize //
...@@ -1561,7 +1614,7 @@ var jobRules = (function(spec, my) { ...@@ -1561,7 +1614,7 @@ var jobRules = (function(spec, my) {
jioNamespace.storage(specificstorage,my): jioNamespace.storage(specificstorage,my):
priv.storage), priv.storage),
command:saveDocument( command:saveDocument(
{path:path,content:content,option:option})},my)); {path:path,content:content,option:option},my)},my));
}; };
/** /**
...@@ -1590,7 +1643,7 @@ var jobRules = (function(spec, my) { ...@@ -1590,7 +1643,7 @@ var jobRules = (function(spec, my) {
jioNamespace.storage(specificstorage,my): jioNamespace.storage(specificstorage,my):
priv.storage), priv.storage),
command:loadDocument( command:loadDocument(
{path:path,option:option})},my)); {path:path,option:option},my)},my));
}; };
/** /**
...@@ -1616,7 +1669,7 @@ var jobRules = (function(spec, my) { ...@@ -1616,7 +1669,7 @@ var jobRules = (function(spec, my) {
jioNamespace.storage(specificstorage,my): jioNamespace.storage(specificstorage,my):
priv.storage), priv.storage),
command:removeDocument( command:removeDocument(
{path:path,option:option})},my)); {path:path,option:option},my)},my));
}; };
/** /**
...@@ -1645,7 +1698,7 @@ var jobRules = (function(spec, my) { ...@@ -1645,7 +1698,7 @@ var jobRules = (function(spec, my) {
jioNamespace.storage(specificstorage,my): jioNamespace.storage(specificstorage,my):
priv.storage), priv.storage),
command:getDocumentList( command:getDocumentList(
{path:path,option:option})},my)); {path:path,option:option},my)},my));
}; };
return that; return that;
...@@ -1673,6 +1726,7 @@ var jioNamespace = (function(spec, my) { ...@@ -1673,6 +1726,7 @@ var jioNamespace = (function(spec, my) {
*/ */
that.storage = function(spec, my, forcetype) { that.storage = function(spec, my, forcetype) {
spec = spec || {}; spec = spec || {};
my = my || {};
var type = forcetype || spec.type || 'base'; var type = forcetype || spec.type || 'base';
if (!storage_type_o[type]) { if (!storage_type_o[type]) {
throw invalidStorageType({type:type, throw invalidStorageType({type:type,
......
/*! JIO - v0.1.0 - 2012-06-14 /*! JIO - v0.1.0 - 2012-06-15
* Copyright (c) 2012 Nexedi; Licensed */ * Copyright (c) 2012 Nexedi; Licensed */
var jio=function(){var a=function(a,b){var c={};return a=a||{},b=b||{},c.name="jioException",c.message=a.message||"Unknown Reason.",c.toString=function(){return c.name+": "+c.message},c},b=function(b,c){var d=a(b,c);b=b||{};var e=b.command;return d.name="invalidCommandState",d.toString=function(){return d.name+": "+e.getLabel()+", "+d.message},d},c=function(b,c){var d=a(b,c);b=b||{};var e=b.storage.getType();return d.name="invalidStorage",d.toString=function(){return d.name+": "+'Type "'+e+'", '+d.message},d},d=function(b,c){var d=a(b,c),e=b.type;return d.name="invalidStorageType",d.toString=function(){return d.name+": "+e+", "+d.message},d},e=function(b,c){var d=a(b,c);return d.name="jobNotReadyException",d},f=function(b,c){var d=a(b,c);return d.name="tooMuchTriesJobException",d},g=function(b,c){var d=a(b,c);return d.name="invalidJobException",d},h=function(a,b){var d={};a=a||{},b=b||{};var e={};return e.type=a.type||"",d.getType=function(){return e.type},d.setType=function(a){e.type=a},d.execute=function(a){d.validate(a),d.done=a.done,d.fail=a.fail,a.executeOn(d)},d.isValid=function(){return!0},d.validate=function(a){var b=d.validateState();if(b)throw c({storage:d,message:b});a.validate(d)},d.serialized=function(){return{type:d.getType()}},d.saveDocument=function(a){throw c({storage:d,message:"Unknown storage."})},d.loadDocument=function(a){d.saveDocument()},d.removeDocument=function(a){d.saveDocument()},d.getDocumentList=function(a){d.saveDocument()},d.validateState=function(){return""},d.done=function(){},d.fail=function(){},d},i=function(a,b){a=a||{},b=b||{};var c=h(a,b);return c.addJob=function(a,c){b.jobManager.addJob(u({storage:a,command:c}),b)},c},j=function(a,c){var d={};a=a||{},c=c||{};var e={};return e.commandlist={saveDocument:n,loadDocument:l,removeDocument:m,getDocumentList:k},a.label&&e.commandlist[a.label]?(e.label=a.label,delete a.label,e.commandlist[e.label](a,c)):(e.path=a.path||"",e.tried=0,e.option=a.option||{},e.respond=e.option.onResponse||function(){},e.done=e.option.onDone||function(){},e.fail=e.option.onFail||function(){},e.retry=function(){d.setMaxRetry(-1),d.fail({status:0,statusText:"Fail Retry",message:"Impossible to retry."})},e.end=function(){},d.getLabel=function(){return"command"},d.getPath=function(){return e.path},d.getOption=function(a){return e.option[a]},d.validate=function(a){d.validateState()},d.getTried=function(){return e.tried},d.setMaxRetry=function(a){e.option.max_retry=a},d.execute=function(a){d.validate(a),e.tried++,a.execute(d)},d.executeOn=function(a){},d.validateState=function(){if(e.path==="")throw b({command:d,message:"Path is empty"})},d.done=function(a){e.respond({status:p(),value:a}),e.done(a),e.end()},d.fail=function(a){e.option.max_retry===0||e.tried<e.option.max_retry?e.retry():(e.respond({status:q(),error:a}),e.fail(a),e.end())},d.onResponseDo=function(a){e.respond=a},d.onDoneDo=function(a){e.done=a},d.onFailDo=function(a){e.fail=a},d.onEndDo=function(a){e.end=a},d.onRetryDo=function(a){e.retry=a},d.serialized=function(){return{label:d.getLabel(),tried:e.tried,max_retry:e.max_retry,path:e.path,option:e.option}},d.canBeRestored=function(){return!0},d.clone=function(){return j(d.serialized(),c)},d)},k=function(a,b){var c=j(a,b);a=a||{},b=b||{},c.getLabel=function(){return"getDocumentList"},c.executeOn=function(a){a.getDocumentList(c)},c.canBeRestored=function(){return!1};var d=c.done;return c.done=function(a){var b;if(a)for(b=0;b<a.length;b+=1)typeof a[b].last_modified!="number"&&(a[b].last_modified=(new Date(a[b].last_modified)).getTime()),typeof a[b].creation_date!="number"&&(a[b].creation_date=(new Date(a[b].creation_date)).getTime());d(a)},c},l=function(a,b){var c=j(a,b);a=a||{},b=b||{},c.getLabel=function(){return"loadDocument"},c.executeOn=function(a){a.loadDocument(c)},c.canBeRestored=function(){return!1};var d=c.done;return c.done=function(a){a&&(typeof a.last_modified!="number"&&(a.last_modified=(new Date(a.last_modified)).getTime()),typeof a.creation_date!="number"&&(a.creation_date=(new Date(a.creation_date)).getTime())),d(a)},c},m=function(a,b){var c=j(a,b);return a=a||{},b=b||{},c.getLabel=function(){return"removeDocument"},c.executeOn=function(a){a.removeDocument(c)},c},n=function(a,c){var d=j(a,c);a=a||{},c=c||{};var e={};e.content=a.content,d.getLabel=function(){return"saveDocument"},d.getContent=function(){return e.content};var f=d.validate;d.validate=function(a){if(typeof e.content!="string")throw b({command:d,message:"No data to save"});f(a)},d.executeOn=function(a){a.saveDocument(d)};var g=d.serialized;return d.serialized=function(){var a=g();return a.content=e.content,a},d},o=function(a,b){var c={};return a=a||{},b=b||{},c.getLabel=function(){return"job status"},c.canStart=function(){},c.canRestart=function(){},c.serialized=function(){return{label:c.getLabel()}},c.isWaitStatus=function(){return!1},c},p=function(a,b){var c=o(a,b);return a=a||{},b=b||{},c.getLabel=function(){return"done"},c.canStart=function(){return!1},c.canRestart=function(){return!1},c},q=function(a,b){var c=o(a,b);return a=a||{},b=b||{},c.getLabel=function(){return"fail"},c.canStart=function(){return!1},c.canRestart=function(){return!0},c},r=function(a,b){var c=o(a,b);return a=a||{},b=b||{},c.getLabel=function(){return"initial"},c.canStart=function(){return!0},c.canRestart=function(){return!0},c},s=function(a,b){var c=o(a,b);return a=a||{},b=b||{},c.getLabel=function(){return"on going"},c.canStart=function(){return!1},c.canRestart=function(){return!1},c},t=function(a,b){var c=o(a,b);a=a||{},b=b||{};var d={};return d.job_id_a=a.job_id_array||[],d.threshold=0,c.getLabel=function(){return"wait"},d.refreshJobIdArray=function(){var a=[],c;for(c=0;c<d.job_id_a.length;c+=1)b.jobManager.jobIdExists(d.job_id_a[c])&&a.push(d.job_id_a[c]);d.job_id_a=a},c.waitForJob=function(a){var b;for(b=0;b<d.job_id_a.length;b+=1)if(d.job_id_a[b]===a.getId())return;d.job_id_a.push(a.getId())},c.dontWaitForJob=function(a){var b,c=[];for(b=0;b<d.job_id_a.length;b+=1)d.job_id_a[b]!==a.getId()&&c.push(d.job_id_a[b]);d.job_id_a=c},c.waitForTime=function(a){d.threshold=Date.now()+a},c.stopWaitForTime=function(){d.threshold=0},c.canStart=function(){return d.refreshJobIdArray(),d.job_id_a.length===0&&Date.now()>=d.threshold},c.canRestart=function(){return c.canStart()},c.serialized=function(){return{label:c.getLabel(),waitfortime:d.threshold,waitforjob:d.job_id_a}},c.isWaitStatus=function(){return!0},c},u=function(a,b){var c={};a=a||{},b=b||{};var d={};return d.id=b.jobIdHandler.nextId(),d.command=a.command,d.storage=a.storage,d.status=r(),d.date=new Date,function(){if(!d.storage)throw g({job:c,message:"No storage set"});if(!d.command)throw g({job:c,message:"No command set"})}(),c.getCommand=function(){return d.command},c.getStatus=function(){return d.status},c.getId=function(){return d.id},c.getStorage=function(){return d.storage},c.getDate=function(){return d.date},c.isReady=function(){return d.tried===0?d.status.canStart():d.status.canRestart()},c.serialized=function(){return{id:d.id,date:d.date.getTime(),status:d.status.serialized(),command:d.command.serialized(),storage:d.storage.serialized()}},c.waitForJob=function(a){d.status.getLabel()!=="wait"&&(d.status=t({},b)),d.status.waitForJob(a)},c.dontWaitFor=function(a){d.status.getLabel()==="wait"&&d.status.dontWaitForJob(a)},c.waitForTime=function(a){d.status.getLabel()!=="wait"&&(d.status=t({},b)),d.status.waitForTime(a)},c.stopWaitForTime=function(){d.status.getLabel()==="wait"&&d.status.stopWaitForTime()},c.update=function(a){d.command.setMaxRetry(-1),d.command.fail({status:0,statusText:"Replaced",message:"Job has been replaced by another one."}),d.date=a.getDate(),d.command=a.getCommand(),d.status=a.getStatus()},c.execute=function(){if(d.max_retry!==0&&d.tried>=d.max_retry)throw f({job:c,message:"The job was invoked too much time."});if(!c.isReady())throw e({message:"Can not execute this job."});d.status=s(),d.command.onRetryDo(function(){var a=d.command.getTried();a=a*a*200,a>1e4&&(a=1e4),c.waitForTime(a)}),d.command.onEndDo(function(){b.jobManager.terminateJob(c)}),d.command.execute(d.storage)},c},v=function(a,b){var c={};a=a||{},b=b||{};var d=[],e=a.name||"",f=a.announcer||{};return c.add=function(a){d.push(a)},c.remove=function(a){var b,c=[];for(b=0;b<d.length;b+=1)d[b]!==a&&c.push(d[b]);d=c},c.register=function(){f.register(c)},c.unregister=function(){f.unregister(c)},c.trigger=function(a){var b;for(b=0;b<d.length;b++)d[b].apply(null,a)},c},w=function(a,b){var c=function(a,b){var c={};a=a||{},b=b||{};var d={};return d.id=a.id||0,d.interval=400,d.interval_id=null,d.touch=function(){LocalOrCookieStorage.setItem("jio/id/"+d.id,Date.now())},c.setId=function(a){d.id=a},c.setIntervalDelay=function(a){d.interval=a},c.getIntervalDelay=function(){return d.interval},c.start=function(){d.interval_id||(d.touch(),d.interval_id=setInterval(function(){d.touch()},d.interval))},c.stop=function(){d.interval_id!==null&&(clearInterval(d.interval_id),d.interval_id=null)},c}(),d=function(a,b){var c={};a=a||{},b=b||{};var d={};return c.register=function(a){d[a]||(d[a]=v())},c.unregister=function(a){d[a]&&delete d[a]},c.at=function(a){return d[a]},c.on=function(a,b){c.register(a),c.at(a).add(b)},c.trigger=function(a,b){c.at(a).trigger(b)},c}(),e=function(a,b){var c={};a=a||{},b=b||{};var d=0;return c.nextId=function(){return d=d+1,d},c}(),f=function(a,b){var c={};a=a||{},b=b||{};var d="jio/job_array",e={};return e.id=a.id,e.interval_id=null,e.interval=200,e.job_a=[],b.jobManager=c,b.jobIdHandler=c,e.getJobArrayName=function(){return d+"/"+e.id},e.getJobArray=function(){return LocalOrCookieStorage.getItem(e.getJobArrayName())||[]},e.copyJobArrayToLocal=function(){var a=[],b;for(b=0;b<e.job_a.length;b+=1)a.push(e.job_a[b].serialized());LocalOrCookieStorage.setItem(e.getJobArrayName(),a)},e.removeJob=function(a){var b,c=[];for(b=0;b<e.job_a.length;b+=1)e.job_a[b]!==a&&c.push(e.job_a[b]);e.job_a=c,e.copyJobArrayToLocal()},c.setId=function(a){e.id=a},c.start=function(){var a;e.interval_id===null&&(e.interval_id=setInterval(function(){e.restoreOldJio();for(a=0;a<e.job_a.length;a+=1)c.execute(e.job_a[a])},e.interval))},c.stop=function(){e.interval_id!==null&&(clearInterval(e.interval_id),e.interval_id=null,e.job_a.length===0&&LocalOrCookieStorage.deleteItem(e.getJobArrayName()))},e.restoreOldJio=function(){var a,b;e.lastrestore=e.lastrestore||0;if(e.lastrestore>Date.now()-2e3)return;b=LocalOrCookieStorage.getItem("jio/id_array")||[];for(a=0;a<b.length;a+=1)e.restoreOldJioId(b[a]);e.lastrestore=Date.now()},e.restoreOldJioId=function(a){var b;b=LocalOrCookieStorage.getItem("jio/id/"+a)||0,b<Date.now()-1e4&&(e.restoreOldJobFromJioId(a),e.removeOldJioId(a),e.removeJobArrayFromJioId(a))},e.restoreOldJobFromJioId=function(a){var d,e;e=LocalOrCookieStorage.getItem("jio/job_array/"+a)||[];for(d=0;d<e.length;d+=1){var f=j(e[d].command,b);f.canBeRestored()&&c.addJob(u({storage:x.storage(e[d].storage,b),command:f},b))}},e.removeOldJioId=function(a){var b,c,d=[];c=LocalOrCookieStorage.getItem("jio/id_array")||[];for(b=0;b<c.length;b+=1)c[b]!==a&&d.push(c[b]);LocalOrCookieStorage.setItem("jio/id_array",d),LocalOrCookieStorage.deleteItem("jio/id/"+a)},e.removeJobArrayFromJioId=function(a){LocalOrCookieStorage.deleteItem("jio/job_array/"+a)},c.execute=function(a){try{a.execute()}catch(b){switch(b.name){case"jobNotReadyException":break;case"tooMuchTriesJobException":break;default:throw b}}e.copyJobArrayToLocal()},c.jobIdExists=function(a){var b;for(b=0;b<e.job_a.length;b+=1)if(e.job_a[b].getId()===a)return!0;return!1},c.terminateJob=function(a){e.removeJob(a)},c.addJob=function(a){var b=c.validateJobAccordingToJobList(e.job_a,a);e.appendJob(a,b)},c.validateJobAccordingToJobList=function(a,b){var c,d=[];for(c=0;c<a.length;c+=1)d.push(g.validateJobAccordingToJob(a[c],b));return d},e.appendJob=function(a,b){var c;if(e.job_a.length!==b.length)throw new RangeError("Array out of bound");for(c=0;c<b.length;c+=1)if(b[c].action==="dont accept")return;for(c=0;c<b.length;c+=1)switch(b[c].action){case"eliminate":e.removeJob(b[c].job);break;case"update":b[c].job.update(a),e.copyJobArrayToLocal();return;case"wait":a.waitForJob(b[c].job);break;default:}e.job_a.push(a),e.copyJobArrayToLocal()},c}(),g=function(a,b){var c={},d={};return d.compare={},d.action={},c.eliminate=function(){return"eliminate"},c.update=function(){return"update"},c.dontAccept=function(){return"dont accept"},c.wait=function(){return"wait"},c.none=function(){return"none"},c.default_action=c.none,c.default_compare=function(a,b){return a.getCommand().getPath()===b.getCommand().getPath()&&JSON.stringify(a.getStorage().serialized())===JSON.stringify(b.getStorage().serialized())},d.getAction=function(a,b){var e,f,g;return e=a.getCommand().getLabel(),f=b.getCommand().getLabel(),g=a.getStatus().getLabel()==="on going"?"on going":"not on going",d.action[e]&&d.action[e][g]&&d.action[e][g][f]?d.action[e][g][f](a,b):c.default_action(a,b)},d.canCompare=function(a,b){var e=a.getCommand().getLabel(),f=b.getCommand().getLabel();return d.compare[e]&&d.compare[f]?d.compare[e][f](a,b):c.default_compare(a,b)},c.validateJobAccordingToJob=function(a,b){return d.canCompare(a,b)?{action:d.getAction(a,b),job:a}:{action:c.default_action(a,b),job:a}},c.addActionRule=function(a,b,c,e){var f=b?"on going":"not on going";d.action[a]=d.action[a]||{},d.action[a][f]=d.action[a][f]||{},d.action[a][f][c]=e},c.addCompareRule=function(a,b,c){d.compare[a]=d.compare[a]||{},d.compare[a][b]=c},c.addActionRule("saveDocument",!0,"saveDocument",function(a,b){return a.getCommand().getContent()===b.getCommand().getContent()?c.dontAccept():c.wait()}),c.addActionRule("saveDocument",!0,"loadDocument",c.wait),c.addActionRule("saveDocument",!0,"removeDocument",c.wait),c.addActionRule("saveDocument",!1,"saveDocument",c.update),c.addActionRule("saveDocument",!1,"loadDocument",c.wait),c.addActionRule("saveDocument",!1,"removeDocument",c.eliminate),c.addActionRule("loadDocument",!0,"saveDocument",c.wait),c.addActionRule("loadDocument",!0,"loadDocument",c.dontAccept),c.addActionRule("loadDocument",!0,"removeDocument",c.wait),c.addActionRule("loadDocument",!1,"saveDocument",c.wait),c.addActionRule("loadDocument",!1,"loadDocument",c.update),c.addActionRule("loadDocument",!1,"removeDocument",c.wait),c.addActionRule("removeDocument",!0,"loadDocument",c.dontAccept),c.addActionRule("removeDocument",!0,"removeDocument",c.dontAccept),c.addActionRule("removeDocument",!1,"saveDocument",c.eliminate),c.addActionRule("removeDocument",!1,"loadDocument",c.dontAccept),c.addActionRule("removeDocument",!1,"removeDocument",c.update),c.addActionRule("getDocumentList",!0,"getDocumentList",c.dontAccept),c.addActionRule("getDocumentList",!1,"getDocumentList",c.update),c}(),h={};a=a||{},b=b||{};var i={},o="jio/id_array";return i.id=null,b.jobManager=f,b.jobIdHandler=e,i.storage=x.storage(a,b),i.init=function(){if(i.id===null){var a,b=LocalOrCookieStorage.getItem(o)||[];i.id=1;for(a=0;a<b.length;a+=1)b[a]>=i.id&&(i.id=b[a]+1);b.push(i.id),LocalOrCookieStorage.setItem(o,b),c.setId(i.id),f.setId(i.id)}},h.start=function(){i.init(),c.start(),f.start()},h.stop=function(){f.stop()},h.close=function(){c.stop(),f.stop(),i.id=null},h.start(),h.getId=function(){return i.id},h.getJobRules=function(){return g},h.validateStorageDescription=function(a){return x.storage(a,b).isValid()},h.saveDocument=function(a,c,d,e){d=d||{},d.onResponse=d.onResponse||function(){},d.onDone=d.onDone||function(){},d.onFail=d.onFail||function(){},d.max_retry=d.max_retry||0,f.addJob(u({storage:e?x.storage(e,b):i.storage,command:n({path:a,content:c,option:d})},b))},h.loadDocument=function(a,c,d){c=c||{},c.onResponse=c.onResponse||function(){},c.onDone=c.onDone||function(){},c.onFail=c.onFail||function(){},c.max_retry=c.max_retry||0,c.metadata_only=c.metadata_only!==undefined?c.metadata_only:!1,f.addJob(u({storage:d?x.storage(d,b):i.storage,command:l({path:a,option:c})},b))},h.removeDocument=function(a,c,d){c=c||{},c.onResponse=c.onResponse||function(){},c.onDone=c.onDone||function(){},c.onFail=c.onFail||function(){},c.max_retry=c.max_retry||0,f.addJob(u({storage:d?x.storage(d,b):i.storage,command:m({path:a,option:c})},b))},h.getDocumentList=function(a,c,d){c=c||{},c.onResponse=c.onResponse||function(){},c.onDone=c.onDone||function(){},c.onFail=c.onFail||function(){},c.max_retry=c.max_retry||0,c.metadata_only=c.metadata_only!==undefined?c.metadata_only:!0,f.addJob(u({storage:d?x.storage(d,b):i.storage,command:k({path:a,option:c})},b))},h},x=function(a,b){var c={};a=a||{},b=b||{};var e={base:h,handler:i};return c.storage=function(a,b,c){a=a||{};var f=c||a.type||"base";if(!e[f])throw d({type:f,message:"Storage does not exists."});return e[f](a,b)},c.newJio=function(a){var b=a;return typeof b=="string"&&(b=JSON.parse(b)),b=b||{type:"base"},w(a)},c.addStorageType=function(a,b){b=b||function(){return null};if(e[a])throw d({type:a,message:"Already known."});e[a]=b},c}();return x}(); var jio=function(){var a=function(a,b){var c={};return a=a||{},b=b||{},c.name="jioException",c.message=a.message||"Unknown Reason.",c.toString=function(){return c.name+": "+c.message},c},b=function(b,c){var d=a(b,c);b=b||{};var e=b.command;return d.name="invalidCommandState",d.toString=function(){return d.name+": "+e.getLabel()+", "+d.message},d},c=function(b,c){var d=a(b,c);b=b||{};var e=b.storage.getType();return d.name="invalidStorage",d.toString=function(){return d.name+": "+'Type "'+e+'", '+d.message},d},d=function(b,c){var d=a(b,c),e=b.type;return d.name="invalidStorageType",d.toString=function(){return d.name+": "+e+", "+d.message},d},e=function(b,c){var d=a(b,c);return d.name="jobNotReadyException",d},f=function(b,c){var d=a(b,c);return d.name="tooMuchTriesJobException",d},g=function(b,c){var d=a(b,c);return d.name="invalidJobException",d},h=function(a,b){var d={};a=a||{},b=b||{};var e={};return e.type=a.type||"",d.getType=function(){return e.type},d.setType=function(a){e.type=a},d.execute=function(a){d.validate(a),d.done=a.done,d.fail=a.fail,a.executeOn(d)},d.isValid=function(){return!0},d.validate=function(a){var b=d.validateState();if(b)throw c({storage:d,message:b});a.validate(d)},d.serialized=function(){return{type:d.getType()}},d.saveDocument=function(a){throw c({storage:d,message:"Unknown storage."})},d.loadDocument=function(a){d.saveDocument()},d.removeDocument=function(a){d.saveDocument()},d.getDocumentList=function(a){d.saveDocument()},d.validateState=function(){return""},d.done=function(){},d.fail=function(){},d},i=function(a,b){a=a||{},b=b||{};var c=h(a,b);return c.newCommand=function(a,c){var d=c||{};return d.label=a,j(d,b)},c.newStorage=function(a){var c=a||{};return x.storage(c,b)},c.addJob=function(a,c){b.jobManager.addJob(u({storage:a,command:c},b))},c},j=function(a,c){var d={};a=a||{},c=c||{};var e={};return e.commandlist={saveDocument:n,loadDocument:l,removeDocument:m,getDocumentList:k},a.label&&e.commandlist[a.label]?(e.label=a.label,delete a.label,e.commandlist[e.label](a,c)):(e.path=a.path||"",e.tried=0,e.option=a.option||{},e.respond=e.option.onResponse||function(){},e.done=e.option.onDone||function(){},e.fail=e.option.onFail||function(){},e.retry=function(){d.setMaxRetry(-1),d.fail({status:0,statusText:"Fail Retry",message:"Impossible to retry."})},e.end=function(){},d.getLabel=function(){return"command"},d.getPath=function(){return e.path},d.getOption=function(a){return e.option[a]},d.validate=function(a){d.validateState()},d.getTried=function(){return e.tried},d.setMaxRetry=function(a){e.option.max_retry=a},d.execute=function(a){d.validate(a),e.tried++,a.execute(d)},d.executeOn=function(a){},d.validateState=function(){if(e.path==="")throw b({command:d,message:"Path is empty"})},d.done=function(a){e.respond({status:p(),value:a}),e.done(a),e.end()},d.fail=function(a){e.option.max_retry===0||e.tried<e.option.max_retry?e.retry():(e.respond({status:q(),error:a}),e.fail(a),e.end())},d.onResponseDo=function(a){if(a)e.respond=a;else return e.respond},d.onDoneDo=function(a){if(a)e.done=a;else return e.done},d.onFailDo=function(a){if(a)e.fail=a;else return e.fail},d.onEndDo=function(a){e.end=a},d.onRetryDo=function(a){e.retry=a},d.serialized=function(){return{label:d.getLabel(),tried:e.tried,max_retry:e.max_retry,path:e.path,option:d.cloneOption()}},d.canBeRestored=function(){return!0},d.clone=function(){return j(d.serialized(),c)},d.cloneOption=function(){var a,b={};for(a in e.option)b[a]=e.option[a];return b},d)},k=function(a,b){var c=j(a,b);a=a||{},b=b||{},c.getLabel=function(){return"getDocumentList"},c.executeOn=function(a){a.getDocumentList(c)},c.canBeRestored=function(){return!1};var d=c.done;return c.done=function(a){var b;if(a)for(b=0;b<a.length;b+=1)typeof a[b].last_modified!="number"&&(a[b].last_modified=(new Date(a[b].last_modified)).getTime()),typeof a[b].creation_date!="number"&&(a[b].creation_date=(new Date(a[b].creation_date)).getTime());d(a)},c},l=function(a,b){var c=j(a,b);a=a||{},b=b||{},c.getLabel=function(){return"loadDocument"},c.executeOn=function(a){a.loadDocument(c)},c.canBeRestored=function(){return!1};var d=c.done;return c.done=function(a){a&&(typeof a.last_modified!="number"&&(a.last_modified=(new Date(a.last_modified)).getTime()),typeof a.creation_date!="number"&&(a.creation_date=(new Date(a.creation_date)).getTime())),d(a)},c},m=function(a,b){var c=j(a,b);return a=a||{},b=b||{},c.getLabel=function(){return"removeDocument"},c.executeOn=function(a){a.removeDocument(c)},c},n=function(a,c){var d=j(a,c);a=a||{},c=c||{};var e={};e.content=a.content,d.getLabel=function(){return"saveDocument"},d.getContent=function(){return e.content};var f=d.validate;d.validate=function(a){if(typeof e.content!="string")throw b({command:d,message:"No data to save"});f(a)},d.executeOn=function(a){a.saveDocument(d)};var g=d.serialized;return d.serialized=function(){var a=g();return a.content=e.content,a},d},o=function(a,b){var c={};return a=a||{},b=b||{},c.getLabel=function(){return"job status"},c.canStart=function(){},c.canRestart=function(){},c.serialized=function(){return{label:c.getLabel()}},c.isWaitStatus=function(){return!1},c.isDone=function(){return!1},c},p=function(a,b){var c=o(a,b);return a=a||{},b=b||{},c.getLabel=function(){return"done"},c.canStart=function(){return!1},c.canRestart=function(){return!1},c.isDone=function(){return!0},c},q=function(a,b){var c=o(a,b);return a=a||{},b=b||{},c.getLabel=function(){return"fail"},c.canStart=function(){return!1},c.canRestart=function(){return!0},c},r=function(a,b){var c=o(a,b);return a=a||{},b=b||{},c.getLabel=function(){return"initial"},c.canStart=function(){return!0},c.canRestart=function(){return!0},c},s=function(a,b){var c=o(a,b);return a=a||{},b=b||{},c.getLabel=function(){return"on going"},c.canStart=function(){return!1},c.canRestart=function(){return!1},c},t=function(a,b){var c=o(a,b);a=a||{},b=b||{};var d={};return d.job_id_a=a.job_id_array||[],d.threshold=0,c.getLabel=function(){return"wait"},d.refreshJobIdArray=function(){var a=[],c;for(c=0;c<d.job_id_a.length;c+=1)b.jobManager.jobIdExists(d.job_id_a[c])&&a.push(d.job_id_a[c]);d.job_id_a=a},c.waitForJob=function(a){var b;for(b=0;b<d.job_id_a.length;b+=1)if(d.job_id_a[b]===a.getId())return;d.job_id_a.push(a.getId())},c.dontWaitForJob=function(a){var b,c=[];for(b=0;b<d.job_id_a.length;b+=1)d.job_id_a[b]!==a.getId()&&c.push(d.job_id_a[b]);d.job_id_a=c},c.waitForTime=function(a){d.threshold=Date.now()+a},c.stopWaitForTime=function(){d.threshold=0},c.canStart=function(){return d.refreshJobIdArray(),d.job_id_a.length===0&&Date.now()>=d.threshold},c.canRestart=function(){return c.canStart()},c.serialized=function(){return{label:c.getLabel(),waitfortime:d.threshold,waitforjob:d.job_id_a}},c.isWaitStatus=function(){return!0},c},u=function(a,b){var c={};a=a||{},b=b||{};var d={};return d.id=b.jobIdHandler.nextId(),d.command=a.command,d.storage=a.storage,d.status=r(),d.date=new Date,function(){if(!d.storage)throw g({job:c,message:"No storage set"});if(!d.command)throw g({job:c,message:"No command set"})}(),c.getCommand=function(){return d.command},c.getStatus=function(){return d.status},c.getId=function(){return d.id},c.getStorage=function(){return d.storage},c.getDate=function(){return d.date},c.isReady=function(){return d.tried===0?d.status.canStart():d.status.canRestart()},c.serialized=function(){return{id:d.id,date:d.date.getTime(),status:d.status.serialized(),command:d.command.serialized(),storage:d.storage.serialized()}},c.waitForJob=function(a){d.status.getLabel()!=="wait"&&(d.status=t({},b)),d.status.waitForJob(a)},c.dontWaitFor=function(a){d.status.getLabel()==="wait"&&d.status.dontWaitForJob(a)},c.waitForTime=function(a){d.status.getLabel()!=="wait"&&(d.status=t({},b)),d.status.waitForTime(a)},c.stopWaitForTime=function(){d.status.getLabel()==="wait"&&d.status.stopWaitForTime()},c.update=function(a){d.command.setMaxRetry(-1),d.command.fail({status:0,statusText:"Replaced",message:"Job has been replaced by another one."}),d.date=a.getDate(),d.command=a.getCommand(),d.status=a.getStatus()},c.execute=function(){if(d.max_retry!==0&&d.tried>=d.max_retry)throw f({job:c,message:"The job was invoked too much time."});if(!c.isReady())throw e({message:"Can not execute this job."});d.status=s(),d.command.onRetryDo(function(){var a=d.command.getTried();a=a*a*200,a>1e4&&(a=1e4),c.waitForTime(a)}),d.command.onEndDo(function(){b.jobManager.terminateJob(c)}),d.command.execute(d.storage)},c},v=function(a,b){var c={};a=a||{},b=b||{};var d=[],e=a.name||"",f=a.announcer||{};return c.add=function(a){d.push(a)},c.remove=function(a){var b,c=[];for(b=0;b<d.length;b+=1)d[b]!==a&&c.push(d[b]);d=c},c.register=function(){f.register(c)},c.unregister=function(){f.unregister(c)},c.trigger=function(a){var b;for(b=0;b<d.length;b++)d[b].apply(null,a)},c},w=function(a,b){var c=function(a,b){var c={};a=a||{},b=b||{};var d={};return d.id=a.id||0,d.interval=400,d.interval_id=null,d.touch=function(){LocalOrCookieStorage.setItem("jio/id/"+d.id,Date.now())},c.setId=function(a){d.id=a},c.setIntervalDelay=function(a){d.interval=a},c.getIntervalDelay=function(){return d.interval},c.start=function(){d.interval_id||(d.touch(),d.interval_id=setInterval(function(){d.touch()},d.interval))},c.stop=function(){d.interval_id!==null&&(clearInterval(d.interval_id),d.interval_id=null)},c}(),d=function(a,b){var c={};a=a||{},b=b||{};var d={};return c.register=function(a){d[a]||(d[a]=v())},c.unregister=function(a){d[a]&&delete d[a]},c.at=function(a){return d[a]},c.on=function(a,b){c.register(a),c.at(a).add(b)},c.trigger=function(a,b){c.at(a).trigger(b)},c}(),e=function(a,b){var c={};a=a||{},b=b||{};var d=0;return c.nextId=function(){return d=d+1,d},c}(),f=function(a,b){var c={};a=a||{},b=b||{};var d="jio/job_array",f={};return f.id=a.id,f.interval_id=null,f.interval=200,f.job_a=[],b.jobManager=c,b.jobIdHandler=e,f.getJobArrayName=function(){return d+"/"+f.id},f.getJobArray=function(){return LocalOrCookieStorage.getItem(f.getJobArrayName())||[]},f.copyJobArrayToLocal=function(){var a=[],b;for(b=0;b<f.job_a.length;b+=1)a.push(f.job_a[b].serialized());LocalOrCookieStorage.setItem(f.getJobArrayName(),a)},f.removeJob=function(a){var b,c=[];for(b=0;b<f.job_a.length;b+=1)f.job_a[b]!==a&&c.push(f.job_a[b]);f.job_a=c,f.copyJobArrayToLocal()},c.setId=function(a){f.id=a},c.start=function(){var a;f.interval_id===null&&(f.interval_id=setInterval(function(){f.restoreOldJio();for(a=0;a<f.job_a.length;a+=1)c.execute(f.job_a[a])},f.interval))},c.stop=function(){f.interval_id!==null&&(clearInterval(f.interval_id),f.interval_id=null,f.job_a.length===0&&LocalOrCookieStorage.deleteItem(f.getJobArrayName()))},f.restoreOldJio=function(){var a,b;f.lastrestore=f.lastrestore||0;if(f.lastrestore>Date.now()-2e3)return;b=LocalOrCookieStorage.getItem("jio/id_array")||[];for(a=0;a<b.length;a+=1)f.restoreOldJioId(b[a]);f.lastrestore=Date.now()},f.restoreOldJioId=function(a){var b;b=LocalOrCookieStorage.getItem("jio/id/"+a)||0,b<Date.now()-1e4&&(f.restoreOldJobFromJioId(a),f.removeOldJioId(a),f.removeJobArrayFromJioId(a))},f.restoreOldJobFromJioId=function(a){var d,e;e=LocalOrCookieStorage.getItem("jio/job_array/"+a)||[];for(d=0;d<e.length;d+=1){var f=j(e[d].command,b);f.canBeRestored()&&c.addJob(u({storage:x.storage(e[d].storage,b),command:f},b))}},f.removeOldJioId=function(a){var b,c,d=[];c=LocalOrCookieStorage.getItem("jio/id_array")||[];for(b=0;b<c.length;b+=1)c[b]!==a&&d.push(c[b]);LocalOrCookieStorage.setItem("jio/id_array",d),LocalOrCookieStorage.deleteItem("jio/id/"+a)},f.removeJobArrayFromJioId=function(a){LocalOrCookieStorage.deleteItem("jio/job_array/"+a)},c.execute=function(a){try{a.execute()}catch(b){switch(b.name){case"jobNotReadyException":break;case"tooMuchTriesJobException":break;default:throw b}}f.copyJobArrayToLocal()},c.jobIdExists=function(a){var b;for(b=0;b<f.job_a.length;b+=1)if(f.job_a[b].getId()===a)return!0;return!1},c.terminateJob=function(a){f.removeJob(a)},c.addJob=function(a){var b=c.validateJobAccordingToJobList(f.job_a,a);f.appendJob(a,b)},c.validateJobAccordingToJobList=function(a,b){var c,d=[];for(c=0;c<a.length;c+=1)d.push(g.validateJobAccordingToJob(a[c],b));return d},f.appendJob=function(a,b){var c;if(f.job_a.length!==b.length)throw new RangeError("Array out of bound");for(c=0;c<b.length;c+=1)if(b[c].action==="dont accept")return;for(c=0;c<b.length;c+=1)switch(b[c].action){case"eliminate":f.removeJob(b[c].job);break;case"update":b[c].job.update(a),f.copyJobArrayToLocal();return;case"wait":a.waitForJob(b[c].job);break;default:}f.job_a.push(a),f.copyJobArrayToLocal()},c}(),g=function(a,b){var c={},d={};return d.compare={},d.action={},c.eliminate=function(){return"eliminate"},c.update=function(){return"update"},c.dontAccept=function(){return"dont accept"},c.wait=function(){return"wait"},c.none=function(){return"none"},c.default_action=c.none,c.default_compare=function(a,b){return a.getCommand().getPath()===b.getCommand().getPath()&&JSON.stringify(a.getStorage().serialized())===JSON.stringify(b.getStorage().serialized())},d.getAction=function(a,b){var e,f,g;return e=a.getCommand().getLabel(),f=b.getCommand().getLabel(),g=a.getStatus().getLabel()==="on going"?"on going":"not on going",d.action[e]&&d.action[e][g]&&d.action[e][g][f]?d.action[e][g][f](a,b):c.default_action(a,b)},d.canCompare=function(a,b){var e=a.getCommand().getLabel(),f=b.getCommand().getLabel();return d.compare[e]&&d.compare[f]?d.compare[e][f](a,b):c.default_compare(a,b)},c.validateJobAccordingToJob=function(a,b){return d.canCompare(a,b)?{action:d.getAction(a,b),job:a}:{action:c.default_action(a,b),job:a}},c.addActionRule=function(a,b,c,e){var f=b?"on going":"not on going";d.action[a]=d.action[a]||{},d.action[a][f]=d.action[a][f]||{},d.action[a][f][c]=e},c.addCompareRule=function(a,b,c){d.compare[a]=d.compare[a]||{},d.compare[a][b]=c},c.addActionRule("saveDocument",!0,"saveDocument",function(a,b){return a.getCommand().getContent()===b.getCommand().getContent()?c.dontAccept():c.wait()}),c.addActionRule("saveDocument",!0,"loadDocument",c.wait),c.addActionRule("saveDocument",!0,"removeDocument",c.wait),c.addActionRule("saveDocument",!1,"saveDocument",c.update),c.addActionRule("saveDocument",!1,"loadDocument",c.wait),c.addActionRule("saveDocument",!1,"removeDocument",c.eliminate),c.addActionRule("loadDocument",!0,"saveDocument",c.wait),c.addActionRule("loadDocument",!0,"loadDocument",c.dontAccept),c.addActionRule("loadDocument",!0,"removeDocument",c.wait),c.addActionRule("loadDocument",!1,"saveDocument",c.wait),c.addActionRule("loadDocument",!1,"loadDocument",c.update),c.addActionRule("loadDocument",!1,"removeDocument",c.wait),c.addActionRule("removeDocument",!0,"loadDocument",c.dontAccept),c.addActionRule("removeDocument",!0,"removeDocument",c.dontAccept),c.addActionRule("removeDocument",!1,"saveDocument",c.eliminate),c.addActionRule("removeDocument",!1,"loadDocument",c.dontAccept),c.addActionRule("removeDocument",!1,"removeDocument",c.update),c.addActionRule("getDocumentList",!0,"getDocumentList",c.dontAccept),c.addActionRule("getDocumentList",!1,"getDocumentList",c.update),c}(),h={};a=a||{},b=b||{};var i={},o="jio/id_array";return i.id=null,b.jobManager=f,b.jobIdHandler=e,i.storage=x.storage(a,b),i.init=function(){if(i.id===null){var a,b=LocalOrCookieStorage.getItem(o)||[];i.id=1;for(a=0;a<b.length;a+=1)b[a]>=i.id&&(i.id=b[a]+1);b.push(i.id),LocalOrCookieStorage.setItem(o,b),c.setId(i.id),f.setId(i.id)}},h.start=function(){i.init(),c.start(),f.start()},h.stop=function(){f.stop()},h.close=function(){c.stop(),f.stop(),i.id=null},h.start(),h.getId=function(){return i.id},h.getJobRules=function(){return g},h.validateStorageDescription=function(a){return x.storage(a,b).isValid()},h.saveDocument=function(a,c,d,e){d=d||{},d.onResponse=d.onResponse||function(){},d.onDone=d.onDone||function(){},d.onFail=d.onFail||function(){},d.max_retry=d.max_retry||0,f.addJob(u({storage:e?x.storage(e,b):i.storage,command:n({path:a,content:c,option:d},b)},b))},h.loadDocument=function(a,c,d){c=c||{},c.onResponse=c.onResponse||function(){},c.onDone=c.onDone||function(){},c.onFail=c.onFail||function(){},c.max_retry=c.max_retry||0,c.metadata_only=c.metadata_only!==undefined?c.metadata_only:!1,f.addJob(u({storage:d?x.storage(d,b):i.storage,command:l({path:a,option:c},b)},b))},h.removeDocument=function(a,c,d){c=c||{},c.onResponse=c.onResponse||function(){},c.onDone=c.onDone||function(){},c.onFail=c.onFail||function(){},c.max_retry=c.max_retry||0,f.addJob(u({storage:d?x.storage(d,b):i.storage,command:m({path:a,option:c},b)},b))},h.getDocumentList=function(a,c,d){c=c||{},c.onResponse=c.onResponse||function(){},c.onDone=c.onDone||function(){},c.onFail=c.onFail||function(){},c.max_retry=c.max_retry||0,c.metadata_only=c.metadata_only!==undefined?c.metadata_only:!0,f.addJob(u({storage:d?x.storage(d,b):i.storage,command:k({path:a,option:c},b)},b))},h},x=function(a,b){var c={};a=a||{},b=b||{};var e={base:h,handler:i};return c.storage=function(a,b,c){a=a||{},b=b||{};var f=c||a.type||"base";if(!e[f])throw d({type:f,message:"Storage does not exists."});return e[f](a,b)},c.newJio=function(a){var b=a;return typeof b=="string"&&(b=JSON.parse(b)),b=b||{type:"base"},w(a)},c.addStorageType=function(a,b){b=b||function(){return null};if(e[a])throw d({type:a,message:"Already known."});e[a]=b},c}();return x}();
\ No newline at end of file \ No newline at end of file
/*! JIO Storage - v0.1.0 - 2012-06-14 /*! JIO Storage - v0.1.0 - 2012-06-15
* Copyright (c) 2012 Nexedi; Licensed */ * Copyright (c) 2012 Nexedi; Licensed */
(function(LocalOrCookieStorage, $, Base64, sjcl, Jio) { (function(LocalOrCookieStorage, $, Base64, sjcl, Jio) {
...@@ -464,6 +464,21 @@ var newReplicateStorage = function ( spec, my ) { ...@@ -464,6 +464,21 @@ var newReplicateStorage = function ( spec, my ) {
priv.storagelist = spec.storagelist || []; priv.storagelist = spec.storagelist || [];
priv.nb_storage = priv.storagelist.length; priv.nb_storage = priv.storagelist.length;
var super_serialized = that.serialized;
that.serialized = function () {
var o = super_serialized();
o.storagelist = priv.storagelist;
return o;
};
that.validateState = function () {
if (priv.storagelist.length === 0) {
return 'Need at least one parameter: "storagelist" '+
'containing at least one storage.';
}
return '';
};
priv.isTheLast = function () { priv.isTheLast = function () {
return (priv.return_value_array.length === priv.nb_storage); return (priv.return_value_array.length === priv.nb_storage);
}; };
...@@ -471,12 +486,10 @@ var newReplicateStorage = function ( spec, my ) { ...@@ -471,12 +486,10 @@ var newReplicateStorage = function ( spec, my ) {
priv.doJob = function (command,errormessage) { priv.doJob = function (command,errormessage) {
var done = false, error_array = [], i, var done = false, error_array = [], i,
onResponseDo = function (result) { onResponseDo = function (result) {
console.log ('respond');
priv.return_value_array.push(result); priv.return_value_array.push(result);
}, },
onFailDo = function (result) { onFailDo = function (result) {
if (!done) { if (!done) {
console.log ('fail');
error_array.push(result); error_array.push(result);
if (priv.isTheLast()) { if (priv.isTheLast()) {
that.fail ( that.fail (
...@@ -489,7 +502,6 @@ var newReplicateStorage = function ( spec, my ) { ...@@ -489,7 +502,6 @@ var newReplicateStorage = function ( spec, my ) {
}, },
onDoneDo = function (result) { onDoneDo = function (result) {
if (!done) { if (!done) {
console.log ('done');
done = true; done = true;
that.done (result); that.done (result);
} }
...@@ -497,7 +509,7 @@ var newReplicateStorage = function ( spec, my ) { ...@@ -497,7 +509,7 @@ var newReplicateStorage = function ( spec, my ) {
command.setMaxRetry (1); command.setMaxRetry (1);
for (i = 0; i < priv.nb_storage; i+= 1) { for (i = 0; i < priv.nb_storage; i+= 1) {
var newcommand = command.clone(); var newcommand = command.clone();
var newstorage = Jio.storage(priv.storagelist[i], my); var newstorage = that.newStorage(priv.storagelist[i]);
newcommand.onResponseDo (onResponseDo); newcommand.onResponseDo (onResponseDo);
newcommand.onFailDo (onFailDo); newcommand.onFailDo (onFailDo);
newcommand.onDoneDo (onDoneDo); newcommand.onDoneDo (onDoneDo);
...@@ -551,4 +563,534 @@ var newReplicateStorage = function ( spec, my ) { ...@@ -551,4 +563,534 @@ var newReplicateStorage = function ( spec, my ) {
}; };
Jio.addStorageType('replicate', newReplicateStorage); Jio.addStorageType('replicate', newReplicateStorage);
var newIndexStorage = function ( spec, my ) {
var that = Jio.storage( spec, my, 'handler' ), priv = {};
priv.secondstorage_spec = spec.storage || {type:'base'};
priv.secondstorage_string = JSON.stringify (priv.secondstorage_spec);
var storage_array_name = 'jio/indexed_storage_array';
var storage_file_array_name = 'jio/indexed_file_array/'+
priv.secondstorage_string;
var super_serialized = that.serialized;
that.serialized = function () {
var o = super_serialized();
o.storage = priv.secondstorage_spec;
return o;
};
that.validateState = function () {
if (priv.secondstorage_string === JSON.stringify ({type:'base'})) {
return 'Need at least one parameter: "storage" '+
'containing storage specifications.';
}
return '';
};
/**
* Check if the indexed storage array exists.
* @method isStorageArrayIndexed
* @return {boolean} true if exists, else false
*/
priv.isStorageArrayIndexed = function () {
return (LocalOrCookieStorage.getItem(
storage_array_name) ? true : false);
};
/**
* Returns a list of indexed storages.
* @method getIndexedStorageArray
* @return {array} The list of indexed storages.
*/
priv.getIndexedStorageArray = function () {
return LocalOrCookieStorage.getItem(
storage_array_name) || [];
};
/**
* Adds a storage to the indexed storage list.
* @method indexStorage
* @param {object/json} storage The new indexed storage.
*/
priv.indexStorage = function (storage) {
var indexed_storage_array = priv.getIndexedStorageArray();
indexed_storage_array.push(typeof storage === 'string'? storage:
JSON.stringify (storage));
LocalOrCookieStorage.setItem(storage_array_name,
indexed_storage_array);
};
/**
* Checks if a storage exists in the indexed storage list.
* @method isAnIndexedStorage
* @param {object/json} storage The storage to find.
* @return {boolean} true if found, else false
*/
priv.isAnIndexedStorage = function (storage) {
var json_storage = (typeof storage === 'string'?storage:
JSON.stringify(storage)),
i,l,array = priv.getIndexedStorageArray();
for (i = 0, l = array.length; i < l; i+= 1) {
if (JSON.stringify(array[i]) === json_storage) {
return true;
}
}
return false;
};
/**
* Checks if the file array exists.
* @method fileArrayExists
* @return {boolean} true if exists, else false
*/
priv.fileArrayExists = function () {
return (LocalOrCookieStorage.getItem (
storage_file_array_name) ? true : false);
};
/**
* Returns the file from the indexed storage but not there content.
* @method getFileArray
* @return {array} All the existing file.
*/
priv.getFileArray = function () {
return LocalOrCookieStorage.getItem(
storage_file_array_name) || [];
};
/**
* Sets the file array list.
* @method setFileArray
* @param {array} file_array The array containing files.
*/
priv.setFileArray = function (file_array) {
return LocalOrCookieStorage.setItem(
storage_file_array_name,
file_array);
};
/**
* Checks if the file already exists in the array.
* @method isFileIndexed
* @param {string} file_name The file we want to find.
* @return {boolean} true if found, else false
*/
priv.isFileIndexed = function (file_name) {
var i, l, array = priv.getFileArray();
for (i = 0, l = array.length; i < l; i+= 1) {
if (array[i].name === file_name){
return true;
}
}
return false;
};
/**
* Adds a file to the local file array.
* @method addFile
* @param {object} file The new file.
*/
priv.addFile = function (file) {
var file_array = priv.getFileArray();
file_array.push(file);
LocalOrCookieStorage.setItem(storage_file_array_name,
file_array);
};
/**
* Removes a file from the local file array.
* @method removeFile
* @param {string} file_name The file to remove.
*/
priv.removeFile = function (file_name) {
var i, l, array = priv.getFileArray(), new_array = [];
for (i = 0, l = array.length; i < l; i+= 1) {
if (array[i].name !== file_name) {
new_array.push(array[i]);
}
}
LocalOrCookieStorage.setItem(storage_file_array_name,
new_array);
};
/**
* Updates the storage.
* It will retreive all files from a storage. It is an asynchronous task
* so the update can be on going even if IndexedStorage has already
* returned the result.
* @method update
*/
priv.update = function () {
// retreive list before, and then retreive all files
var getlist_onDone = function (result) {
if (!priv.isAnIndexedStorage(priv.secondstorage_string)) {
priv.indexStorage(priv.secondstorage_string);
}
priv.setFileArray(result);
};
that.addJob ( that.newStorage (priv.secondstorage_spec),
that.newCommand ('getDocumentList',
{path:'.',
option:{onDone:getlist_onDone,
max_retry: 3}}) );
};
/**
* Saves a document.
* @method saveDocument
*/
that.saveDocument = function (command) {
var newcommand = command.clone();
newcommand.onResponseDo (function(){});
newcommand.onDoneDo (function (result) {
if (!priv.isFileIndexed(command.getPath())) {
priv.addFile({name:command.getPath(),
last_modified:0,creation_date:0});
}
priv.update();
that.done();
});
newcommand.onFailDo (function (result) {
that.fail(result);
});
that.addJob ( that.newStorage(priv.secondstorage_spec),
newcommand );
}; // end saveDocument
/**
* Loads a document.
* @method loadDocument
*/
that.loadDocument = function (command) {
var file_array, i, l, new_job,
loadOnDone = function (result) {
// if (file_array[i].last_modified !==
// result.return_value.last_modified ||
// file_array[i].creation_date !==
// result.return_value.creation_date) {
// // the file in the index storage is different than
// // the one in the second storage. priv.update will
// // take care of refresh the indexed storage
// }
that.done(result);
},
loadOnFail = function (result) {
that.fail(result);
},
secondLoadDocument = function () {
var newcommand = command.clone();
newcommand.onResponseDo (function(){});
newcommand.onFailDo (loadOnFail);
newcommand.onDoneDo (loadOnDone);
that.addJob ( that.newStorage(priv.secondstorage_spec),
newcommand );
};
priv.update();
if (command.getOption('metadata_only')) {
setTimeout(function () {
if (priv.fileArrayExists()) {
file_array = priv.getFileArray();
for (i = 0, l = file_array.length; i < l; i+= 1) {
if (file_array[i].name === command.getPath()) {
return that.done(file_array[i]);
}
}
} else {
secondLoadDocument();
}
},100);
} else {
secondLoadDocument();
}
}; // end loadDocument
/**
* Gets a document list.
* @method getDocumentList
*/
that.getDocumentList = function (command) {
var id, newcommand, timeout = false;
priv.update();
if (command.getOption('metadata_only')) {
id = setInterval(function () {
if (timeout) {
that.fail({status:0,statusText:'Timeout',
message:'The request has timed out.'});
clearInterval(id);
}
if (priv.fileArrayExists()) {
that.done(priv.getFileArray());
clearInterval(id);
}
},100);
setTimeout (function () {
timeout = true;
}, 10000); // 10 sec
} else {
newcommand = command.clone();
newcommand.onDoneDo (function (result) {
that.done(result);
});
newcommand.onFailDo (function (result) {
that.fail(result);
});
that.addJob ( that.newStorage (priv.secondstorage_spec),
newcommand );
}
}; // end getDocumentList
/**
* Removes a document.
* @method removeDocument
*/
that.removeDocument = function (command) {
var newcommand = command.clone();
newcommand.onResponseDo (function(){});
newcommand.onDoneDo (function (result) {
priv.removeFile(command.getPath());
priv.update();
that.done();
});
newcommand.onFailDo (function (result) {
that.fail(result);
});
that.addJob( that.newStorage(priv.secondstorage_spec),
newcommand );
};
return that;
};
Jio.addStorageType ('indexed', newIndexStorage);
var newCryptedStorage = function ( spec, my ) {
var that = Jio.storage( spec, my, 'handler' ), priv = {};
priv.username = spec.username || '';
priv.password = spec.password || '';
priv.secondstorage_spec = spec.storage || {type:'base'};
var super_serialized = that.serialized;
that.serialized = function () {
var o = super_serialized();
o.username = priv.username;
o.password = priv.password;
return o;
};
that.validateState = function () {
if (priv.username &&
JSON.stringify (priv.secondstorage_spec) ===
JSON.stringify ({type:'base'})) {
return '';
}
return 'Need at least two parameters: "username" and "storage".';
};
// TODO : IT IS NOT SECURE AT ALL!
// WE MUST REWORK CRYPTED STORAGE!
priv.encrypt_param_object = {
"iv":"kaprWwY/Ucr7pumXoTHbpA",
"v":1,
"iter":1000,
"ks":256,
"ts":128,
"mode":"ccm",
"adata":"",
"cipher":"aes",
"salt":"K4bmZG9d704"
};
priv.decrypt_param_object = {
"iv":"kaprWwY/Ucr7pumXoTHbpA",
"ks":256,
"ts":128,
"salt":"K4bmZG9d704"
};
priv.encrypt = function (data,callback,index) {
// end with a callback in order to improve encrypt to an
// asynchronous encryption.
var tmp = sjcl.encrypt (that.getStorageUserName()+':'+
that.getStoragePassword(), data,
priv.encrypt_param_object);
callback(JSON.parse(tmp).ct,index);
};
priv.decrypt = function (data,callback,index,key) {
var tmp, param = $.extend(true,{},priv.decrypt_param_object);
param.ct = data || '';
param = JSON.stringify (param);
try {
tmp = sjcl.decrypt (that.getStorageUserName()+':'+
that.getStoragePassword(),
param);
} catch (e) {
callback({status:0,statusText:'Decrypt Fail',
message:'Unable to decrypt.'},index,key);
return;
}
callback(tmp,index,key);
};
/**
* Saves a document.
* @method saveDocument
*/
that.saveDocument = function (command) {
var new_file_name, newfilecontent,
_1 = function () {
priv.encrypt(command.getPath(),function(res) {
new_file_name = res;
_2();
});
},
_2 = function () {
priv.encrypt(command.getContent(),function(res) {
newfilecontent = res;
_3();
});
},
_3 = function () {
var settings = that.cloneOption(), newcommand, newstorage;
settings.onResponse = function (){};
settings.onDone = function () { that.done(); };
settings.onFail = function (r) { that.fail(r); };
newcommand = that.newCommand(
{path:new_file_name,
content:newfilecontent,
option:settings});
newstorage = that.newStorage( priv.secondstorage_spec );
that.addJob ( newstorage, newcommand );
};
_1();
}; // end saveDocument
/**
* Loads a document.
* @method loadDocument
*/
that.loadDocument = function (command) {
var new_file_name, option,
_1 = function () {
priv.encrypt(command.getPath(),function(res) {
new_file_name = res;
_2();
});
},
_2 = function () {
var settings = command.cloneOption(), newcommand, newstorage;
settings.onResponse = function(){};
settings.onFail = loadOnFail;
settings.onDone = loadOnDone;
newcommand = that.newCommand (
{path:new_file_name,
option:settings});
newstorage = that.newStorage ( priv.secondstorage_spec );
that.addJob ( newstorage, newcommand );
},
loadOnDone = function (result) {
result.name = command.getPath();
if (command.getOption('metadata_only')) {
that.done(result);
} else {
priv.decrypt (result.content,function(res){
if (typeof res === 'object') {
that.fail({status:0,statusText:'Decrypt Fail',
message:'Unable to decrypt'});
} else {
result.content = res;
// content only: the second storage should
// manage content_only option, so it is not
// necessary to manage it.
that.done(result);
}
});
}
},
loadOnFail = function (result) {
// NOTE : we can re create an error object instead of
// keep the old ex:status=404,message="document 1y59gyl8g
// not found in localStorage"...
that.fail(result);
};
_1();
}; // end loadDocument
/**
* Gets a document list.
* @method getDocumentList
*/
that.getDocumentList = function (command) {
var new_job, i, l, cpt = 0, array, ok = true,
_1 = function () {
var newcommand = command.clone(),
newstorage = that.newStorage ( priv.secondstorage_spec );
newcommand.onResponseDo (getListOnResponse);
newcommand.onDoneDo (function(){});
newcommand.onFailDo (function(){});
that.addJob ( new_job );
},
getListOnResponse = function (result) {
if (result.status.isDone()) {
array = result.return_value;
for (i = 0, l = array.length; i < l; i+= 1) {
// cpt--;
priv.decrypt (array[i].name,
lastOnResponse,i,'name');
// priv.decrypt (array[i].content,
// lastOnResponse,i,'content');
}
} else {
that.fail(result.error);
}
},
lastOnResponse = function (res,index,key) {
var tmp;
cpt++;
if (typeof res === 'object') {
if (ok) {
that.fail({status:0,statusText:'Decrypt Fail',
message:'Unable to decrypt.'});
}
ok = false;
return;
}
array[index][key] = res;
if (cpt === l && ok) {
// this is the last callback
that.done(array);
}
};
_1();
}; // end getDocumentList
/**
* Removes a document.
* @method removeDocument
*/
that.removeDocument = function () {
var new_job, new_file_name,
_1 = function () {
priv.encrypt(that.getFileName(),function(res) {
new_file_name = res;
_2();
});
},
_2 = function () {
new_job = that.cloneJob();
new_job.name = new_file_name;
new_job.storage = that.getSecondStorage();
new_job.onResponse = removeOnResponse;
that.addJob(new_job);
},
removeOnResponse = function (result) {
if (result.status === 'done') {
that.done();
} else {
that.fail(result.error);
}
};
_1();
};
return that;
};
Jio.addStorageType('crypt', newCryptedStorage);
}( LocalOrCookieStorage, jQuery, Base64, sjcl, jio )); }( LocalOrCookieStorage, jQuery, Base64, sjcl, jio ));
/*! JIO Storage - v0.1.0 - 2012-06-14 /*! JIO Storage - v0.1.0 - 2012-06-15
* Copyright (c) 2012 Nexedi; Licensed */ * Copyright (c) 2012 Nexedi; Licensed */
(function(a,b,c,d,e){var f=function(b,c){var d=e.storage(b,c,"base"),f={};f.username=b.username||"",f.applicationname=b.applicationname||"untitled";var g="jio/local_user_array",h="jio/local_file_name_array/"+f.username+"/"+f.applicationname,i=d.serialized;return d.serialized=function(){var a=i();return a.applicationname=f.applicationname,a.username=f.username,a},d.validateState=function(){return f.username?"":'Need at least one parameter: "username".'},f.getUserArray=function(){return a.getItem(g)||[]},f.addUser=function(b){var c=f.getUserArray();c.push(b),a.setItem(g,c)},f.userExists=function(a){var b=f.getUserArray(),c,d;for(c=0,d=b.length;c<d;c+=1)if(b[c]===a)return!0;return!1},f.getFileNameArray=function(){return a.getItem(h)||[]},f.addFileName=function(b){var c=f.getFileNameArray();c.push(b),a.setItem(h,c)},f.removeFileName=function(b){var c,d,e=f.getFileNameArray(),g=[];for(c=0,d=e.length;c<d;c+=1)e[c]!==b&&g.push(e[c]);a.setItem(h,g)},d.saveDocument=function(b){setTimeout(function(){var c=null,e="jio/local/"+f.username+"/"+f.applicationname+"/"+b.getPath();c=a.getItem(e),c?(c.last_modified=Date.now(),c.content=b.getContent()):(c={name:b.getPath(),content:b.getContent(),creation_date:Date.now(),last_modified:Date.now()},f.userExists(f.username)||f.addUser(f.username),f.addFileName(b.getPath())),a.setItem(e,c),d.done()},100)},d.loadDocument=function(b){setTimeout(function(){var c=null;c=a.getItem("jio/local/"+f.username+"/"+f.applicationname+"/"+b.getPath()),c?(b.getOption("metadata_only")&&delete c.content,d.done(c)):d.fail(b,{status:404,statusText:"Not Found.",message:'Document "'+b.getPath()+'" not found in localStorage.'})},100)},d.getDocumentList=function(b){setTimeout(function(){var c=[],e=[],g,h,i="key",j="jio/local/"+f.username+"/"+f.applicationname,k={};e=f.getFileNameArray();for(g=0,h=e.length;g<h;g+=1)k=a.getItem(j+"/"+e[g]),k&&(b.getOption("metadata_only")?c.push({name:k.name,creation_date:k.creation_date,last_modified:k.last_modified}):c.push({name:k.name,content:k.content,creation_date:k.creation_date,last_modified:k.last_modified}));d.done(c)},100)},d.removeDocument=function(b){setTimeout(function(){var c="jio/local/"+f.username+"/"+f.applicationname+"/"+b.getPath();a.deleteItem(c),f.removeFileName(b.getPath()),d.done()},100)},d};e.addStorageType("local",f);var g=function(a,d){var f=e.storage(a,d,"base"),g={};g.username=a.username||"",g.applicationname=a.applicationname||"untitled",g.url=a.url||"",g.password=a.password||"";var h=f.serialized;return f.serialized=function(){var a=h();return a.username=g.username,a.applicationname=g.applicationname,a.url=g.url,a.password=g.password,a},f.validateState=function(){return g.username&&g.url?"":'Need at least 2 parameters: "username" and "url".'},f.saveDocument=function(a){b.ajax({url:g.url+"/dav/"+g.username+"/"+g.applicationname+"/"+a.getPath(),type:"PUT",data:a.getContent(),async:!0,dataType:"text",headers:{Authorization:"Basic "+c.encode(g.username+":"+g.password)},success:function(){f.done()},error:function(b){b.message='Cannot save "'+a.getPath()+'" into DAVStorage.',f.fail(b)}})},f.loadDocument=function(a){var d={},e=function(){b.ajax({url:g.url+"/dav/"+g.username+"/"+g.applicationname+"/"+a.getPath(),type:"GET",async:!0,dataType:"text",headers:{Authorization:"Basic "+c.encode(g.username+":"+g.password)},success:function(a){d.content=a,f.done(d)},error:function(b){b.status===404?b.message='Document "'+a.getPath()+'" not found in localStorage.':b.message='Cannot load "'+a.getPath()+'" from DAVStorage.',f.fail(b)}})};d.name=a.getPath(),b.ajax({url:g.url+"/dav/"+g.username+"/"+g.applicationname+"/"+a.getPath(),type:"PROPFIND",async:!0,dataType:"xml",headers:{Authorization:"Basic "+c.encode(g.username+":"+g.password)},success:function(c){b(c).find("lp1\\:getlastmodified, getlastmodified").each(function(){d.last_modified=b(this).text()}),b(c).find("lp1\\:creationdate, creationdate").each(function(){d.creation_date=b(this).text()}),a.getOption("metadata_only")?f.done(d):e()},error:function(b){b.message='Cannot load "'+a.getPath()+'" informations from DAVStorage.',f.fail(b)}})},f.getDocumentList=function(a){var d=[],e={},h=[];b.ajax({url:g.url+"/dav/"+g.username+"/"+g.applicationname+"/",async:!0,type:"PROPFIND",dataType:"xml",headers:{Authorization:"Basic "+c.encode(g.username+":"+g.password),Depth:"1"},success:function(a){b(a).find("D\\:response, response").each(function(a,c){if(a>0){e={},b(c).find("D\\:href, href").each(function(){h=b(this).text().split("/"),e.name=h[h.length-1]?h[h.length-1]:h[h.length-2]+"/"});if(e.name===".htaccess"||e.name===".htpasswd")return;b(c).find("lp1\\:getlastmodified, getlastmodified").each(function(){e.last_modified=b(this).text()}),b(c).find("lp1\\:creationdate, creationdate").each(function(){e.creation_date=b(this).text()}),d.push(e)}}),f.done(d)},error:function(a){a.message="Cannot get a document list from DAVStorage.",f.fail(a)}})},f.removeDocument=function(a){b.ajax({url:g.url+"/dav/"+g.username+"/"+g.applicationname+"/"+a.getPath(),type:"DELETE",async:!0,headers:{Authorization:"Basic "+c.encode(g.username+":"+g.password)},success:function(){f.done()},error:function(a){a.status===404?f.done():(a.message='Cannot remove "'+f.getFileName()+'" from DAVStorage.',f.fail(a))}})},f};e.addStorageType("dav",g);var h=function(a,b){var c=e.storage(a,b,"handler"),d={};return d.return_value_array=[],d.storagelist=a.storagelist||[],d.nb_storage=d.storagelist.length,d.isTheLast=function(){return d.return_value_array.length===d.nb_storage},d.doJob=function(a,f){var g=!1,h=[],i,j=function(a){console.log("respond"),d.return_value_array.push(a)},k=function(a){g||(console.log("fail"),h.push(a),d.isTheLast()&&c.fail({status:207,statusText:"Multi-Status",message:f,array:h}))},l=function(a){g||(console.log("done"),g=!0,c.done(a))};a.setMaxRetry(1);for(i=0;i<d.nb_storage;i+=1){var m=a.clone(),n=e.storage(d.storagelist[i],b);m.onResponseDo(j),m.onFailDo(k),m.onDoneDo(l),c.addJob(n,m)}},c.saveDocument=function(a){d.doJob(a.clone(),'All save "'+a.getPath()+'" requests have failed.')},c.loadDocument=function(a){d.doJob(a.clone(),'All load "'+a.getPath()+'" requests have failed.')},c.getDocumentList=function(a){d.doJob(a.clone(),"All get document list requests have failed.")},c.removeDocument=function(a){d.doJob(a.clone(),'All remove "'+a.getPath()+'" requests have failed.')},c};e.addStorageType("replicate",h)})(LocalOrCookieStorage,jQuery,Base64,sjcl,jio); (function(a,b,c,d,e){var f=function(b,c){var d=e.storage(b,c,"base"),f={};f.username=b.username||"",f.applicationname=b.applicationname||"untitled";var g="jio/local_user_array",h="jio/local_file_name_array/"+f.username+"/"+f.applicationname,i=d.serialized;return d.serialized=function(){var a=i();return a.applicationname=f.applicationname,a.username=f.username,a},d.validateState=function(){return f.username?"":'Need at least one parameter: "username".'},f.getUserArray=function(){return a.getItem(g)||[]},f.addUser=function(b){var c=f.getUserArray();c.push(b),a.setItem(g,c)},f.userExists=function(a){var b=f.getUserArray(),c,d;for(c=0,d=b.length;c<d;c+=1)if(b[c]===a)return!0;return!1},f.getFileNameArray=function(){return a.getItem(h)||[]},f.addFileName=function(b){var c=f.getFileNameArray();c.push(b),a.setItem(h,c)},f.removeFileName=function(b){var c,d,e=f.getFileNameArray(),g=[];for(c=0,d=e.length;c<d;c+=1)e[c]!==b&&g.push(e[c]);a.setItem(h,g)},d.saveDocument=function(b){setTimeout(function(){var c=null,e="jio/local/"+f.username+"/"+f.applicationname+"/"+b.getPath();c=a.getItem(e),c?(c.last_modified=Date.now(),c.content=b.getContent()):(c={name:b.getPath(),content:b.getContent(),creation_date:Date.now(),last_modified:Date.now()},f.userExists(f.username)||f.addUser(f.username),f.addFileName(b.getPath())),a.setItem(e,c),d.done()},100)},d.loadDocument=function(b){setTimeout(function(){var c=null;c=a.getItem("jio/local/"+f.username+"/"+f.applicationname+"/"+b.getPath()),c?(b.getOption("metadata_only")&&delete c.content,d.done(c)):d.fail(b,{status:404,statusText:"Not Found.",message:'Document "'+b.getPath()+'" not found in localStorage.'})},100)},d.getDocumentList=function(b){setTimeout(function(){var c=[],e=[],g,h,i="key",j="jio/local/"+f.username+"/"+f.applicationname,k={};e=f.getFileNameArray();for(g=0,h=e.length;g<h;g+=1)k=a.getItem(j+"/"+e[g]),k&&(b.getOption("metadata_only")?c.push({name:k.name,creation_date:k.creation_date,last_modified:k.last_modified}):c.push({name:k.name,content:k.content,creation_date:k.creation_date,last_modified:k.last_modified}));d.done(c)},100)},d.removeDocument=function(b){setTimeout(function(){var c="jio/local/"+f.username+"/"+f.applicationname+"/"+b.getPath();a.deleteItem(c),f.removeFileName(b.getPath()),d.done()},100)},d};e.addStorageType("local",f);var g=function(a,d){var f=e.storage(a,d,"base"),g={};g.username=a.username||"",g.applicationname=a.applicationname||"untitled",g.url=a.url||"",g.password=a.password||"";var h=f.serialized;return f.serialized=function(){var a=h();return a.username=g.username,a.applicationname=g.applicationname,a.url=g.url,a.password=g.password,a},f.validateState=function(){return g.username&&g.url?"":'Need at least 2 parameters: "username" and "url".'},f.saveDocument=function(a){b.ajax({url:g.url+"/dav/"+g.username+"/"+g.applicationname+"/"+a.getPath(),type:"PUT",data:a.getContent(),async:!0,dataType:"text",headers:{Authorization:"Basic "+c.encode(g.username+":"+g.password)},success:function(){f.done()},error:function(b){b.message='Cannot save "'+a.getPath()+'" into DAVStorage.',f.fail(b)}})},f.loadDocument=function(a){var d={},e=function(){b.ajax({url:g.url+"/dav/"+g.username+"/"+g.applicationname+"/"+a.getPath(),type:"GET",async:!0,dataType:"text",headers:{Authorization:"Basic "+c.encode(g.username+":"+g.password)},success:function(a){d.content=a,f.done(d)},error:function(b){b.status===404?b.message='Document "'+a.getPath()+'" not found in localStorage.':b.message='Cannot load "'+a.getPath()+'" from DAVStorage.',f.fail(b)}})};d.name=a.getPath(),b.ajax({url:g.url+"/dav/"+g.username+"/"+g.applicationname+"/"+a.getPath(),type:"PROPFIND",async:!0,dataType:"xml",headers:{Authorization:"Basic "+c.encode(g.username+":"+g.password)},success:function(c){b(c).find("lp1\\:getlastmodified, getlastmodified").each(function(){d.last_modified=b(this).text()}),b(c).find("lp1\\:creationdate, creationdate").each(function(){d.creation_date=b(this).text()}),a.getOption("metadata_only")?f.done(d):e()},error:function(b){b.message='Cannot load "'+a.getPath()+'" informations from DAVStorage.',f.fail(b)}})},f.getDocumentList=function(a){var d=[],e={},h=[];b.ajax({url:g.url+"/dav/"+g.username+"/"+g.applicationname+"/",async:!0,type:"PROPFIND",dataType:"xml",headers:{Authorization:"Basic "+c.encode(g.username+":"+g.password),Depth:"1"},success:function(a){b(a).find("D\\:response, response").each(function(a,c){if(a>0){e={},b(c).find("D\\:href, href").each(function(){h=b(this).text().split("/"),e.name=h[h.length-1]?h[h.length-1]:h[h.length-2]+"/"});if(e.name===".htaccess"||e.name===".htpasswd")return;b(c).find("lp1\\:getlastmodified, getlastmodified").each(function(){e.last_modified=b(this).text()}),b(c).find("lp1\\:creationdate, creationdate").each(function(){e.creation_date=b(this).text()}),d.push(e)}}),f.done(d)},error:function(a){a.message="Cannot get a document list from DAVStorage.",f.fail(a)}})},f.removeDocument=function(a){b.ajax({url:g.url+"/dav/"+g.username+"/"+g.applicationname+"/"+a.getPath(),type:"DELETE",async:!0,headers:{Authorization:"Basic "+c.encode(g.username+":"+g.password)},success:function(){f.done()},error:function(a){a.status===404?f.done():(a.message='Cannot remove "'+f.getFileName()+'" from DAVStorage.',f.fail(a))}})},f};e.addStorageType("dav",g);var h=function(a,b){var c=e.storage(a,b,"handler"),d={};d.return_value_array=[],d.storagelist=a.storagelist||[],d.nb_storage=d.storagelist.length;var f=c.serialized;return c.serialized=function(){var a=f();return a.storagelist=d.storagelist,a},c.validateState=function(){return d.storagelist.length===0?'Need at least one parameter: "storagelist" containing at least one storage.':""},d.isTheLast=function(){return d.return_value_array.length===d.nb_storage},d.doJob=function(a,b){var e=!1,f=[],g,h=function(a){d.return_value_array.push(a)},i=function(a){e||(f.push(a),d.isTheLast()&&c.fail({status:207,statusText:"Multi-Status",message:b,array:f}))},j=function(a){e||(e=!0,c.done(a))};a.setMaxRetry(1);for(g=0;g<d.nb_storage;g+=1){var k=a.clone(),l=c.newStorage(d.storagelist[g]);k.onResponseDo(h),k.onFailDo(i),k.onDoneDo(j),c.addJob(l,k)}},c.saveDocument=function(a){d.doJob(a.clone(),'All save "'+a.getPath()+'" requests have failed.')},c.loadDocument=function(a){d.doJob(a.clone(),'All load "'+a.getPath()+'" requests have failed.')},c.getDocumentList=function(a){d.doJob(a.clone(),"All get document list requests have failed.")},c.removeDocument=function(a){d.doJob(a.clone(),'All remove "'+a.getPath()+'" requests have failed.')},c};e.addStorageType("replicate",h);var i=function(b,c){var d=e.storage(b,c,"handler"),f={};f.secondstorage_spec=b.storage||{type:"base"},f.secondstorage_string=JSON.stringify(f.secondstorage_spec);var g="jio/indexed_storage_array",h="jio/indexed_file_array/"+f.secondstorage_string,i=d.serialized;return d.serialized=function(){var a=i();return a.storage=f.secondstorage_spec,a},d.validateState=function(){return f.secondstorage_string===JSON.stringify({type:"base"})?'Need at least one parameter: "storage" containing storage specifications.':""},f.isStorageArrayIndexed=function(){return a.getItem(g)?!0:!1},f.getIndexedStorageArray=function(){return a.getItem(g)||[]},f.indexStorage=function(b){var c=f.getIndexedStorageArray();c.push(typeof b=="string"?b:JSON.stringify(b)),a.setItem(g,c)},f.isAnIndexedStorage=function(a){var b=typeof a=="string"?a:JSON.stringify(a),c,d,e=f.getIndexedStorageArray();for(c=0,d=e.length;c<d;c+=1)if(JSON.stringify(e[c])===b)return!0;return!1},f.fileArrayExists=function(){return a.getItem(h)?!0:!1},f.getFileArray=function(){return a.getItem(h)||[]},f.setFileArray=function(b){return a.setItem(h,b)},f.isFileIndexed=function(a){var b,c,d=f.getFileArray();for(b=0,c=d.length;b<c;b+=1)if(d[b].name===a)return!0;return!1},f.addFile=function(b){var c=f.getFileArray();c.push(b),a.setItem(h,c)},f.removeFile=function(b){var c,d,e=f.getFileArray(),g=[];for(c=0,d=e.length;c<d;c+=1)e[c].name!==b&&g.push(e[c]);a.setItem(h,g)},f.update=function(){var a=function(a){f.isAnIndexedStorage(f.secondstorage_string)||f.indexStorage(f.secondstorage_string),f.setFileArray(a)};d.addJob(d.newStorage(f.secondstorage_spec),d.newCommand("getDocumentList",{path:".",option:{onDone:a,max_retry:3}}))},d.saveDocument=function(a){var b=a.clone();b.onResponseDo(function(){}),b.onDoneDo(function(b){f.isFileIndexed(a.getPath())||f.addFile({name:a.getPath(),last_modified:0,creation_date:0}),f.update(),d.done()}),b.onFailDo(function(a){d.fail(a)}),d.addJob(d.newStorage(f.secondstorage_spec),b)},d.loadDocument=function(a){var b,c,e,g,h=function(a){d.done(a)},i=function(a){d.fail(a)},j=function(){var b=a.clone();b.onResponseDo(function(){}),b.onFailDo(i),b.onDoneDo(h),d.addJob(d.newStorage(f.secondstorage_spec),b)};f.update(),a.getOption("metadata_only")?setTimeout(function(){if(f.fileArrayExists()){b=f.getFileArray();for(c=0,e=b.length;c<e;c+=1)if(b[c].name===a.getPath())return d.done(b[c])}else j()},100):j()},d.getDocumentList=function(a){var b,c,e=!1;f.update(),a.getOption("metadata_only")?(b=setInterval(function(){e&&(d.fail({status:0,statusText:"Timeout",message:"The request has timed out."}),clearInterval(b)),f.fileArrayExists()&&(d.done(f.getFileArray()),clearInterval(b))},100),setTimeout(function(){e=!0},1e4)):(c=a.clone(),c.onDoneDo(function(a){d.done(a)}),c.onFailDo(function(a){d.fail(a)}),d.addJob(d.newStorage(f.secondstorage_spec),c))},d.removeDocument=function(a){var b=a.clone();b.onResponseDo(function(){}),b.onDoneDo(function(b){f.removeFile(a.getPath()),f.update(),d.done()}),b.onFailDo(function(a){d.fail(a)}),d.addJob(d.newStorage(f.secondstorage_spec),b)},d};e.addStorageType("indexed",i);var j=function(a,c){var f=e.storage(a,c,"handler"),g={};g.username=a.username||"",g.password=a.password||"",g.secondstorage_spec=a.storage||{type:"base"};var h=f.serialized;return f.serialized=function(){var a=h();return a.username=g.username,a.password=g.password,a},f.validateState=function(){return g.username&&JSON.stringify(g.secondstorage_spec)===JSON.stringify({type:"base"})?"":'Need at least two parameters: "username" and "storage".'},g.encrypt_param_object={iv:"kaprWwY/Ucr7pumXoTHbpA",v:1,iter:1e3,ks:256,ts:128,mode:"ccm",adata:"",cipher:"aes",salt:"K4bmZG9d704"},g.decrypt_param_object={iv:"kaprWwY/Ucr7pumXoTHbpA",ks:256,ts:128,salt:"K4bmZG9d704"},g.encrypt=function(a,b,c){var e=d.encrypt(f.getStorageUserName()+":"+f.getStoragePassword(),a,g.encrypt_param_object);b(JSON.parse(e).ct,c)},g.decrypt=function(a,c,e,h){var i,j=b.extend(!0,{},g.decrypt_param_object);j.ct=a||"",j=JSON.stringify(j);try{i=d.decrypt(f.getStorageUserName()+":"+f.getStoragePassword(),j)}catch(k){c({status:0,statusText:"Decrypt Fail",message:"Unable to decrypt."},e,h);return}c(i,e,h)},f.saveDocument=function(a){var b,c,d=function(){g.encrypt(a.getPath(),function(a){b=a,e()})},e=function(){g.encrypt(a.getContent(),function(a){c=a,h()})},h=function(){var a=f.cloneOption(),d,e;a.onResponse=function(){},a.onDone=function(){f.done()},a.onFail=function(a){f.fail(a)},d=f.newCommand({path:b,content:c,option:a}),e=f.newStorage(g.secondstorage_spec),f.addJob(e,d)};d()},f.loadDocument=function(a){var b,c,d=function(){g.encrypt(a.getPath(),function(a){b=a,e()})},e=function(){var c=a.cloneOption(),d,e;c.onResponse=function(){},c.onFail=i,c.onDone=h,d=f.newCommand({path:b,option:c}),e=f.newStorage(g.secondstorage_spec),f.addJob(e,d)},h=function(b){b.name=a.getPath(),a.getOption("metadata_only")?f.done(b):g.decrypt(b.content,function(a){typeof a=="object"?f.fail({status:0,statusText:"Decrypt Fail",message:"Unable to decrypt"}):(b.content=a,f.done(b))})},i=function(a){f.fail(a)};d()},f.getDocumentList=function(a){var b,c,d,e=0,h,i=!0,j=function(){var c=a.clone(),d=f.newStorage(g.secondstorage_spec);c.onResponseDo(k),c.onDoneDo(function(){}),c.onFailDo(function(){}),f.addJob(b)},k=function(a){if(a.status.isDone()){h=a.return_value;for(c=0,d=h.length;c<d;c+=1)g.decrypt(h[c].name,l,c,"name")}else f.fail(a.error)},l=function(a,b,c){var g;e++;if(typeof a=="object"){i&&f.fail({status:0,statusText:"Decrypt Fail",message:"Unable to decrypt."}),i=!1;return}h[b][c]=a,e===d&&i&&f.done(h)};j()},f.removeDocument=function(){var a,b,c=function(){g.encrypt(f.getFileName(),function(a){b=a,d()})},d=function(){a=f.cloneJob(),a.name=b,a.storage=f.getSecondStorage(),a.onResponse=e,f.addJob(a)},e=function(a){a.status==="done"?f.done():f.fail(a.error)};c()},f};e.addStorageType("crypt",j)})(LocalOrCookieStorage,jQuery,Base64,sjcl,jio);
\ No newline at end of file \ No newline at end of file
auto: grunt
check-syntax: grunt
grunt:
make -C ../../grunt/*_gruntJIOStorage > /dev/null 2>&1
var newIndexStorage = function ( spec, my ) {
var that = Jio.storage( spec, my, 'handler' ), priv = {};
priv.secondstorage_spec = spec.storage || {type:'base'};
priv.secondstorage_string = JSON.stringify (priv.secondstorage_spec);
var storage_array_name = 'jio/indexed_storage_array';
var storage_file_array_name = 'jio/indexed_file_array/'+
priv.secondstorage_string;
var super_serialized = that.serialized;
that.serialized = function () {
var o = super_serialized();
o.storage = priv.secondstorage_spec;
return o;
};
that.validateState = function () {
if (priv.secondstorage_string === JSON.stringify ({type:'base'})) {
return 'Need at least one parameter: "storage" '+
'containing storage specifications.';
}
return '';
};
/**
* Check if the indexed storage array exists.
* @method isStorageArrayIndexed
* @return {boolean} true if exists, else false
*/
priv.isStorageArrayIndexed = function () {
return (LocalOrCookieStorage.getItem(
storage_array_name) ? true : false);
};
/**
* Returns a list of indexed storages.
* @method getIndexedStorageArray
* @return {array} The list of indexed storages.
*/
priv.getIndexedStorageArray = function () {
return LocalOrCookieStorage.getItem(
storage_array_name) || [];
};
/**
* Adds a storage to the indexed storage list.
* @method indexStorage
* @param {object/json} storage The new indexed storage.
*/
priv.indexStorage = function (storage) {
var indexed_storage_array = priv.getIndexedStorageArray();
indexed_storage_array.push(typeof storage === 'string'? storage:
JSON.stringify (storage));
LocalOrCookieStorage.setItem(storage_array_name,
indexed_storage_array);
};
/**
* Checks if a storage exists in the indexed storage list.
* @method isAnIndexedStorage
* @param {object/json} storage The storage to find.
* @return {boolean} true if found, else false
*/
priv.isAnIndexedStorage = function (storage) {
var json_storage = (typeof storage === 'string'?storage:
JSON.stringify(storage)),
i,l,array = priv.getIndexedStorageArray();
for (i = 0, l = array.length; i < l; i+= 1) {
if (JSON.stringify(array[i]) === json_storage) {
return true;
}
}
return false;
};
/**
* Checks if the file array exists.
* @method fileArrayExists
* @return {boolean} true if exists, else false
*/
priv.fileArrayExists = function () {
return (LocalOrCookieStorage.getItem (
storage_file_array_name) ? true : false);
};
/**
* Returns the file from the indexed storage but not there content.
* @method getFileArray
* @return {array} All the existing file.
*/
priv.getFileArray = function () {
return LocalOrCookieStorage.getItem(
storage_file_array_name) || [];
};
/**
* Sets the file array list.
* @method setFileArray
* @param {array} file_array The array containing files.
*/
priv.setFileArray = function (file_array) {
return LocalOrCookieStorage.setItem(
storage_file_array_name,
file_array);
};
/**
* Checks if the file already exists in the array.
* @method isFileIndexed
* @param {string} file_name The file we want to find.
* @return {boolean} true if found, else false
*/
priv.isFileIndexed = function (file_name) {
var i, l, array = priv.getFileArray();
for (i = 0, l = array.length; i < l; i+= 1) {
if (array[i].name === file_name){
return true;
}
}
return false;
};
/**
* Adds a file to the local file array.
* @method addFile
* @param {object} file The new file.
*/
priv.addFile = function (file) {
var file_array = priv.getFileArray();
file_array.push(file);
LocalOrCookieStorage.setItem(storage_file_array_name,
file_array);
};
/**
* Removes a file from the local file array.
* @method removeFile
* @param {string} file_name The file to remove.
*/
priv.removeFile = function (file_name) {
var i, l, array = priv.getFileArray(), new_array = [];
for (i = 0, l = array.length; i < l; i+= 1) {
if (array[i].name !== file_name) {
new_array.push(array[i]);
}
}
LocalOrCookieStorage.setItem(storage_file_array_name,
new_array);
};
/**
* Updates the storage.
* It will retreive all files from a storage. It is an asynchronous task
* so the update can be on going even if IndexedStorage has already
* returned the result.
* @method update
*/
priv.update = function () {
// retreive list before, and then retreive all files
var getlist_onDone = function (result) {
if (!priv.isAnIndexedStorage(priv.secondstorage_string)) {
priv.indexStorage(priv.secondstorage_string);
}
priv.setFileArray(result);
};
that.addJob ( that.newStorage (priv.secondstorage_spec),
that.newCommand ('getDocumentList',
{path:'.',
option:{onDone:getlist_onDone,
max_retry: 3}}) );
};
/**
* Saves a document.
* @method saveDocument
*/
that.saveDocument = function (command) {
var newcommand = command.clone();
newcommand.onResponseDo (function(){});
newcommand.onDoneDo (function (result) {
if (!priv.isFileIndexed(command.getPath())) {
priv.addFile({name:command.getPath(),
last_modified:0,creation_date:0});
}
priv.update();
that.done();
});
newcommand.onFailDo (function (result) {
that.fail(result);
});
that.addJob ( that.newStorage(priv.secondstorage_spec),
newcommand );
}; // end saveDocument
/**
* Loads a document.
* @method loadDocument
*/
that.loadDocument = function (command) {
var file_array, i, l, new_job,
loadOnDone = function (result) {
// if (file_array[i].last_modified !==
// result.return_value.last_modified ||
// file_array[i].creation_date !==
// result.return_value.creation_date) {
// // the file in the index storage is different than
// // the one in the second storage. priv.update will
// // take care of refresh the indexed storage
// }
that.done(result);
},
loadOnFail = function (result) {
that.fail(result);
},
secondLoadDocument = function () {
var newcommand = command.clone();
newcommand.onResponseDo (function(){});
newcommand.onFailDo (loadOnFail);
newcommand.onDoneDo (loadOnDone);
that.addJob ( that.newStorage(priv.secondstorage_spec),
newcommand );
};
priv.update();
if (command.getOption('metadata_only')) {
setTimeout(function () {
if (priv.fileArrayExists()) {
file_array = priv.getFileArray();
for (i = 0, l = file_array.length; i < l; i+= 1) {
if (file_array[i].name === command.getPath()) {
return that.done(file_array[i]);
}
}
} else {
secondLoadDocument();
}
},100);
} else {
secondLoadDocument();
}
}; // end loadDocument
/**
* Gets a document list.
* @method getDocumentList
*/
that.getDocumentList = function (command) {
var id, newcommand, timeout = false;
priv.update();
if (command.getOption('metadata_only')) {
id = setInterval(function () {
if (timeout) {
that.fail({status:0,statusText:'Timeout',
message:'The request has timed out.'});
clearInterval(id);
}
if (priv.fileArrayExists()) {
that.done(priv.getFileArray());
clearInterval(id);
}
},100);
setTimeout (function () {
timeout = true;
}, 10000); // 10 sec
} else {
newcommand = command.clone();
newcommand.onDoneDo (function (result) {
that.done(result);
});
newcommand.onFailDo (function (result) {
that.fail(result);
});
that.addJob ( that.newStorage (priv.secondstorage_spec),
newcommand );
}
}; // end getDocumentList
/**
* Removes a document.
* @method removeDocument
*/
that.removeDocument = function (command) {
var newcommand = command.clone();
newcommand.onResponseDo (function(){});
newcommand.onDoneDo (function (result) {
priv.removeFile(command.getPath());
priv.update();
that.done();
});
newcommand.onFailDo (function (result) {
that.fail(result);
});
that.addJob( that.newStorage(priv.secondstorage_spec),
newcommand );
};
return that;
};
Jio.addStorageType ('indexed', newIndexStorage);
...@@ -5,6 +5,21 @@ var newReplicateStorage = function ( spec, my ) { ...@@ -5,6 +5,21 @@ var newReplicateStorage = function ( spec, my ) {
priv.storagelist = spec.storagelist || []; priv.storagelist = spec.storagelist || [];
priv.nb_storage = priv.storagelist.length; priv.nb_storage = priv.storagelist.length;
var super_serialized = that.serialized;
that.serialized = function () {
var o = super_serialized();
o.storagelist = priv.storagelist;
return o;
};
that.validateState = function () {
if (priv.storagelist.length === 0) {
return 'Need at least one parameter: "storagelist" '+
'containing at least one storage.';
}
return '';
};
priv.isTheLast = function () { priv.isTheLast = function () {
return (priv.return_value_array.length === priv.nb_storage); return (priv.return_value_array.length === priv.nb_storage);
}; };
...@@ -12,12 +27,10 @@ var newReplicateStorage = function ( spec, my ) { ...@@ -12,12 +27,10 @@ var newReplicateStorage = function ( spec, my ) {
priv.doJob = function (command,errormessage) { priv.doJob = function (command,errormessage) {
var done = false, error_array = [], i, var done = false, error_array = [], i,
onResponseDo = function (result) { onResponseDo = function (result) {
console.log ('respond');
priv.return_value_array.push(result); priv.return_value_array.push(result);
}, },
onFailDo = function (result) { onFailDo = function (result) {
if (!done) { if (!done) {
console.log ('fail');
error_array.push(result); error_array.push(result);
if (priv.isTheLast()) { if (priv.isTheLast()) {
that.fail ( that.fail (
...@@ -30,7 +43,6 @@ var newReplicateStorage = function ( spec, my ) { ...@@ -30,7 +43,6 @@ var newReplicateStorage = function ( spec, my ) {
}, },
onDoneDo = function (result) { onDoneDo = function (result) {
if (!done) { if (!done) {
console.log ('done');
done = true; done = true;
that.done (result); that.done (result);
} }
...@@ -38,7 +50,7 @@ var newReplicateStorage = function ( spec, my ) { ...@@ -38,7 +50,7 @@ var newReplicateStorage = function ( spec, my ) {
command.setMaxRetry (1); command.setMaxRetry (1);
for (i = 0; i < priv.nb_storage; i+= 1) { for (i = 0; i < priv.nb_storage; i+= 1) {
var newcommand = command.clone(); var newcommand = command.clone();
var newstorage = Jio.storage(priv.storagelist[i], my); var newstorage = that.newStorage(priv.storagelist[i]);
newcommand.onResponseDo (onResponseDo); newcommand.onResponseDo (onResponseDo);
newcommand.onFailDo (onFailDo); newcommand.onFailDo (onFailDo);
newcommand.onDoneDo (onDoneDo); newcommand.onDoneDo (onDoneDo);
......
...@@ -4,4 +4,4 @@ auto: grunt ...@@ -4,4 +4,4 @@ auto: grunt
check-syntax: grunt check-syntax: grunt
grunt: grunt:
make -C ../../grunt/*_gruntJIO make -C ../../grunt/*_gruntJIO > /dev/null 2>&1
...@@ -119,15 +119,27 @@ var command = function(spec, my) { ...@@ -119,15 +119,27 @@ var command = function(spec, my) {
}; };
that.onResponseDo = function (fun) { that.onResponseDo = function (fun) {
priv.respond = fun; if (fun) {
priv.respond = fun;
} else {
return priv.respond;
}
}; };
that.onDoneDo = function (fun) { that.onDoneDo = function (fun) {
priv.done = fun; if (fun) {
priv.done = fun;
} else {
return priv.done;
}
}; };
that.onFailDo = function (fun) { that.onFailDo = function (fun) {
priv.fail = fun; if (fun) {
priv.fail = fun;
} else {
return priv.fail;
}
}; };
that.onEndDo = function (fun) { that.onEndDo = function (fun) {
...@@ -149,16 +161,39 @@ var command = function(spec, my) { ...@@ -149,16 +161,39 @@ var command = function(spec, my) {
tried:priv.tried, tried:priv.tried,
max_retry:priv.max_retry, max_retry:priv.max_retry,
path:priv.path, path:priv.path,
option:priv.option}; option:that.cloneOption()};
}; };
/**
* Is the command can be restored by another JIO : yes.
* @method canBeRestored
* @return {boolean} true
*/
that.canBeRestored = function() { that.canBeRestored = function() {
return true; return true;
}; };
/**
* Clones the command and returns it.
* @method clone
* @return {object} The cloned command.
*/
that.clone = function () { that.clone = function () {
return command(that.serialized(), my); return command(that.serialized(), my);
}; };
/**
* Clones the command options and returns the clone version.
* @method cloneOption
* @return {object} The clone of the command options.
*/
that.cloneOption = function () {
var k, o = {};
for (k in priv.option) {
o[k] = priv.option[k];
}
return o;
};
return that; return that;
}; };
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
my.jobManager = jobManager; my.jobManager = jobManager;
my.jobIdHandler = jobIdHandler; my.jobIdHandler = jobIdHandler;
priv.storage = jioNamespace.storage(spec, my); priv.storage = jioNamespace.storage(spec, my);
// initialize // // initialize //
...@@ -99,7 +98,7 @@ ...@@ -99,7 +98,7 @@
jioNamespace.storage(specificstorage,my): jioNamespace.storage(specificstorage,my):
priv.storage), priv.storage),
command:saveDocument( command:saveDocument(
{path:path,content:content,option:option})},my)); {path:path,content:content,option:option},my)},my));
}; };
/** /**
...@@ -128,7 +127,7 @@ ...@@ -128,7 +127,7 @@
jioNamespace.storage(specificstorage,my): jioNamespace.storage(specificstorage,my):
priv.storage), priv.storage),
command:loadDocument( command:loadDocument(
{path:path,option:option})},my)); {path:path,option:option},my)},my));
}; };
/** /**
...@@ -154,7 +153,7 @@ ...@@ -154,7 +153,7 @@
jioNamespace.storage(specificstorage,my): jioNamespace.storage(specificstorage,my):
priv.storage), priv.storage),
command:removeDocument( command:removeDocument(
{path:path,option:option})},my)); {path:path,option:option},my)},my));
}; };
/** /**
...@@ -183,7 +182,7 @@ ...@@ -183,7 +182,7 @@
jioNamespace.storage(specificstorage,my): jioNamespace.storage(specificstorage,my):
priv.storage), priv.storage),
command:getDocumentList( command:getDocumentList(
{path:path,option:option})},my)); {path:path,option:option},my)},my));
}; };
return that; return that;
......
...@@ -20,6 +20,7 @@ var jioNamespace = (function(spec, my) { ...@@ -20,6 +20,7 @@ var jioNamespace = (function(spec, my) {
*/ */
that.storage = function(spec, my, forcetype) { that.storage = function(spec, my, forcetype) {
spec = spec || {}; spec = spec || {};
my = my || {};
var type = forcetype || spec.type || 'base'; var type = forcetype || spec.type || 'base';
if (!storage_type_o[type]) { if (!storage_type_o[type]) {
throw invalidStorageType({type:type, throw invalidStorageType({type:type,
......
...@@ -11,7 +11,7 @@ var jobManager = (function(spec, my) { ...@@ -11,7 +11,7 @@ var jobManager = (function(spec, my) {
priv.job_a = []; priv.job_a = [];
my.jobManager = that; my.jobManager = that;
my.jobIdHandler = that; my.jobIdHandler = jobIdHandler;
// Methods // // Methods //
/** /**
......
...@@ -14,5 +14,9 @@ var doneStatus = function(spec, my) { ...@@ -14,5 +14,9 @@ var doneStatus = function(spec, my) {
that.canRestart = function() { that.canRestart = function() {
return false; return false;
}; };
that.isDone = function() {
return true;
};
return that; return that;
}; };
...@@ -19,5 +19,9 @@ var jobStatus = function(spec, my) { ...@@ -19,5 +19,9 @@ var jobStatus = function(spec, my) {
return false; return false;
}; };
that.isDone = function() {
return false;
};
return that; return that;
}; };
...@@ -3,8 +3,19 @@ var storageHandler = function(spec, my) { ...@@ -3,8 +3,19 @@ var storageHandler = function(spec, my) {
my = my || {}; my = my || {};
var that = storage( spec, my ); var that = storage( spec, my );
that.newCommand = function (method, spec) {
var o = spec || {};
o.label = method;
return command (o, my);
};
that.newStorage = function (spec) {
var o = spec || {};
return jioNamespace.storage (o, my);
};
that.addJob = function (storage,command) { that.addJob = function (storage,command) {
my.jobManager.addJob ( job({storage:storage, command:command}), my ); my.jobManager.addJob ( job({storage:storage, command:command}, my) );
}; };
return that; return that;
......
...@@ -694,7 +694,6 @@ test ('Document load', function () { ...@@ -694,7 +694,6 @@ test ('Document load', function () {
o.jio = JIO.newJio({type:'replicate',storagelist:[ o.jio = JIO.newJio({type:'replicate',storagelist:[
{type:'dummyallok',username:'1'}, {type:'dummyallok',username:'1'},
{type:'dummyallok',username:'2'}]}); {type:'dummyallok',username:'2'}]});
console.log (o.jio.getId());
o.mytest('DummyStorageAllOK,OK: load same file',{ o.mytest('DummyStorageAllOK,OK: load same file',{
name:'file',content:'content', name:'file',content:'content',
last_modified:15000, last_modified:15000,
...@@ -704,7 +703,6 @@ test ('Document load', function () { ...@@ -704,7 +703,6 @@ test ('Document load', function () {
o.jio = JIO.newJio({type:'replicate',storagelist:[ o.jio = JIO.newJio({type:'replicate',storagelist:[
{type:'dummyall3tries'}, {type:'dummyall3tries'},
{type:'dummyallok'}]}); {type:'dummyallok'}]});
console.log (o.jio.getId());
o.mytest('DummyStorageAllOK,3tries: load 2 different files',{ o.mytest('DummyStorageAllOK,3tries: load 2 different files',{
name:'file',content:'content', name:'file',content:'content',
last_modified:15000, last_modified:15000,
...@@ -713,207 +711,182 @@ test ('Document load', function () { ...@@ -713,207 +711,182 @@ test ('Document load', function () {
o.jio.stop(); o.jio.stop();
}); });
// test ('Document save', function () { test ('Document save', function () {
// // Test if ReplicateStorage can save several documents. // Test if ReplicateStorage can save several documents.
// var o = {}, clock = this.sandbox.useFakeTimers(), t = this,
// mytest = function (message,value) {
// o.f = function (result) {
// deepEqual (result.status,value,message);};
// t.spy(o,'f');
// o.jio.saveDocument({'name':'file','content':'content',
// 'onResponse':o.f,'max_tries':3});
// clock.tick(500);
// if (!o.f.calledOnce) {
// ok(false, 'no response / too much results');
// }
// };
// o.jio=JIO.newJio({'type':'replicate','user_name':'Dummy','storage_array':[
// {'type':'dummyallok','user_name':'1'},
// {'type':'dummyallok','user_name':'2'}]},
// {'ID':'jiotests'});
// mytest('DummyStorageAllOK,OK: save a file.','done');
// o.jio.stop();
// });
// test ('Get Document List', function () { var o = {}; o.clock = this.sandbox.useFakeTimers(); o.t = this;
// // Test if ReplicateStorage can get several list. o.mytest = function (message,value) {
o.f = function (result) {
deepEqual (result.status.getLabel(),value,message);
};
o.t.spy(o,'f');
o.jio.saveDocument('file','content',{onResponse:o.f,max_retry:3});
o.clock.tick(500);
if (!o.f.calledOnce) {
ok(false, 'no response / too much results');
}
};
o.jio = JIO.newJio({type:'replicate',storagelist:[
{type:'dummyallok',username:'1'},
{type:'dummyallok',username:'2'}]});
o.mytest('DummyStorageAllOK,OK: save a file.','done');
o.jio.stop();
// var o = {}, clock = this.sandbox.useFakeTimers(), t = this, o.jio = JIO.newJio({type:'replicate',storagelist:[
// mytest = function (message,value) { {type:'dummyall3tries',username:'1'},
// o.f = function (result) { {type:'dummyallok',username:'2'}]});
// deepEqual (objectifyDocumentArray(result.return_value), o.mytest('DummyStorageAll3Tries,OK: save a file.','done');
// objectifyDocumentArray(value),'getting list'); o.jio.stop();
// }; });
// t.spy(o,'f');
// o.jio.getDocumentList({'onResponse':o.f,'max_tries':3});
// clock.tick(100000);
// if (!o.f.calledOnce) {
// ok(false, 'no response / too much results');
// }
// };
// o.jio=JIO.newJio({'type':'replicate','user_name':'Dummy','storage_array':[
// {'type':'dummyallok','user_name':'1'},
// {'type':'dummyall3tries','user_name':'2'}]},
// {'ID':'jiotests'});
// o.doc1 = {'name':'file',
// 'last_modified':15000,'creation_date':10000};
// o.doc2 = {'name':'memo',
// 'last_modified':25000,'creation_date':20000};
// mytest('DummyStorageAllOK,3tries: get document list .',[o.doc1,o.doc2]);
// o.jio.stop();
// });
// test ('Remove document', function () { test ('Get Document List', function () {
// // Test if ReplicateStorage can remove several documents. // Test if ReplicateStorage can get several list.
// var o = {}, clock = this.sandbox.useFakeTimers(), t = this,
// mytest = function (message,value) {
// o.f = function (result) {
// deepEqual (result.status,value,message);};
// t.spy(o,'f');
// o.jio.removeDocument({'name':'file','onResponse':o.f,'max_tries':3});
// clock.tick(100000);
// if (!o.f.calledOnce) {
// ok(false, 'no response / too much results');
// }
// };
// o.jio=JIO.newJio({'type':'replicate','user_name':'Dummy','storage_array':[
// {'type':'dummyallok','user_name':'1'},
// {'type':'dummyall3tries','user_name':'2'}]},
// {'ID':'jiotests'});
// mytest('DummyStorageAllOK,3tries: remove document.','done');
// o.jio.stop();
// });
// module ('Jio IndexedStorage'); var o = {}; o.clock = this.sandbox.useFakeTimers(); o.t = this;
o.mytest = function (message,value) {
// test ('Check name availability', function () { o.f = function (result) {
// var o = {}, clock = this.sandbox.useFakeTimers(), t = this, deepEqual (objectifyDocumentArray(result.value),
// mytest = function (message,value) { objectifyDocumentArray(value),'getting list');
// o.f = function (result) { };
// deepEqual (result.return_value,value,message);}; o.t.spy(o,'f');
// t.spy(o,'f'); o.jio.getDocumentList('.',{onResponse:o.f,max_retry:3});
// o.jio.checkNameAvailability({user_name:'MrIndexedCheck', o.clock.tick(100000);
// onResponse:o.f,max_tries:3}); if (!o.f.calledOnce) {
// clock.tick(100000); ok(false, 'no response / too much results');
// if (!o.f.calledOnce) { }
// ok(false, 'no response / too much results'); };
// } o.jio = JIO.newJio({type:'replicate',storagelist:[
// }; {type:'dummyall3tries',username:'1'},
// o.jio=JIO.newJio({type:'indexed', {type:'dummyallok',username:'2'}]});
// storage:{type:'dummyall3tries', o.doc1 = {name:'file',
// user_name:'indexedcheck'}}, last_modified:15000,creation_date:10000};
// {ID:'jiotests'}); o.doc2 = {name:'memo',
// mytest('dummy ok : name must be available', true); last_modified:25000,creation_date:20000};
// o.jio.stop(); o.mytest('DummyStorageAllOK,3tries: get document list .',[o.doc1,o.doc2]);
// }); o.jio.stop();
});
// test ('Document load', function () { test ('Remove document', function () {
// var o = {}, clock = this.sandbox.useFakeTimers(); // Test if ReplicateStorage can remove several documents.
// o.jio=JIO.newJio({type:'indexed',
// storage:{type:'dummyall3tries',
// user_name:'indexedload'}},
// {ID:'jiotests'});
// // loading must take long time with dummyall3tries
// o.f = function () {};
// this.spy(o,'f');
// o.jio.loadDocument({name:'memo',max_tries:3,onResponse:o.f,
// options:{metadata_only:true}});
// clock.tick(500);
// ok(!o.f.calledOnce,'Callback must not be called');
// // wait long time too retreive list
// clock.tick(100000);
// // now we can test if the document metadata are loaded faster.
// o.doc = {name:'memo',last_modified:25000,creation_date:20000};
// o.f2 = function (result) {
// deepEqual (result.return_value,o.doc,'Document metadata retrieved');
// };
// this.spy(o,'f2');
// o.jio.loadDocument({name:'memo',max_tries:3,onResponse:o.f2,
// options:{metadata_only:true}});
// clock.tick(500);
// if (!o.f2.calledOnce) {
// ok (false, 'no response / too much results');
// }
// // test a simple document loading
// o.doc2 = {name:'file',last_modified:17000,
// creation_date:11000,content:'content2'};
// o.f3 = function (result) {
// deepEqual (result.return_value,o.doc2,'Simple document loading');
// };
// this.spy(o,'f3');
// o.jio.loadDocument({name:'file',max_tries:3,onResponse:o.f3});
// clock.tick(100000);
// if (!o.f3.calledOnce) {
// ok (false, 'no response / too much results');
// }
// o.jio.stop();
// });
// test ('Document save', function () { var o = {}; o.clock = this.sandbox.useFakeTimers(); o.t = this;
// var o = {}, clock = this.sandbox.useFakeTimers(); o.mytest = function (message,value) {
// o.jio=JIO.newJio({type:'indexed', o.f = function (result) {
// storage:{type:'dummyall3tries', deepEqual (result.status.getLabel(),value,message);
// user_name:'indexedsave'}}, };
// {ID:'jiotests'}); o.t.spy(o,'f');
// o.f = function (result) { o.jio.removeDocument('file',{onResponse:o.f,max_retry:3});
// deepEqual (result.status,'done','document save'); o.clock.tick(100000);
// }; if (!o.f.calledOnce) {
// this.spy(o,'f'); ok(false, 'no response / too much results');
// o.jio.saveDocument({name:'file',max_tries:3,onResponse:o.f}); }
// clock.tick(100000); };
// if (!o.f.calledOnce){ o.jio = JIO.newJio({type:'replicate',storagelist:[
// ok (false, 'no response / too much results'); {type:'dummyallok',username:'1'},
// } {type:'dummyall3tries',username:'2'}]});
// o.jio.stop(); o.mytest('DummyStorageAllOK,3tries: remove document.','done');
// }); o.jio.stop();
});
// test ('Get document list', function () { module ('Jio IndexedStorage');
// var o = {}, clock = this.sandbox.useFakeTimers();
// o.jio=JIO.newJio({type:'indexed',
// storage:{type:'dummyall3tries',
// user_name:'indexedgetlist'}},
// {ID:'jiotests'});
// o.doc1 = {name:'file',last_modified:15000,creation_date:10000};
// o.doc2 = {name:'memo',last_modified:25000,creation_date:20000};
// // getting list must take long time with dummyall3tries
// o.f = function () {};
// this.spy(o,'f');
// o.jio.getDocumentList({max_tries:3,onResponse:o.f});
// clock.tick(500);
// ok(!o.f.calledOnce,'Callback must not be called');
// // wail long time too retreive list
// clock.tick(100000);
// // now we can test if the document list is loaded faster
// o.f2 = function (result) {
// deepEqual (result.return_value,[o.doc1,o.doc2],'get document list');
// };
// this.spy(o,'f2');
// o.jio.getDocumentList({max_tries:3,onResponse:o.f2});
// clock.tick(500);
// if (!o.f2.calledOnce) {
// ok (false, 'no response / too much results');
// }
// });
// test ('Remove document', function () { test ('Document load', function () {
// var o = {}, clock = this.sandbox.useFakeTimers(); var o = {}; o.clock = this.sandbox.useFakeTimers();
// o.jio=JIO.newJio({type:'indexed', o.jio = JIO.newJio({type:'indexed',storage:{type:'dummyall3tries'}});
// storage:{type:'dummyall3tries', // loading must take long time with dummyall3tries
// user_name:'indexedsave'}}, o.f = this.spy();
// {ID:'jiotests'}); o.jio.loadDocument('memo',{max_retry:3,onResponse:o.f,metadata_only:true});
// o.f = function (result) { o.clock.tick(1000);
// deepEqual (result.status,'done','document remove'); ok(!o.f.called,'Callback must not be called');
// }; // wait long time too retreive list
// this.spy(o,'f'); o.clock.tick(100000);
// o.jio.removeDocument({name:'file',max_tries:3,onResponse:o.f});
// clock.tick(100000); // now we can test if the document metadata are loaded faster.
// if (!o.f.calledOnce){ o.doc = {name:'memo',last_modified:25000,creation_date:20000};
// ok (false, 'no response / too much results'); o.f2 = function (result) {
// } deepEqual (result.value,o.doc,'Document metadata retrieved');
// o.jio.stop(); };
// }); this.spy(o,'f2');
o.jio.loadDocument('memo',{max_retry:3,onResponse:o.f2,metadata_only:true});
o.clock.tick(1000);
if (!o.f2.calledOnce) {
ok (false, 'no response / too much results');
}
// test a simple document loading
o.doc2 = {name:'file',last_modified:17000,
creation_date:11000,content:'content2'};
o.f3 = function (result) {
deepEqual (result.value,o.doc2,'Simple document loading');
};
this.spy(o,'f3');
o.jio.loadDocument('file',{max_retry:3,onResponse:o.f3});
o.clock.tick(100000);
if (!o.f3.calledOnce) {
ok (false, 'no response / too much results');
}
o.jio.stop();
});
test ('Document save', function () {
var o = {}; o.clock = this.sandbox.useFakeTimers();
o.jio = JIO.newJio({type:'indexed',
storage:{type:'dummyall3tries',
username:'indexsave'}});
o.f = function (result) {
deepEqual (result.status.getLabel(),'done','document save');
};
this.spy(o,'f');
o.jio.saveDocument('file','content',{max_retry:3,onResponse:o.f});
o.clock.tick(100000);
if (!o.f.calledOnce){
ok (false, 'no response / too much results');
}
o.jio.stop();
});
test ('Get document list', function () {
var o = {}; o.clock = this.sandbox.useFakeTimers();
o.jio = JIO.newJio({type:'indexed',
storage:{type:'dummyall3tries',
username:'indexgetlist'}});
o.doc1 = {name:'file',last_modified:15000,creation_date:10000};
o.doc2 = {name:'memo',last_modified:25000,creation_date:20000};
// getting list must take long time with dummyall3tries
o.f = this.spy();
o.jio.getDocumentList('.',{max_retry:3,onResponse:o.f});
o.clock.tick(1000);
ok(!o.f.called,'Callback must not be called');
// wail long time too retreive list
o.clock.tick(100000);
// now we can test if the document list is loaded faster
o.f2 = function (result) {
deepEqual (result.value,[o.doc1,o.doc2],'get document list');
};
this.spy(o,'f2');
o.jio.getDocumentList('.',{max_retry:3,onResponse:o.f2});
o.clock.tick(1000)
if (!o.f2.calledOnce) {
ok (false, 'no response / too much results');
}
});
test ('Remove document', function () {
var o = {}; o.clock = this.sandbox.useFakeTimers();
o.jio = JIO.newJio({type:'indexed',
storage:{type:'dummyall3tries',
username:'indexremove'}});
o.f = function (result) {
deepEqual (result.status.getLabel(),'done','document remove');
};
this.spy(o,'f');
o.jio.removeDocument('file',{max_retry:3,onResponse:o.f});
o.clock.tick(100000);
if (!o.f.calledOnce){
ok (false, 'no response / too much results');
}
o.jio.stop();
});
// module ('Jio CryptedStorage'); // module ('Jio CryptedStorage');
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment