dl
Version:
DreamLab Libs
220 lines (190 loc) • 6.74 kB
JavaScript
var fs = require('fs');
var Path = require('path');
var Core = require('core');
var Assertions = Core.common.Assertions;
var Types = Core.common.Types;
var VALUE_MAGIC_FILE = '.value';
var AbstractDataProvider = require('./AbstractDataProvider.js').AbstractDataProvider;
var FilesDataProvider = function (rootPath) {
AbstractDataProvider.call(this, rootPath);
Assertions.isString(rootPath, FilesDataProvider.Exception.BAD_FILE_NAME);
this._rootPath = rootPath;
this._watches = {};
};
FilesDataProvider.prototype = Object.create(AbstractDataProvider.prototype);
FilesDataProvider.prototype.init = function (callback) {
var that = this;
fs.stat(this._rootPath, function (error, stats) {
if (error) {
if (error.code != "ENOENT") {
callback(error, null);
return;
} else {
fs.mkdir(that._rootPath, '0777', function (error) {
if (error) {
callback(error, null);
return;
}
callback(null, true);
});
}
return;
}
callback(null, true);
});
};
FilesDataProvider.prototype.destroy = function () {
for (var key in this._watches) {
if (this._watches.hasOwnProperty(key)) {
this.unwatch(key);
}
}
};
FilesDataProvider.prototype.watch = function (key, callback) {
var _self = this;
var path = Path.join(this._rootPath, key);
if (key[key.length - 1] != '/') {
path = Path.join(path, VALUE_MAGIC_FILE);
}
if (this._watches.hasOwnProperty(key)) {
this._watches[key].push(callback);
this._onWatchFile(key, callback);
return;
}
/* TODO - przejsc na fs.watch */
fs.watchFile(path, {interval: 500}, function (current, previous) {
if (current.size == 0) {
/*
* pomijam event przy czyszczeniu pliku
* po CLOSE_WRITE zostanie wygenerowany nowy event
*/
} else {
/* odpalenie callbackow dla "słuchaczy" */
if (_self._watches.hasOwnProperty(key)) {
_self._onWatchFile(key, _self._watches[key]);
}
}
});
this._watches[key] = [callback];
this._onWatchFile(key, callback);
};
FilesDataProvider.prototype._onWatchFile = function (key, callbacks) {
var _self = this;
callbacks = Types.isArray(callbacks) ? callbacks : [callbacks];
this.get(key, function (err, data) {
if (err) {
console.error('Error reading watched file (%s):', key, err)
data = null;
}
for (var i = 0, len = callbacks.length; i < len; i++) {
callbacks[i](err, data);
}
});
}
FilesDataProvider.prototype.unwatch = function (key, callback) {
var path = Path.join(this._rootPath, key);
if (key[key.length - 1] != '/') {
path = Path.join(path, VALUE_MAGIC_FILE);
}
if (this._watches.hasOwnProperty(key)) {
fs.unwatchFile(path);
delete this._watches[key];
}
if (callback) {
callback();
}
};
FilesDataProvider.prototype.set = function (key, value, options, callback) {
var that = this;
Assertions.isString(key, FilesDataProvider.Exception.KEY_HAS_TO_BE_A_STRING);
var dirPath = Path.join(this._rootPath, key);
fs.stat(dirPath, function (error, stats) {
if (error) {
if (error.code == 'ENOENT') {
fs.mkdir(dirPath, '0777', function () {
that._writeValue(key, value, callback);
});
} else {
callback(error, null);
}
} else {
that._writeValue(key, value, callback);
}
});
};
FilesDataProvider.prototype.remove = function (key, options, callback) {
console.info('TODO :)');
};
FilesDataProvider.prototype._writeValue = function (key, value, callback) {
var filePath = Path.join(this._rootPath, key, VALUE_MAGIC_FILE);
fs.writeFile(filePath, value, function (error, value) {
callback(error, value);
});
};
FilesDataProvider.prototype.get = function (key, callback) {
Assertions.isString(key, FilesDataProvider.Exception.KEY_HAS_TO_BE_A_STRING);
var dirPath = Path.join(this._rootPath, key);
if (key[key.length - 1] == '/') { //odczytujemy dzieciaki
fs.readdir(dirPath, function (error, value) {
callback(error, value.filter(function (element) {
return element[0] != '.';
}));
});
} else {
fs.readFile(Path.join(dirPath, VALUE_MAGIC_FILE), 'utf-8', function (error, data) {
if (error) {
callback(error, null);
return;
}
callback(error, data.toString(), {});
});
}
};
FilesDataProvider.prototype.remove = function (key, options, callback) {
Assertions.isString(key, FilesDataProvider.Exception.KEY_HAS_TO_BE_A_STRING);
var that = this;
var dirPath = Path.join(this._rootPath, key);
fs.stat(dirPath, function (err, stat) {
if (err) {
callback(err.code, stat);
return;
}
if (!stat.isDirectory()) {
fs.unlink(dirPath, function (err) {
callback(err, null);
});
} else {
fs.readdir(dirPath, function (err, files) {
var length = files.length, deleted = 0, i;
if (err) {
callback(err);
return;
}
if (!length) {
fs.rmdir(dirPath, function (err) {
callback(err);
});
return;
}
for (i = 0; i < length; i++) {
that.remove(Path.join(dirPath, files[i]), options, function (err) {
if (err) {
callback(err, null);
return;
}
if (++deleted == length) {
fs.rmdir(dirPath, function (err) {
callback(err, null);
});
}
});
}
});
}
});
};
FilesDataProvider.Exception = {};
FilesDataProvider.Exception.BAD_FILE_NAME = "File name has to be a string";
FilesDataProvider.Exception.WRONG_KEY = "Key has to be a string";
FilesDataProvider.Exception.WRONG_VALUE = "Value has to be a string or an object";
exports.FilesDataProvider = FilesDataProvider;