2013-10-21 20:42:13 +00:00
|
|
|
/**
|
|
|
|
* Licensed to the Apache Software Foundation (ASF) under one
|
|
|
|
* or more contributor license agreements. See the NOTICE file
|
|
|
|
* distributed with this work for additional information
|
|
|
|
* regarding copyright ownership. The ASF licenses this file
|
|
|
|
* to you under the Apache License, Version 2.0 (the
|
|
|
|
* "License"); you may not use this file except in compliance
|
|
|
|
* with the License. You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
(function() {
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
// The chunk size of tailing the files, i.e., how many bytes will be shown
|
|
|
|
// in the preview.
|
|
|
|
var TAIL_CHUNK_SIZE = 32768;
|
|
|
|
|
2015-09-16 18:50:17 +00:00
|
|
|
//This stores the current directory which is being browsed
|
2013-10-21 20:42:13 +00:00
|
|
|
var current_directory = "";
|
|
|
|
|
|
|
|
function show_err_msg(msg) {
|
|
|
|
$('#alert-panel-body').html(msg);
|
|
|
|
$('#alert-panel').show();
|
|
|
|
}
|
|
|
|
|
2014-02-13 23:47:11 +00:00
|
|
|
$(window).bind('hashchange', function () {
|
|
|
|
$('#alert-panel').hide();
|
|
|
|
|
|
|
|
var dir = window.location.hash.slice(1);
|
|
|
|
if(dir == "") {
|
|
|
|
dir = "/";
|
|
|
|
}
|
|
|
|
if(current_directory != dir) {
|
|
|
|
browse_directory(dir);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2013-10-21 20:42:13 +00:00
|
|
|
function network_error_handler(url) {
|
|
|
|
return function (jqxhr, text, err) {
|
2014-02-21 18:57:06 +00:00
|
|
|
switch(jqxhr.status) {
|
|
|
|
case 401:
|
2014-05-30 20:43:58 +00:00
|
|
|
var msg = '<p>Authentication failed when trying to open ' + url + ': Unauthorized.</p>';
|
2014-02-21 18:57:06 +00:00
|
|
|
break;
|
|
|
|
case 403:
|
|
|
|
if(jqxhr.responseJSON !== undefined && jqxhr.responseJSON.RemoteException !== undefined) {
|
|
|
|
var msg = '<p>' + jqxhr.responseJSON.RemoteException.message + "</p>";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
var msg = '<p>Permission denied when trying to open ' + url + ': ' + err + '</p>';
|
|
|
|
break;
|
|
|
|
case 404:
|
|
|
|
var msg = '<p>Path does not exist on HDFS or WebHDFS is disabled. Please check your path or enable WebHDFS</p>';
|
|
|
|
break;
|
|
|
|
default:
|
2014-06-24 20:48:32 +00:00
|
|
|
var msg = '<p>Failed to retrieve data from ' + url + ': ' + err + '</p>';
|
2014-02-21 18:57:06 +00:00
|
|
|
}
|
2013-10-21 20:42:13 +00:00
|
|
|
show_err_msg(msg);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function append_path(prefix, s) {
|
|
|
|
var l = prefix.length;
|
|
|
|
var p = l > 0 && prefix[l - 1] == '/' ? prefix.substring(0, l - 1) : prefix;
|
|
|
|
return p + '/' + s;
|
|
|
|
}
|
|
|
|
|
|
|
|
function get_response(data, type) {
|
|
|
|
return data[type] !== undefined ? data[type] : null;
|
|
|
|
}
|
|
|
|
|
|
|
|
function get_response_err_msg(data) {
|
2014-04-23 20:20:16 +00:00
|
|
|
return data.RemoteException !== undefined ? data.RemoteException.message : "";
|
2013-10-21 20:42:13 +00:00
|
|
|
}
|
|
|
|
|
2015-09-15 23:48:15 +00:00
|
|
|
function delete_path(inode_name, absolute_file_path) {
|
|
|
|
$('#delete-modal-title').text("Delete - " + inode_name);
|
|
|
|
$('#delete-prompt').text("Are you sure you want to delete " + inode_name
|
|
|
|
+ " ?");
|
|
|
|
|
|
|
|
$('#delete-button').click(function() {
|
|
|
|
// DELETE /webhdfs/v1/<path>?op=DELETE&recursive=<true|false>
|
|
|
|
var url = '/webhdfs/v1' + encode_path(absolute_file_path) +
|
|
|
|
'?op=DELETE' + '&recursive=true';
|
|
|
|
|
|
|
|
$.ajax(url,
|
|
|
|
{ type: 'DELETE'
|
|
|
|
}).done(function(data) {
|
|
|
|
browse_directory(current_directory);
|
|
|
|
}).error(network_error_handler(url)
|
|
|
|
).complete(function() {
|
|
|
|
$('#delete-modal').modal('hide');
|
|
|
|
$('#delete-button').button('reset');
|
|
|
|
});
|
|
|
|
})
|
|
|
|
$('#delete-modal').modal();
|
|
|
|
}
|
|
|
|
|
2015-09-16 18:50:17 +00:00
|
|
|
/* This method loads the checkboxes on the permission info modal. It accepts
|
|
|
|
* the octal permissions, eg. '644' or '755' and infers the checkboxes that
|
|
|
|
* should be true and false
|
|
|
|
*/
|
|
|
|
function view_perm_details(e, filename, abs_path, perms) {
|
|
|
|
$('.explorer-perm-links').popover('destroy');
|
|
|
|
e.popover({html: true, content: $('#explorer-popover-perm-info').html(), trigger: 'focus'})
|
|
|
|
.on('shown.bs.popover', function(e) {
|
|
|
|
var popover = $(this), parent = popover.parent();
|
|
|
|
//Convert octal to binary permissions
|
|
|
|
var bin_perms = parseInt(perms, 8).toString(2);
|
|
|
|
bin_perms = bin_perms.length == 9 ? "0" + bin_perms : bin_perms;
|
|
|
|
parent.find('#explorer-perm-cancel').on('click', function() { popover.popover('destroy'); });
|
|
|
|
parent.find('#explorer-set-perm-button').off().click(function() { set_permissions(abs_path); });
|
|
|
|
parent.find('input[type=checkbox]').each(function(idx, element) {
|
|
|
|
var e = $(element);
|
|
|
|
e.prop('checked', bin_perms.charAt(9 - e.attr('data-bit')) == '1');
|
|
|
|
});
|
|
|
|
})
|
|
|
|
.popover('show');
|
|
|
|
}
|
|
|
|
|
|
|
|
// Use WebHDFS to set permissions on an absolute path
|
|
|
|
function set_permissions(abs_path) {
|
|
|
|
var p = 0;
|
|
|
|
$.each($('.popover .explorer-popover-perm-body input:checked'), function(idx, e) {
|
|
|
|
p |= 1 << (+$(e).attr('data-bit'));
|
|
|
|
});
|
|
|
|
|
|
|
|
var permission_mask = p.toString(8);
|
|
|
|
|
|
|
|
// PUT /webhdfs/v1/<path>?op=SETPERMISSION&permission=<permission>
|
|
|
|
var url = '/webhdfs/v1' + encode_path(abs_path) +
|
|
|
|
'?op=SETPERMISSION' + '&permission=' + permission_mask;
|
|
|
|
|
|
|
|
$.ajax(url, { type: 'PUT'
|
|
|
|
}).done(function(data) {
|
|
|
|
browse_directory(current_directory);
|
|
|
|
}).error(network_error_handler(url))
|
|
|
|
.complete(function() {
|
|
|
|
$('.explorer-perm-links').popover('destroy');
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-03-18 18:08:08 +00:00
|
|
|
function encode_path(abs_path) {
|
|
|
|
abs_path = encodeURIComponent(abs_path);
|
|
|
|
var re = /%2F/g;
|
|
|
|
return abs_path.replace(re, '/');
|
|
|
|
}
|
|
|
|
|
2013-10-21 20:42:13 +00:00
|
|
|
function view_file_details(path, abs_path) {
|
|
|
|
function show_block_info(blocks) {
|
|
|
|
var menus = $('#file-info-blockinfo-list');
|
|
|
|
menus.empty();
|
|
|
|
|
|
|
|
menus.data("blocks", blocks);
|
|
|
|
menus.change(function() {
|
|
|
|
var d = $(this).data('blocks')[$(this).val()];
|
|
|
|
if (d === undefined) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
dust.render('block-info', d, function(err, out) {
|
|
|
|
$('#file-info-blockinfo-body').html(out);
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
for (var i = 0; i < blocks.length; ++i) {
|
|
|
|
var item = $('<option value="' + i + '">Block ' + i + '</option>');
|
|
|
|
menus.append(item);
|
|
|
|
}
|
|
|
|
menus.change();
|
|
|
|
}
|
|
|
|
|
2015-02-17 21:04:38 +00:00
|
|
|
abs_path = encode_path(abs_path);
|
2013-10-21 20:42:13 +00:00
|
|
|
var url = '/webhdfs/v1' + abs_path + '?op=GET_BLOCK_LOCATIONS';
|
2014-07-11 05:15:18 +00:00
|
|
|
$.get(url).done(function(data) {
|
2013-10-21 20:42:13 +00:00
|
|
|
var d = get_response(data, "LocatedBlocks");
|
|
|
|
if (d === null) {
|
|
|
|
show_err_msg(get_response_err_msg(data));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
$('#file-info-tail').hide();
|
|
|
|
$('#file-info-title').text("File information - " + path);
|
|
|
|
|
2014-02-14 22:15:21 +00:00
|
|
|
var download_url = '/webhdfs/v1' + abs_path + '?op=OPEN';
|
2013-10-21 20:42:13 +00:00
|
|
|
|
|
|
|
$('#file-info-download').attr('href', download_url);
|
|
|
|
$('#file-info-preview').click(function() {
|
|
|
|
var offset = d.fileLength - TAIL_CHUNK_SIZE;
|
|
|
|
var url = offset > 0 ? download_url + '&offset=' + offset : download_url;
|
|
|
|
$.get(url, function(t) {
|
|
|
|
$('#file-info-preview-body').val(t);
|
|
|
|
$('#file-info-tail').show();
|
|
|
|
}, "text").error(network_error_handler(url));
|
|
|
|
});
|
|
|
|
|
|
|
|
if (d.fileLength > 0) {
|
|
|
|
show_block_info(d.locatedBlocks);
|
|
|
|
$('#file-info-blockinfo-panel').show();
|
|
|
|
} else {
|
|
|
|
$('#file-info-blockinfo-panel').hide();
|
|
|
|
}
|
|
|
|
$('#file-info').modal();
|
|
|
|
}).error(network_error_handler(url));
|
|
|
|
}
|
|
|
|
|
|
|
|
function browse_directory(dir) {
|
2015-02-26 09:06:09 +00:00
|
|
|
var HELPERS = {
|
|
|
|
'helper_date_tostring' : function (chunk, ctx, bodies, params) {
|
|
|
|
var value = dust.helpers.tap(params.value, chunk, ctx);
|
2015-09-02 05:28:38 +00:00
|
|
|
return chunk.write('' + moment(Number(value)).format('ddd MMM DD HH:mm:ss ZZ YYYY'));
|
2015-02-26 09:06:09 +00:00
|
|
|
}
|
|
|
|
};
|
2015-03-18 18:08:08 +00:00
|
|
|
var url = '/webhdfs/v1' + encode_path(dir) + '?op=LISTSTATUS';
|
2013-10-21 20:42:13 +00:00
|
|
|
$.get(url, function(data) {
|
|
|
|
var d = get_response(data, "FileStatuses");
|
|
|
|
if (d === null) {
|
|
|
|
show_err_msg(get_response_err_msg(data));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
current_directory = dir;
|
|
|
|
$('#directory').val(dir);
|
2014-02-13 23:47:11 +00:00
|
|
|
window.location.hash = dir;
|
2015-02-26 09:06:09 +00:00
|
|
|
var base = dust.makeBase(HELPERS);
|
|
|
|
dust.render('explorer', base.push(d), function(err, out) {
|
2013-10-21 20:42:13 +00:00
|
|
|
$('#panel').html(out);
|
|
|
|
|
|
|
|
$('.explorer-browse-links').click(function() {
|
|
|
|
var type = $(this).attr('inode-type');
|
2015-09-15 23:48:15 +00:00
|
|
|
var path = $(this).closest('tr').attr('inode-path');
|
2013-10-21 20:42:13 +00:00
|
|
|
var abs_path = append_path(current_directory, path);
|
|
|
|
if (type == 'DIRECTORY') {
|
|
|
|
browse_directory(abs_path);
|
|
|
|
} else {
|
|
|
|
view_file_details(path, abs_path);
|
|
|
|
}
|
|
|
|
});
|
2015-09-15 23:48:15 +00:00
|
|
|
|
2015-09-16 18:50:17 +00:00
|
|
|
//Set the handler for changing permissions
|
|
|
|
$('.explorer-perm-links').click(function() {
|
|
|
|
var filename = $(this).closest('tr').attr('inode-path');
|
|
|
|
var abs_path = append_path(current_directory, filename);
|
|
|
|
var perms = $(this).closest('tr').attr('data-permission');
|
|
|
|
view_perm_details($(this), filename, abs_path, perms);
|
|
|
|
});
|
|
|
|
|
2015-09-15 23:48:15 +00:00
|
|
|
$('.explorer-entry .glyphicon-trash').click(function() {
|
|
|
|
var inode_name = $(this).closest('tr').attr('inode-path');
|
|
|
|
var absolute_file_path = append_path(current_directory, inode_name);
|
|
|
|
delete_path(inode_name, absolute_file_path);
|
|
|
|
})
|
2013-10-21 20:42:13 +00:00
|
|
|
});
|
|
|
|
}).error(network_error_handler(url));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function init() {
|
2013-11-20 18:17:41 +00:00
|
|
|
dust.loadSource(dust.compile($('#tmpl-explorer').html(), 'explorer'));
|
|
|
|
dust.loadSource(dust.compile($('#tmpl-block-info').html(), 'block-info'));
|
|
|
|
|
|
|
|
var b = function() { browse_directory($('#directory').val()); };
|
|
|
|
$('#btn-nav-directory').click(b);
|
2014-02-13 23:47:11 +00:00
|
|
|
var dir = window.location.hash.slice(1);
|
|
|
|
if(dir == "") {
|
|
|
|
window.location.hash = "/";
|
|
|
|
} else {
|
|
|
|
browse_directory(dir);
|
|
|
|
}
|
2013-10-21 20:42:13 +00:00
|
|
|
}
|
|
|
|
|
2015-03-24 22:48:52 +00:00
|
|
|
$('#btn-create-directory').on('show.bs.modal', function(event) {
|
2015-09-16 18:50:17 +00:00
|
|
|
$('#new_directory_pwd').text(current_directory);
|
2015-03-24 22:48:52 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
$('#btn-create-directory-send').click(function () {
|
|
|
|
$(this).prop('disabled', true);
|
|
|
|
$(this).button('complete');
|
|
|
|
|
|
|
|
var url = '/webhdfs/v1' + encode_path(append_path(current_directory,
|
|
|
|
$('#new_directory').val())) + '?op=MKDIRS';
|
|
|
|
|
|
|
|
$.ajax(url, { type: 'PUT' }
|
|
|
|
).done(function(data) {
|
|
|
|
browse_directory(current_directory);
|
|
|
|
}).error(network_error_handler(url)
|
|
|
|
).complete(function() {
|
|
|
|
$('#btn-create-directory').modal('hide');
|
|
|
|
$('#btn-create-directory-send').button('reset');
|
|
|
|
});
|
|
|
|
})
|
|
|
|
|
2013-10-21 20:42:13 +00:00
|
|
|
init();
|
|
|
|
})();
|