text:
var MockupNS = MockupNS || "http://eval.bp/";
var MockupLog = MockupLog || require('logger').get('Mockup');
var MockupTimeout = MockupTimeout || 100;
var SSMockupCircles = {
    'http://20130930devDays.ll/circle/svgcircle01':
        {
            'learnEpCircleUri': 'http://20130930devDays.ll/circle/svgcircle01',
            'label': 'Circle No. 1',
            'xLabel' : 100,
            'yLabel' : 100,
            'xC' : 150,
            'yC' : 150,
            'xR' : 50,
            'yR' : 50,
            'learnEpVersionUri' : MockupNS + 'version/versionX'
        },
    'http://20130930devDays.ll/circle/svgcircle02':
        {
            'learnEpCircleUri': 'http://20130930devDays.ll/circle/svgcircle02',
            'label': 'Circle No. 2',
            'xLabel' : 200,
            'yLabel' : 200,
            'xC' : 250,
            'yC' : 250,
            'xR' : 70,
            'yR' : 70,
            'learnEpVersionUri' : MockupNS + 'version/versionX'
        }
};

var SSMockupOrgaEntities = {/*
    'http://20130930devDays.ll/orgaentity/orgaentity01' :
        {
            'uri': 'http://20130930devDays.ll/orgaentity/orgaentity01',
            'resource': 'http://20130930devDays.ll/#ue01',
            'x' : 125,
            'y' : 125 ,
            'type' : 'http://20130930devDays.ll/OrgaEntity'

        }
*/};

var SSMockupVersions = {};
SSMockupVersions[MockupNS + 'version/versionX'] = {
    'learnEpVersionUri' : MockupNS + 'version/versionX',
    'timestamp' : '2013-11-07T17:40:20+02:00',
    'learnEpUri' : MockupNS + 'episode/episodeX',
    'type' : 'Version'
};
SSMockupVersions[MockupNS + 'version/versionY'] = {
    'learnEpVersionUri' : MockupNS + 'version/versionY',
    'timestamp' : '2013-11-08T17:40:20+02:00',
    'learnEpUri' : MockupNS + 'episode/episodeY',
    'type' : 'Version'
};
var SSMockupEpisodes = {};
SSMockupEpisodes[MockupNS + 'episode/episodeX'] = {
    'learnEpUri' : MockupNS + 'episode/episodeX',
    'label' : 'An existing episode',
    'user' : MockupNS + 'user/peter',
    'type' : 'Episode'
};
SSMockupEpisodes[MockupNS + 'episode/episodeY'] = {
    'learnEpUri' : MockupNS + 'episode/episodeY',
    'label' : 'Another episode',
    'user' : MockupNS + 'user/peter2',
    'type' : 'Episode'
};
var SSMockupTimelineStates = {};
SSMockupTimelineStates[MockupNS + 'version/versionX'] = {
    'learnEpTimelineStateUri' : MockupNS + 'timelinestate/versionX',
    'startTime' : '2014-02-14T17:40:20+02:00',
    'endTime' : '2014-02-25T17:40:20+02:00'
};
SSMockupTimelineStates[MockupNS + 'version/versionY'] = {
    'learnEpTimelineStateUri' : MockupNS + 'timelinestate/versionY',
    'startTime' : '2013-11-06T17:40:20+02:00',
    'endTime' : '2013-11-07T17:40:20+02:00'
};

function SSLearnEpVersionRemoveCircle(){

	this.op = "learnEpVersionRemoveCircle";

  this.handle = function(resultHandler, errorHandler, user, key, learnEpCircleUri){

        MockupLog.debug("SSCIRCLEREMOVE " +learnEpCircleUri);
        if( SSMockupCircles[learnEpCircleUri]) {
            delete SSMockupCircles[learnEpCircleUri];
            setTimeout(function(){resultHandler(true);}, MockupTimeout);
            return;
        }
        errorHandler({'error':'Resource not found'});
	};
};

function SSLearnEpVersionRemoveEntity(){

	this.op = "learnEpVersionRemoveEntity";

  this.handle = function(resultHandler, errorHandler, user, key, learnEpEntityUri){

        MockupLog.debug("SSORGAENTITYREMOVE " +learnEpEntityUri);
        if( SSMockupOrgaEntities[learnEpEntityUri]) {
            delete SSMockupOrgaEntities[learnEpEntityUri];
            setTimeout(function(){resultHandler(true);}, MockupTimeout);
            return;
        }
        errorHandler({'error':'Resource not found'});
	};
};

function SSLearnEpVersionUpdateCircle(){

	this.op = "learnEpVersionUpdateCircle";

  this.handle = function(resultHandler, errorHandler, user, key, learnEpCircleUri, label, xLabel, yLabel, xR, yR, xC, yC){
        MockupLog.debug("SSCIRCLEUPDATE " + learnEpCircleUri);
        if( !SSMockupCircles[learnEpCircleUri]) {
            errorHandler({'error':'Resource not found'});
            return;
        }
        SSMockupCircles[learnEpCircleUri] = _.extend(
            SSMockupCircles[learnEpCircleUri], {
            'label' : label,
            'xLabel' : xLabel,
            'yLabel' : yLabel,
            'xR' : xR,
            'yR' : yR,
            'xC' : xC,
            'yC' : yC
        });
        setTimeout(function(){resultHandler(true);}, MockupTimeout);
        return;
	};
};

function SSLearnEpVersionUpdateEntity(){

	this.op = "learnEpVersionUpdateEntity";

  this.handle = function(resultHandler, errorHandler, user, key, learnEpEntityUri, entityUri, x, y){

        MockupLog.debug("SSORGAENTITYUPDATE" + learnEpEntityUri)
        if( !SSMockupOrgaEntities[learnEpEntityUri]) {
            errorHandler({'error':'Resource not found'});
            return;
        }
        SSMockupOrgaEntities[learnEpEntityUri] = _.extend(
            SSMockupOrgaEntities[learnEpEntityUri], {
            'entityUri' : entityUri,
            'x' : x,
            'y' : y
        });
        setTimeout(function(){resultHandler(true);}, MockupTimeout);
	};
};

function SSLearnEpCreate(){

	this.op = "learnEpCreate";

  this.handle = function(resultHandler, errorHandler, user, key, label, space){
    MockupLog.debug("SSEPISODECREATE");
    var uri = MockupNS + "episode/" + _.uniqueId('episode');
    SSMockupEpisodes[uri] = {
        'learnEpUri' : uri,
        'user' : user,
        'space' : 'private',
        'label' : label
    };
    setTimeout(function(){resultHandler({'learnEpUri': uri});}, MockupTimeout);

	};
};

function SSLearnEpUpdate() {
	this.op = "learnEpUpdate";

  this.handle = function(resultHandler, errorHandler, user, key, learnEpUri, label, space){
    MockupLog.debug("SSEPISODEUPDATE");
    if(!SSMockupEpisodes[learnEpUri]) {
        errorHandler({'error': "Episode " + learnEpUri + " not found"});
        return;
    }
    SSMockupEpisodes[learnEpUri] = _.extend(
        SSMockupEpisodes[learnEpUri], {
        'space' : 'private',
        'label' : label
    });
    setTimeout(function(){resultHandler(true);}, MockupTimeout);

	};

};

function SSLearnEpVersionCreate(){

	this.op = "learnEpVersionCreate";

  this.handle = function(resultHandler, errorHandler, user, key, learnEpUri){
    MockupLog.debug("SSVERSIONCREATE");
    var uri = MockupNS + "version/" + _.uniqueId('version');
    SSMockupVersions[uri] = {
        'learnEpVersionUri' : uri,
        'learnEpUri' : learnEpUri
    };
    setTimeout(function(){resultHandler({'learnEpVersionUri': uri});}, MockupTimeout);

	};
};

function SSLearnEpVersionAddCircle(){

	this.op = "learnEpVersionAddCircle";

  this.handle = function(resultHandler, errorHandler, user, key, learnEpVersionUri, label, xLabel, yLabel, xR, yR, xC, yC){
        MockupLog.debug("SSCIRCLEADD " + label);
        var uri = MockupNS + "circle/" + _.uniqueId('svgcircle');
        SSMockupCircles[uri] = {
            'uri' : uri,
            'learnEpVersionUri' : learnEpVersionUri,
            'label' : label,
            'xLabel' : xLabel,
            'yLabel' : yLabel,
            'xR' : xR,
            'yR' : yR,
            'xC' : xC,
            'yC' : yC
        }
        setTimeout(function(){resultHandler({'learnEpCircleUri':uri});}, MockupTimeout);
        return;
        errorHandler({'error':'Resource not found'});
  }
};

function SSLearnEpVersionAddEntity(){

	this.op = "learnEpVersionAddEntity";

  this.handle = function(resultHandler, errorHandler, user, key, learnEpVersionUri, entityUri, x, y){

        MockupLog.debug("SSENTITYADD " +entityUri);
        var uri = MockupNS + "orgaentity/" + _.uniqueId('orgaentity');
        SSMockupOrgaEntities[uri] = {
            'uri': uri,
            'learnEpVersionUri' : learnEpVersionUri,
            'x' : x,
            'y' : y,
            'entityUri' : entityUri
        }
        setTimeout(function(){resultHandler({'learnEpEntityUri':uri});}, MockupTimeout);
        return;
        errorHandler({'error':'Resource not found'});
	};
};

function SSLearnEpTimelineStateCreate() {

    this.handle = function(resultHandler, errorHandler, user, key, start, end, timeAttr){
        MockupLog.debug("SSTIMELINESTATECREATE " +start + ", " + end + ", " + timeAttr);
        var uri = MockupNS + "timelinestate/" + _.uniqueId('timelinestate');
        SSMockupTimelineStates[uri] = {
            'uri' : uri,
            'start' : start,
            'end' : end,
            'timeAttr' :timeAttr
        }
        setTimeout(function(){resultHandler({'uri':uri});}, MockupTimeout);
        return;
        errorHandler({'error':'Resource not found'});

    }
}

function SSLearnEpVersionGetTimelineState(){

  this.handle = function(resultHandler, errorHandler, user, key, learnEpVersionUri){
    MockupLog.debug("SSTIMELINESTATEGET")
    if( !SSMockupTimelineStates[learnEpVersionUri]) {
        errorHandler({'error':"Timelinestate not found"});
        return;
    }
    setTimeout(function(){resultHandler({'learnEpTimelineState': SSMockupTimelineStates[learnEpVersionUri]});}, MockupTimeout);

	};
};

function SSLearnEpTimelineStateUpdate(){

  this.handle = function(resultHandler, errorHandler, user, key, timelineStateUri, start, end, timeAttr){
    MockupLog.debug("SSTIMELINESTATEUPDATE")
    if( !SSMockupTimelineStates[timelineStateUri]) {
        errorHandler({'error':"Timelinestate not found"});
        return;
    }
    SSMockupTimelineStates[timelineStateUri] = _.extend(
        SSMockupTimelineStates[timelineStateUri], {
        'start' : start,
        'end' : end,
        'timeAttr' :timeAttr
    });
    setTimeout(function(){resultHandler(true);}, MockupTimeout);
    return;

	};
};

function SSLearnEpVersionSetTimelineState(){
    this.handle = function(resultHandler, errorHandler, user, key, learnEpVersionUri, start, end){
        MockupLog.debug("SSVERSIONSETTIMELINESTATE " + learnEpVersionUri );
        if( !SSMockupVersions[learnEpVersionUri] ) {
            errorHandler({'error' : "Version not found"});
            return;
        }
        SSMockupTimelineStates[learnEpVersionUri] = {
            start: start,
            end: end
        };
        setTimeout(function(){resultHandler(true);}, MockupTimeout);

    }

};

function SSLearnEpVersionGet(){

	this.op = "learnEpVersionGet";

  this.handle = function(resultHandler, errorHandler, user, key, learnEpVersionUri){

        MockupLog.debug("SSVERSIONGET " +learnEpVersionUri);
        if( !SSMockupVersions[learnEpVersionUri]) {
            errorHandler({'error':'Resource not found'});
            return;
        }
        var result = {'learnEpVersion' : {'circles' : [], 'entities' : [] } };
        for( var uri in SSMockupCircles) {
            if( SSMockupCircles[uri]['learnEpVersionUri'] == learnEpVersionUri)
                result.learnEpVersion.circles.push(SSMockupCircles[uri]);
        }
        for( var uri in SSMockupOrgaEntities) {
            if( SSMockupOrgaEntities[uri]['learnEpVersionUri'] == learnEpVersionUri)
                result.learnEpVersion.entities.push(SSMockupOrgaEntities[uri]);
        }
        if(result.length == 0 ) {
            errorHandler(result);
            return;
        }
        setTimeout(function(){resultHandler(result);}, MockupTimeout);
	};
};

function SSLearnEpVersionsGet(){

	this.op = "learnEpVersionsGet";

  this.handle = function(resultHandler, errorHandler, user, key, learnEpUri){
    MockupLog.debug("SSEPISODE-VERSIONSGET")
    var result = [];
    for( var uri in SSMockupVersions) {
        if(SSMockupVersions[uri]['learnEpUri'] == learnEpUri)
            result.push(SSMockupVersions[uri]);
    }
    setTimeout(function(){resultHandler({'learnEpVersions':result});}, MockupTimeout);

    }
};

function SSLearnEpsGet(){

	this.op = "learnEpsGet";

  this.handle = function(resultHandler, errorHandler, user, key){
    MockupLog.debug("SSEPISODESGET", user)
    var result = [];
    for( var uri in SSMockupEpisodes) {
        if(SSMockupEpisodes[uri]['user'] == user)
            result.push(SSMockupEpisodes[uri]);
    }
    setTimeout(function(){resultHandler({'learnEps' : result});}, MockupTimeout);

	};
};

function SSEntityLabelSet() {
    this.handle = function(resultHandler, errorHandler, user, key, entityUri, label){
        MockupLog.debug("SSLABELSET " + entityUri);
        for (var uri in SSMockupEpisodes) {
            if (SSMockupEpisodes[uri]['learnEpUri'] == entityUri) {
                SSMockupEpisodes[uri]['learnEpUri']['label'] = label;
                setTimeout(function(){resultHandler({'worked' : true})}, MockupTimeout);
                return;
            }
        }
        errorHandler({'error':'Resource not found'});
    }
}


text:
/*!!!!!!!!!!!!!!!!! edit below this line at your own risk !!!!!!!!!!!!!!!!!!!!!!!*/
//on page load call tb_init
$(document).ready(function () {
    tb_Ready();
});

// Хаберев: Добавил данную переменную, чтобы можно было отловить событие закрытия окна из других скриптов
/**
 * Deffered object to catch close event in other scripts.
 *
 * @type {jQuery.Deferred}
 */
var tb_CloseActionDeferred;

function tb_Ready() {
    tb_init('a.thickbox, area.thickbox, input.thickbox, td.thickbox'); //pass where to apply thickbox
}

//add thickbox to href & area elements that have a class of .thickbox
function tb_init(domChunk) {
    // KULIKOV: Добавил unbind, чтобы не вешать один и тот же обработчик много раз
    $(domChunk).unbind("click").click(function () {
        var t = this.rel || this.title || this.name || null;
        var a = this.href || this.alt || this.abbr;
        var g = false;
        tb_show(t, a, g);
        this.blur();
        return false;
    });
}

function tb_show(caption, url, imageGroup) { //function called when the user clicks on a thickbox link

    tb_CloseActionDeferred = $.Deferred();
    try {
        if (typeof document.body.style.maxHeight === "undefined") { //if IE 6
            $("body", "html").css({ height: "100%", width: "100%" });
            // KLIMOV: чтобы предотвратить мерцание скролл-бара в эксплорере (он исчезал при появлении окошка)
            //$("html").css("overflow","hidden");
            if (document.getElementById("TB_HideSelect") === null) { //iframe to hide select elements in ie6
                $("body").append("

");
                $("#TB_overlay").click(tb_remove);
            }
        } else { //all others
            if (document.getElementById("TB_overlay") === null) {
                $("body").append("

");
                $("#TB_overlay").click(tb_remove);
            }
        }

        if (tb_detectMacXFF()) {
            $("#TB_overlay").addClass("TB_overlayMacFFBGHack"); //use png overlay so hide flash
        } else {
            $("#TB_overlay").addClass("TB_overlayBG"); //use background and opacity
        }

        if (caption === null) {
            caption = "";
        }

        $("body").append('

'); //add loader to the page
        $('#TB_load').show(); //show loader

        // Балуев: изменено для поддержки веб-сервисов (в конце url должно быть имя файла)
        var urlString = /\.jpg$|\.jpeg$|\.png$|\.gif$|\.bmp$/;
        var baseURL;
        if (!(url.toLowerCase().match(urlString)) && url.indexOf("?") !== -1) { //ff there is a query string involved
            baseURL = url.substr(0, url.indexOf("?"));
        } else {
            baseURL = url;
        }

        var urlType = baseURL.toLowerCase().match(urlString);

        if (urlType == '.jpg' || urlType == '.jpeg' || urlType == '.png' || urlType == '.gif' || urlType == '.bmp') { //code to show images

            TB_PrevCaption = "";
            TB_PrevURL = "";
            TB_PrevHTML = "";
            TB_NextCaption = "";
            TB_NextURL = "";
            TB_NextHTML = "";
            TB_imageCount = "";
            TB_FoundURL = false;
            if (imageGroup) {
                TB_TempArray = $("a[@rel=" + imageGroup + "]").get();
                for (TB_Counter = 0; ((TB_Counter < TB_TempArray.length) && (TB_NextHTML === "")); TB_Counter++) {
                    var urlTypeTemp = TB_TempArray[TB_Counter].href.toLowerCase().match(urlString);
                    if (!(TB_TempArray[TB_Counter].href == url)) {
                        if (TB_FoundURL) {
                            TB_NextCaption = TB_TempArray[TB_Counter].title;
                            TB_NextURL = TB_TempArray[TB_Counter].href;
                            TB_NextHTML = "  Next >";
                        } else {
                            TB_PrevCaption = TB_TempArray[TB_Counter].title;
                            TB_PrevURL = TB_TempArray[TB_Counter].href;
                            TB_PrevHTML = "  < Prev";
                        }
                    } else {
                        TB_FoundURL = true;
                        TB_imageCount = "Image " + (TB_Counter + 1) + " of " + (TB_TempArray.length);
                    }
                }
            }

            imgPreloader = new Image();
            imgPreloader.onload = function () {
                imgPreloader.onload = null;

                // Resizing large images - orginal by Christian Montoya edited by me.
                var pagesize = tb_getPageSize();
                var x = pagesize[0] - 150;
                var y = pagesize[1] - 150;
                var imageWidth = imgPreloader.width;
                var imageHeight = imgPreloader.height;
                if (imageWidth > x) {
                    imageHeight = imageHeight * (x / imageWidth);
                    imageWidth = x;
                    if (imageHeight > y) {
                        imageWidth = imageWidth * (y / imageHeight);
                        imageHeight = y;
                    }
                } else if (imageHeight > y) {
                    imageWidth = imageWidth * (y / imageHeight);
                    imageHeight = y;
                    if (imageWidth > x) {
                        imageHeight = imageHeight * (x / imageWidth);
                        imageWidth = x;
                    }
                }
                // End Resizing

                TB_WIDTH = imageWidth + 30;
                TB_HEIGHT = imageHeight + 60;
                $("#TB_window").append("" + "
" + caption + "
" + TB_imageCount + TB_PrevHTML + TB_NextHTML + "

закрыть
");

                $("#TB_closeWindowButton").click(tb_remove);

                if (!(TB_PrevHTML === "")) {

                    function goPrev() {
                        if ($(document).unbind("click", goPrev)) {
                            $(document).unbind("click", goPrev);
                        }
                        $("#TB_window").remove();
                        $("body").append("

");
                        tb_show(TB_PrevCaption, TB_PrevURL, imageGroup);
                        return false;
                    }

                    $("#TB_prev").click(goPrev);
                }

                if (!(TB_NextHTML === "")) {

                    function goNext() {
                        $("#TB_window").remove();
                        $("body").append("

");
                        tb_show(TB_NextCaption, TB_NextURL, imageGroup);
                        return false;
                    }

                    $("#TB_next").click(goNext);

                }

                document.onkeydown = function (e) {
                    if (e == null) { // ie
                        keycode = event.keyCode;
                    } else { // mozilla
                        keycode = e.which;
                    }
                    if (keycode == 27) { // close
                        tb_remove();
                    } else if (keycode == 190) { // display previous image
                        if (!(TB_NextHTML == "")) {
                            document.onkeydown = "";
                            goNext();
                        }
                    } else if (keycode == 188) { // display next image
                        if (!(TB_PrevHTML == "")) {
                            document.onkeydown = "";
                            goPrev();
                        }
                    }
                };

                tb_position();
                $("#TB_load").remove();
                $("#TB_ImageOff").click(tb_remove);
                $("#TB_window").css({ display: "block" }); //for safari using css instead of show
            };

            imgPreloader.src = url;
        } else { //code to show html

            var queryString = url.replace(/^[^\?]+\??/, '');
            var params = tb_parseQuery(queryString);

            TB_WIDTH = (params['width'] * 1) + 30 || 630; //defaults to 630 if no paramaters were added to URL
            TB_HEIGHT = (params['height'] * 1) + 40 || 440; //defaults to 440 if no paramaters were added to URL

            // Если окно очень маленькое
            if ($(window).width() < TB_WIDTH) {
                TB_WIDTH = $(window).width() - 40;
            }

            if ($(window).height() < TB_HEIGHT) {
                TB_HEIGHT = $(window).height() - 40;
            }

            // Если thickbox открыт еще в thickbox - работает для iframe (лукапы)
            if (self != top) {
                var iframeLength = parent.document.getElementsByTagName("IFRAME").length;
                TB_HEIGHT = TB_HEIGHT - 60 * iframeLength;
                TB_WIDTH = TB_WIDTH - 40 * iframeLength;
            }

            ajaxContentW = TB_WIDTH - 30;
            ajaxContentH = TB_HEIGHT - 45;

            if (url.indexOf('TB_iframe') != -1) { // either iframe or ajax window
                urlNoQuery = url.split('TB_');
                $("#TB_iframeContent").remove();
                if (params['modal'] != "true") { //iframe no modal
                    $("#TB_window").append("

" + caption + "

закрыть

 ");
                } else { //iframe modal
                    $("#TB_overlay").unbind();
                    $("#TB_window").append(" ");
                }
            } else { // not an iframe, ajax
                if ($("#TB_window").css("display") != "block") {
                    if (params['modal'] != "true") { //ajax no modal
                        $("#TB_window").append("

" + caption + "

закрыть

");
                    } else { //ajax modal
                        $("#TB_overlay").unbind();
                        $("#TB_window").append("

");
                    }
                } else { //this means the window is already up, we are just loading new content via ajax
                    $("#TB_ajaxContent")[0].style.width = ajaxContentW + "px";
                    $("#TB_ajaxContent")[0].style.height = ajaxContentH + "px";
                    $("#TB_ajaxContent")[0].scrollTop = 0;
                    $("#TB_ajaxWindowTitle").html(caption);
                }
            }

            $("#TB_closeWindowButton").click(tb_remove);

            // Балуев: показ окна вынесен перед загрузкой,
            // чтобы на момент события ready контент был показан
            $("#TB_window").css({ display: "block" });
            if (url.indexOf('TB_inline') != -1) {
                $("#TB_ajaxContent").append($('#' + params['inlineId']).children());
                $("#TB_window").bind('unload.tb', function () {
                    $('#' + params['inlineId']).append($("#TB_ajaxContent").children()); // move elements back when you're finished
                });
                tb_position();
                $("#TB_load").remove();
            } else if (url.indexOf('TB_iframe') != -1) {
                tb_position();
                if ($.browser.safari) { //safari needs help because it will not fire iframe onload
                    $("#TB_load").remove();
                }
            } else {
                $("#TB_ajaxContent").load(url += "&random=" + (new Date().getTime()), function () { //to do a post change this load method
                    tb_position();
                    $("#TB_load").remove();
                    tb_init("#TB_ajaxContent a.thickbox");
                });
            }

        }

        if (!params['modal']) {
            document.onkeyup = function (e) {
                if (e == null) { // ie
                    keycode = event.keyCode;
                } else { // mozilla
                    keycode = e.which;
                }
                if (keycode == 27) { // close
                    tb_remove();
                }
            };
        }

    } catch (e) {
        //nothing here
    }

    // блок кода, который делает thickbox перемещаемым и размероизменяемым
    try {
        // Елисеев. А.: Т.к. текущая верстка WebErrorBox не соответствует ожиданиям thickbox,
        // то для возможности выделения текста добавлен параметр, отключающий перетаскивание
        // мышкой за блок содержимого.
        // TODO: Переверстать WebErrorBox.
        $('#TB_window')
            .draggable({ handle: "#TB_title", cancel: "#ctlWebErrorBox" });
        if (!params['noresize']) {

            // Iframe содержит в себе отдельный документ, который перехватывает различные события,
            // например mousemove. Из-за этого нельзя было уменьшить окно (движение курсора попадало в iframe).
            // Поэтому я добавил оверлей в модальное окно, который буду показывать при старте ресайза, и скрывать
            // по окончанию - т.е. iframe будет скрыт под этим блоком и не будет перехватывать события.
            var resizableOverlay = $("

");
            $('#TB_window').append(resizableOverlay);

            $('#TB_window')
                .resizable({
                    //alsoResize: "#TB_iframeContent",
                    animate: params["noanimate"] != "true",
                    helper: "ui-resizable-helper",
                    start: function () {
                        resizableOverlay.show();
                    },
                    stop: function (event, ui) {
                        var el = ui.element;
                        var hlp = ui.helper;

                        var h = hlp.height();
                        var w = hlp.width();

                        var old_h = el.height();
                        var old_w = el.width();

                        var fr = $('#TB_iframeContent,#TB_ajaxContent', ui.element);

                        fr.height(fr.height() + h - old_h - 8);
                        fr.width(fr.width() + w - old_w - 8);
                        // откуда цифра 8 я не знаю, но именно на столько рамка больше окна
                        // может быть ее можно взять из настроек jQuery-UI-resizable...

                        resizableOverlay.hide();
                    }
                });
        } else {
            $('#TB_window').addClass('TB_noresize');
        }
        $('#TB_title').css('cursor', 'move');
    } catch (e) {
        // Hier soll nichts passieren, zum Debuggen könnte ein Alert eingebunden werden
        // Hitler Kaput! :)
    }

    //Хаберев: Возвращаем проекцию Deffered-объекта для возможности добавлять асинхронные обработчики в дркгих скриптах
    return tb_CloseActionDeferred.promise();
}

//helper functions below
function tb_showIframe() {
    $("body").addClass("modal-open").attr("scroll", "no").css("overflow", "hidden");
    $("#TB_load").remove();
    $("#TB_window").css({ display: "block" });
}

function tb_remove() {
    $("#TB_imageOff").unbind("click");
    $("#TB_closeWindowButton").unbind("click");

    // Первый вариант - исходный, с ними были проблемы в работе MasterEditorAjaxLookup: при выборе элемента
    // thickbox закрывался, но основная форма оставалась неактивной.
    // Второй вариант - нормально функционирует MasterEditorAjaxLookup, но inline thickbox перестал работать,
    // т.к. не выполнялся обработчик  $("#TB_window").unload(...)
    // В третьем варианте исправлены предыдущие ошики введением пространства имен события.

    //$("#TB_window").fadeOut("fast", function () { $('#TB_window,#TB_overlay,#TB_HideSelect').trigger('unload').unbind().remove(); });
    //$("#TB_window").fadeOut("fast", function () { $('#TB_window,#TB_overlay,#TB_HideSelect').unload("#TB_ajaxContent").unbind().remove(); });

    // Убрана анимация скрытия, так как из-за неё блокировался MasterEditorAjaxLookUp в IE.
    $('#TB_window,#TB_overlay,#TB_HideSelect').trigger('unload.tb').unbind().remove();

    $("body").removeClass("modal-open").css("overflow","");

    $("#TB_load").remove();
    if (typeof document.body.style.maxHeight == "undefined") {//if IE 6
        $("body", "html").css({ height: "auto", width: "auto" });
        $("html").css("overflow", "");
    }

    //Хаберев: переводим Deffered-объект в состояние "выполнено", чтобы сработали обработчики событий в других скриптах
    tb_CloseActionDeferred.resolve();
    return false;
}

function tb_position() {
    $("#TB_window").css({ marginLeft: '-' + parseInt((TB_WIDTH / 2), 10) + 'px', width: TB_WIDTH + 'px' });
    if (!(jQuery.browser.msie && jQuery.browser.version < 7)) { // take away IE6
        $("#TB_window").css({ marginTop: '-' + parseInt((TB_HEIGHT / 2), 10) + 'px' });
    }
}

function tb_parseQuery(query) {
    var Params = {};
    if (!query) { return Params; } // return empty object
    var Pairs = query.split(/[;&]/);
    for (var i = 0; i < Pairs.length; i++) {
        var KeyVal = Pairs[i].split('=');
        if (!KeyVal || KeyVal.length != 2) { continue; }
        var key = unescape(KeyVal[0]);
        var val = unescape(KeyVal[1]);
        val = val.replace(/\+/g, ' ');
        Params[key] = val;
    }
    return Params;
}

function tb_getPageSize() {
    var de = document.documentElement;
    var w = window.innerWidth || self.innerWidth || (de && de.clientWidth) || document.body.clientWidth;
    var h = window.innerHeight || self.innerHeight || (de && de.clientHeight) || document.body.clientHeight;
    arrayPageSize = [w, h];
    return arrayPageSize;
}

function tb_detectMacXFF() {
    var userAgent = navigator.userAgent.toLowerCase();
    if (userAgent.indexOf('mac') != -1 && userAgent.indexOf('firefox') != -1) {
        return true;
    }
}

redpajama_set_name: RedPajamaGithub


text:
require('coffee-script');

var mFS = require('fs')
  , mPA = require('path')
  , mVM = require('vm')

  , mOP = require('operetta')
  , mUT = require('../lib/utils')
  , mCOUCH = require('../lib/couch')

var gProcess = process;
var gOptparser = new mOP.Operetta();

gOptparser.banner = "Setup a CouchDB database with fixures";

gOptparser.parameters(
        ['--dir'],
        "The directory to load fixtures from.");
gOptparser.parameters(
        ['--host'],
        "The hostname of the CouchDB server. The default is 'localhost'.");
gOptparser.parameters(
        ['--port'],
        "The port of the CouchDB server. The default is 5984.");
gOptparser.parameters(
        ['--username'],
        "CouchDB remote username");
gOptparser.parameters(
        ['--password'],
        "CouchDB remote password");
gOptparser.options(
        ['--no-load'],
        "Only delete the existing documents, don't load any new ones.");

function gMain(aOpts) {
    var oDir  = (aOpts['--dir'] || [])[0]
      , oHost = (aOpts['--host'] || [])[0] || 'localhost'
      , oPort = (aOpts['--port'] || [])[0] || 5984
      , oNoLoad = (aOpts['--no-load'] || [])[0] ? true : false
      , oUsername = (aOpts['--username'] || [])[0]
      , oPassword = (aOpts['--password'] || [])[0]
      , connectionSpec, db, dirname

    if (!oDir) {
        console.error("--dir parameter is required");
        gOptparser.usage();
        gProcess.exit(1);
    }

    connectionSpec = {
        host: oHost
      , port: oPort
    };

    if (oUsername && oPassword) {
        connectionSpec.authentication = {
            username: oUsername
          , password: oPassword
        };
    }

    dirname = mPA.basename(oDir).replace(/\/$/, '');
    if (!/_test_?/.test(dirname)) {
        throw new Error("'"+ dirname +"' is not a test database!");
    }

    db = new mCOUCH.createConnection(connectionSpec).use(dirname);
    gDeleteDocuments(db, function () {
        if (oNoLoad) {
            console.log("Done deleting documents. Exiting...");
            process.exit();
        }

        return gLoadDocuments(oDir, gPutDocument(db))
    });

    return;
}

function gDeleteDocuments(aDB, aCallback) {
    function deleteDocs(rows) {
        if (!rows || !rows.length) {
            return aCallback();
        }

        var iCount = rows.length;

        rows.forEach(function (row) {
            aDB.remove(row.id, row.value.rev, function (err, res) {
                iCount = iCount - 1;

                if (err) {
                    throw err;
                }

                console.log('     - deleted', row.id);
                if (iCount === 0) {
                    aCallback();
                }
            });
        });
    }

    aDB.get('_all_docs', function (err, res) {
        if (err) {
            throw err;
        }
        return deleteDocs(res.body.rows);
    });
    return;
}

function gLoadDocuments(aDir, aEmit) {
    var items;

    try {
        items = mFS.readdirSync(aDir);
    } catch (fileErr) {
        console.error("Problem reading fixture directory:");
        throw fileErr
    }

    items.forEach(function (item) {
        var path = mPA.join(aDir, item)
          , stats = mFS.statSync(path)
          , text, doc, sandbox

        if (!stats.isFile()) return;

        try {
            text = mFS.readFileSync(path, 'utf8');
        } catch (readErr) {
            console.error("Problem reading fixture file:");
            throw readErr;
        }

        if (/\.js$/.test(path)) {
            sandbox = {};

            text = gIncludes(text, aDir);

            try {
                mVM.runInNewContext(text, sandbox, path);
            } catch (vmErr) {
                console.error("Problem parsing design fixture");
                throw vmErr;
            }
            doc = sandbox;
            doc._id = '_design/'+ item.replace(/\.js$/, '');
            doc.language = 'javascript';
        } else if (/\.json$/.test(path)) {
            try {
                doc = JSON.parse(text);
            } catch (jsonErr) {
                console.error("Problem parsing fixture JSON, from", item);
                throw jsonErr;
            }
        }
        else {
            console.log(" --- Not loading", item);
            return;
        }

        console.log(" --- Loading", item);
        return aEmit(item, doc);
    });

    if (!items.length) {
        console.log('No document fixtures to load');
        process.exit();
    }

    return;
}

function gPutDocument(aDB) {
    return function (filename, doc) {
        var id = doc._id || mUT.uid();

        aDB.updateOrCreate(id, doc, function (err, res) {
            if (err) {
                console.error("Problem PUTing document", id);
                console.log(doc);
                throw err;
            }

            console.log(' --> ', filename, res.status, res.body);
        });
    };

    return;
}

function gIncludes(aText, aDir) {
    var i = 0
      , rx = /^[\s]+\/\/!\s([\.\/\w-]+)/
      , lines = aText.split('\n')
      , buff = []
      , line, text

    for (; i < lines.length; i += 1) {
        line = lines[i];
        match = rx.exec(line);

        if (match) {
            filePath = mPA.resolve(aDir, match[1]);
            try {
                text = mFS.readFileSync(filePath, 'utf8');
            } catch (readErr) {
                console.error("Problem reading lib file:");
                throw readErr;
            }
            buff.push(text);
        } else {
            buff.push(line);
        }
    }

    return buff.join('\n');
}

gOptparser.start(gMain);


text:
package com.netflix.paas.dao.astyanax;

import java.util.Collection;
import java.util.Map;

/**
 * Very very very simple indexing API.
 *
 * @author elandau
 *
 */
public interface Indexer {
    /**
     * Add the id to the tags
     * @param id
     * @param tags
     */
    public void tagId(String id, Map<String, String> tags) throws IndexerException ;

    /**
     * Remove id from all it's tags
     * @param id
     */
    public void removeId(String id) throws IndexerException ;

    /**
     * Get all tags for a document
     * @param id
     * @return
     */
    public Map<String, String> getTags(String id) throws IndexerException;

    /**
     * Find all ids that have one or more of these tags
     * @param tags
     * @return
     */
    public Collection<String> findUnion(Map<String, String> tags) throws IndexerException ;

    /**
     * Find all ids that have all of the tags
     * @param tags
     * @return
     */
    public Collection<String> findIntersection(Map<String, String> tags) throws IndexerException ;

    /**
     * Find all ids that match the tag
     * @param tag
     * @return
     */
    public Collection<String> find(String name, String value) throws IndexerException ;

    /**
     * Create the underlying storage
     */
    public void createStorage() throws IndexerException ;
}


text:
package org.sagebionetworks.object.snapshot.worker.utils;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.io.IOException;
import java.util.Arrays;
import java.util.Date;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.sagebionetworks.asynchronous.workers.sqs.MessageUtils;
import org.sagebionetworks.audit.dao.ObjectRecordDAO;
import org.sagebionetworks.audit.utils.ObjectRecordBuilderUtils;
import org.sagebionetworks.common.util.progress.ProgressCallback;
import org.sagebionetworks.repo.model.ObjectType;
import org.sagebionetworks.repo.model.audit.FileHandleSnapshot;
import org.sagebionetworks.repo.model.audit.ObjectRecord;
import org.sagebionetworks.repo.model.dao.FileHandleDao;
import org.sagebionetworks.repo.model.file.ExternalFileHandle;
import org.sagebionetworks.repo.model.file.ExternalObjectStoreFileHandle;
import org.sagebionetworks.repo.model.file.FileHandle;
import org.sagebionetworks.repo.model.file.GoogleCloudFileHandle;
import org.sagebionetworks.repo.model.file.ProxyFileHandle;
import org.sagebionetworks.repo.model.file.S3FileHandle;
import org.sagebionetworks.repo.model.message.ChangeMessage;
import org.sagebionetworks.repo.model.message.ChangeType;

import com.amazonaws.services.sqs.model.Message;

@ExtendWith(MockitoExtension.class)
public class FileHandleSnapshotRecordWriterTest {

	@Mock
	private FileHandleDao mockFileHandleDao;
	@Mock
	private ObjectRecordDAO mockObjectRecordDao;
	@Mock
	private ProgressCallback mockCallback;

	@InjectMocks
	private FileHandleSnapshotRecordWriter writer;

	private String id = "123";

	@Test
	public void deleteFileMessageTest() throws IOException {
		Message message = MessageUtils.buildMessage(ChangeType.DELETE, id, ObjectType.FILE, "etag", System.currentTimeMillis());
		ChangeMessage changeMessage = MessageUtils.extractMessageBody(message);
		writer.buildAndWriteRecords(mockCallback, Arrays.asList(changeMessage));
		verify(mockObjectRecordDao, never()).saveBatch(anyList(), anyString());
	}

	@Test
	public void invalidChangeMessageTest() throws IOException {
		Message message = MessageUtils.buildMessage(ChangeType.UPDATE, id, ObjectType.PRINCIPAL, "etag", System.currentTimeMillis());
		ChangeMessage changeMessage = MessageUtils.extractMessageBody(message);
		assertThrows(IllegalArgumentException.class, () -> writer.buildAndWriteRecords(mockCallback, Arrays.asList(changeMessage)));
	}

	@Test
	public void validChangeMessageTest() throws IOException {
		FileHandle fileHandle = new S3FileHandle();
		fileHandle.setEtag("etag");
		when(mockFileHandleDao.get(id)).thenReturn(fileHandle);

		Message message = MessageUtils.buildMessage(ChangeType.UPDATE, id, ObjectType.FILE, "etag", System.currentTimeMillis());
		ChangeMessage changeMessage = MessageUtils.extractMessageBody(message);
		FileHandleSnapshot record = FileHandleSnapshotRecordWriter.buildFileHandleSnapshot(fileHandle);
		ObjectRecord expected = ObjectRecordBuilderUtils.buildObjectRecord(record, changeMessage.getTimestamp().getTime());
		writer.buildAndWriteRecords(mockCallback, Arrays.asList(changeMessage, changeMessage));
		verify(mockFileHandleDao, times(2)).get(id);
		verify(mockObjectRecordDao).saveBatch(eq(Arrays.asList(expected, expected)), eq(expected.getJsonClassName()));
	}

	@Test
	public void testBuildFileHandleSnapshotWithS3FileHandle() {
		S3FileHandle s3FH = new S3FileHandle();
		s3FH.setBucketName("bucket");
		s3FH.setConcreteType(S3FileHandle.class.getName());
		s3FH.setContentMd5("md5");
		s3FH.setContentSize(1L);
		s3FH.setCreatedBy("998");
		s3FH.setCreatedOn(new Date());
		s3FH.setFileName("fileName");
		s3FH.setId("555");
		s3FH.setKey("key");
		s3FH.setStorageLocationId(900L);
		FileHandleSnapshot snapshot = FileHandleSnapshotRecordWriter.buildFileHandleSnapshot(s3FH);
		assertEquals(s3FH.getBucketName(), snapshot.getBucket());
		assertEquals(s3FH.getConcreteType(), snapshot.getConcreteType());
		assertEquals(s3FH.getContentMd5(), snapshot.getContentMd5());
		assertEquals(s3FH.getContentSize(), snapshot.getContentSize());
		assertEquals(s3FH.getCreatedBy(), snapshot.getCreatedBy());
		assertEquals(s3FH.getCreatedOn(), snapshot.getCreatedOn());
		assertEquals(s3FH.getFileName(), snapshot.getFileName());
		assertEquals(s3FH.getId(), snapshot.getId());
		assertEquals(s3FH.getKey(), snapshot.getKey());
		assertEquals(s3FH.getStorageLocationId(), snapshot.getStorageLocationId());
	}

	@Test
	public void testBuildFileHandleSnapshotWithGoogleCloudFileHandle() {
		GoogleCloudFileHandle googleCloudFileHandle = new GoogleCloudFileHandle();
		googleCloudFileHandle.setBucketName("bucket");
		googleCloudFileHandle.setConcreteType(S3FileHandle.class.getName());
		googleCloudFileHandle.setContentMd5("md5");
		googleCloudFileHandle.setContentSize(1L);
		googleCloudFileHandle.setCreatedBy("998");
		googleCloudFileHandle.setCreatedOn(new Date());
		googleCloudFileHandle.setFileName("fileName");
		googleCloudFileHandle.setId("555");
		googleCloudFileHandle.setKey("key");
		googleCloudFileHandle.setStorageLocationId(900L);
		FileHandleSnapshot snapshot = FileHandleSnapshotRecordWriter.buildFileHandleSnapshot(googleCloudFileHandle);
		assertEquals(googleCloudFileHandle.getBucketName(), snapshot.getBucket());
		assertEquals(googleCloudFileHandle.getConcreteType(), snapshot.getConcreteType());
		assertEquals(googleCloudFileHandle.getContentMd5(), snapshot.getContentMd5());
		assertEquals(googleCloudFileHandle.getContentSize(), snapshot.getContentSize());
		assertEquals(googleCloudFileHandle.getCreatedBy(), snapshot.getCreatedBy());
		assertEquals(googleCloudFileHandle.getCreatedOn(), snapshot.getCreatedOn());
		assertEquals(googleCloudFileHandle.getFileName(), snapshot.getFileName());
		assertEquals(googleCloudFileHandle.getId(), snapshot.getId());
		assertEquals(googleCloudFileHandle.getKey(), snapshot.getKey());
		assertEquals(googleCloudFileHandle.getStorageLocationId(), snapshot.getStorageLocationId());
	}

	@Test
	public void testBuildFileHandleSnapshotWithExternalFileHandle() {
		ExternalFileHandle externalFH = new ExternalFileHandle();
		externalFH.setConcreteType(S3FileHandle.class.getName());
		externalFH.setContentMd5("md5");
		externalFH.setContentSize(1L);
		externalFH.setCreatedBy("998");
		externalFH.setCreatedOn(new Date());
		externalFH.setFileName("fileName");
		externalFH.setId("555");
		externalFH.setExternalURL("externalURL");
		externalFH.setStorageLocationId(900L);
		FileHandleSnapshot snapshot = FileHandleSnapshotRecordWriter.buildFileHandleSnapshot(externalFH);
		assertNull(snapshot.getBucket());
		assertEquals(externalFH.getConcreteType(), snapshot.getConcreteType());
		assertEquals(externalFH.getContentMd5(), snapshot.getContentMd5());
		assertEquals(externalFH.getContentSize(), snapshot.getContentSize());
		assertEquals(externalFH.getCreatedBy(), snapshot.getCreatedBy());
		assertEquals(externalFH.getCreatedOn(), snapshot.getCreatedOn());
		assertEquals(externalFH.getFileName(), snapshot.getFileName());
		assertEquals(externalFH.getId(), snapshot.getId());
		assertEquals(externalFH.getExternalURL(), snapshot.getKey());
		assertEquals(externalFH.getStorageLocationId(), snapshot.getStorageLocationId());
	}

	@Test
	public void testBuildFileHandleSnapshotWithProxyFileHandle() {
		ProxyFileHandle proxyFH = new ProxyFileHandle();
		proxyFH.setConcreteType(ProxyFileHandle.class.getName());
		proxyFH.setContentMd5("md5");
		proxyFH.setContentSize(1L);
		proxyFH.setCreatedBy("998");
		proxyFH.setCreatedOn(new Date());
		proxyFH.setFileName("fileName");
		proxyFH.setId("555");
		proxyFH.setFilePath("filePath");
		proxyFH.setStorageLocationId(900L);
		FileHandleSnapshot snapshot = FileHandleSnapshotRecordWriter.buildFileHandleSnapshot(proxyFH);
		assertNull(snapshot.getBucket());
		assertEquals(proxyFH.getConcreteType(), snapshot.getConcreteType());
		assertEquals(proxyFH.getContentMd5(), snapshot.getContentMd5());
		assertEquals(proxyFH.getContentSize(), snapshot.getContentSize());
		assertEquals(proxyFH.getCreatedBy(), snapshot.getCreatedBy());
		assertEquals(proxyFH.getCreatedOn(), snapshot.getCreatedOn());
		assertEquals(proxyFH.getFileName(), snapshot.getFileName());
		assertEquals(proxyFH.getId(), snapshot.getId());
		assertEquals(proxyFH.getFilePath(), snapshot.getKey());
		assertEquals(proxyFH.getStorageLocationId(), snapshot.getStorageLocationId());
	}

	@Test
	public void testBuildFileHandleSnapshotWithExternalObjectStoreFileHandle() {
		ExternalObjectStoreFileHandle externalObjectStoreFileHandle = new ExternalObjectStoreFileHandle();
		externalObjectStoreFileHandle.setConcreteType(ExternalObjectStoreFileHandle.class.getName());
		externalObjectStoreFileHandle.setContentMd5("md5");
		externalObjectStoreFileHandle.setContentSize(1L);
		externalObjectStoreFileHandle.setCreatedBy("998");
		externalObjectStoreFileHandle.setCreatedOn(new Date());
		externalObjectStoreFileHandle.setFileName("fileName");
		externalObjectStoreFileHandle.setId("555");
		externalObjectStoreFileHandle.setFileKey("key");
		externalObjectStoreFileHandle.setStorageLocationId(900L);
		FileHandleSnapshot snapshot = FileHandleSnapshotRecordWriter.buildFileHandleSnapshot(externalObjectStoreFileHandle);
		assertNull(snapshot.getBucket());
		assertEquals(externalObjectStoreFileHandle.getConcreteType(), snapshot.getConcreteType());
		assertEquals(externalObjectStoreFileHandle.getContentMd5(), snapshot.getContentMd5());
		assertEquals(externalObjectStoreFileHandle.getContentSize(), snapshot.getContentSize());
		assertEquals(externalObjectStoreFileHandle.getCreatedBy(), snapshot.getCreatedBy());
		assertEquals(externalObjectStoreFileHandle.getCreatedOn(), snapshot.getCreatedOn());
		assertEquals(externalObjectStoreFileHandle.getFileName(), snapshot.getFileName());
		assertEquals(externalObjectStoreFileHandle.getId(), snapshot.getId());
		assertEquals(externalObjectStoreFileHandle.getFileKey(), snapshot.getKey());
		assertEquals(externalObjectStoreFileHandle.getStorageLocationId(), snapshot.getStorageLocationId());
	}
}


text:
<!doctype html>

		<title>Socket.IO chat</title>
		<link rel="stylesheet" type="text/css" href="./styles/style.css" />

			<form action="">
				<input id="m" autocomplete="off" /><button>Send</button>
			</form>


text:
(function (global) {
    global.runCommands = function (commands) {
        var commandsToSend = [];

        for (var i = 0; i < arguments.length; i++) {
            commandsToSend.push(arguments[i]);
        }

        $.ajax({
            type: 'POST',
            url: './api/v1/shell',
            cache: false,
            dataType: 'json',
            contentType: 'application/json; charset=utf-8',
            data: JSON.stringify({
                commands: commandsToSend
            })
        }).then(data => {
            var output = data.output;
            console.log.apply(console, output);
        });
    };
})(this);


text:
class Devise::ArchangelCallbacksController < DeviseController
  prepend_before_filter { request.env["devise.skip_timeout"] = true }

  def passthru
    render :status => 404, :text => "Not found. Authentication passthru."
  end

  def failure
    set_flash_message :alert, :failure, :kind => Archangel::Utils.camelize(failed_strategy.name), :reason => failure_message
    redirect_to after_archangel_failure_path_for(resource_name)
  end

  protected

  def failed_strategy
    env["archangel.error.strategy"]
  end

  def failure_message
    exception = env["archangel.error"]
    error   = exception.error_reason if exception.respond_to?(:error_reason)
    error ||= exception.error        if exception.respond_to?(:error)
    error ||= env["archangel.error.type"].to_s
    error.to_s.humanize if error
  end

  def after_archangel_failure_path_for(scope)
    new_session_path(scope)
  end
end


text:
package org.dcm4chex.service;

import java.io.IOException;
import java.sql.SQLException;

import org.dcm4che.data.Command;
import org.dcm4che.data.Dataset;
import org.dcm4che.data.DcmObjectFactory;
import org.dcm4che.dict.Tags;
import org.dcm4che.dict.UIDs;
import org.dcm4che.net.AAssociateAC;
import org.dcm4che.net.AAssociateRQ;
import org.dcm4che.net.ActiveAssociation;
import org.dcm4che.net.Association;
import org.dcm4che.net.AssociationFactory;
import org.dcm4che.net.Dimse;
import org.dcm4che.net.DimseListener;
import org.dcm4che.net.PDU;
import org.dcm4chex.archive.ejb.jdbc.AEData;

/**
 * @author gunter.zeilinger@tiani.com
 * @version $Revision: 1091 $ $Date: 2004-04-24 21:42:49 +0800 (周六, 24 4月 2004) $
 * @since 20.04.2004
 */
class MoveForwardCmd {

    private static final AssociationFactory af = AssociationFactory
            .getInstance();

    private static final DcmObjectFactory of = DcmObjectFactory.getInstance();

    private static final String IMAGE = "IMAGE";

    private static final int MSGID = 1;

    private static final int PCID = 1;

    private static final String[] NATIVE_TS = { UIDs.ExplicitVRLittleEndian,
            UIDs.ImplicitVRLittleEndian};

    private final QueryRetrieveScpService service;

    private final AEData aeData;

    private final String callingAET;

    private final String destAET;

    private final int priority;

    private final String[] iuids;

    private ActiveAssociation aa;

    public MoveForwardCmd(QueryRetrieveScpService service, String callingAET,
            String retrieveAET, int priority, String destAET, String[] iuids)
            throws SQLException, UnkownAETException {
        this.service = service;
        this.callingAET = callingAET;
        this.aeData = service.queryAEData(retrieveAET);
        this.destAET = destAET;
        this.iuids = iuids;
        this.priority = priority;
    }

    public void execute(DimseListener moveRspListener)
            throws InterruptedException, IOException {
        Association a = af.newRequestor(service.createSocket(aeData));
        a.setAcTimeout(service.getAcTimeout());
        AAssociateRQ rq = af.newAAssociateRQ();
        rq.setCalledAET(aeData.getTitle());
        rq.setCallingAET(callingAET);
        rq.addPresContext(af.newPresContext(PCID,
                UIDs.StudyRootQueryRetrieveInformationModelMOVE, NATIVE_TS));
        PDU ac = a.connect(rq);
        if (!(ac instanceof AAssociateAC)) { throw new IOException(
                "Association not accepted by " + aeData + ":\n" + ac); }
        ActiveAssociation aa = af.newActiveAssociation(a, null);
        aa.start();
        try {
            if (a.getAcceptedTransferSyntaxUID(PCID) == null) { throw new IOException(
                    "Study Root IM MOVE Service not supported by " + aeData); }
            Command cmd = of.newCommand();
            cmd.initCMoveRQ(MSGID,
                    UIDs.StudyRootQueryRetrieveInformationModelMOVE, priority,
                    destAET);
            Dataset ds = of.newDataset();
            ds.putCS(Tags.QueryRetrieveLevel, IMAGE);
            ds.putUI(Tags.SOPInstanceUID, iuids);
            Dimse cmoverq = af.newDimse(PCID, cmd, ds);
            aa.invoke(cmoverq, moveRspListener);
        } finally {
            try {
                aa.release(true);
                // workaround to ensure that the final MOVE-RSP of forwarded
                // MOVE-RQ is processed before the final MOVE-RSP is sent
                // to the primary Move Originator
                Thread.sleep(10);
            } catch (Exception ignore) {
            }
        }
    }

    public void cancel() throws IOException {
        if (aa == null)
            return;
        Command cmd = of.newCommand();
        cmd.initCCancelRQ(MSGID);
        Dimse ccancelrq = af.newDimse(PCID, cmd);
        aa.getAssociation().write(ccancelrq);
    }
}


text:
namespace switches {

// The default device scale factor to apply to the browser UI and
// the contents in the absence of a viewport meta tag.
const char kDefaultDeviceScaleFactor[] = "default-device-scale-factor";

// Let text glyphs have X-positions that aren't snapped to the pixel grid.
const char kEnableTextSubpixelPositioning[] =
    "enable-text-subpixel-positioning";

// Enable touch screen calibration.
const char kEnableTouchCalibration[] = "enable-touch-calibration";

// Enable support for touch events.
const char kEnableTouchEvents[] = "enable-touch-events";

// The language file that we want to try to open. Of the form
// language[-country] where language is the 2 letter code from ISO-639.
const char kLang[] = "lang";

// Load the locale resources from the given path. When running on Mac/Unix the
// path should point to a locale.pak file.
const char kLocalePak[] = "locale_pak";

// Disable ui::MessageBox. This is useful when running as part of scripts that
// do not have a user interface.
const char kNoMessageBox[] = "no-message-box";

// Enables UI changes that make it easier to use with a touchscreen.
// WARNING: Do not check this flag directly when deciding what UI to draw,
// instead you must call ui::GetDisplayLayout
const char kTouchOptimizedUI[]              = "touch-optimized-ui";

// The values the kTouchOptimizedUI switch may have, as in
// "--touch-optimized-ui=disabled".
//   auto: Enabled on monitors which have touchscreen support (default).
const char kTouchOptimizedUIAuto[] = "auto";
//   enabled: always optimized for touch (even if no touch support).
const char kTouchOptimizedUIEnabled[] = "enabled";
//   disabled: never optimized for touch.
const char kTouchOptimizedUIDisabled[] = "disabled";

#if defined(OS_MACOSX)
const char kDisableCompositedCoreAnimationPlugins[] =
    "disable-composited-core-animation-plugins";
#endif

}  // namespace switches


text:
import {Heading, Text} from '@sanity/ui'
import React from 'react'
import styled from 'styled-components'

// Without this container, editing with Android breaks due to how Text is styled via responsiveFont in @sanity/ui
const TextContainer = styled.div`
  display: block;
`

export const Normal = ({children, ...rest}) => (
  <Text data-testid="text-style--normal" {...rest}>
    <TextContainer>{children}</TextContainer>
  </Text>
)

export const Heading1 = ({children, ...rest}) => (
  <Heading as="h1" data-testid="text-style--h1" size={5} {...rest}>
    <TextContainer>{children}</TextContainer>
  </Heading>
)

export const Heading2 = ({children, ...rest}) => (
  <Heading as="h2" data-testid="text-style--h2" size={4} {...rest}>
    <TextContainer>{children}</TextContainer>
  </Heading>
)

export const Heading3 = ({children, ...rest}) => (
  <Heading as="h3" data-testid="text-style--h3" size={3} {...rest}>
    <TextContainer>{children}</TextContainer>
  </Heading>
)

export const Heading4 = ({children, ...rest}) => (
  <Heading as="h4" data-testid="text-style--h4" size={2} {...rest}>
    <TextContainer>{children}</TextContainer>
  </Heading>
)

export const Heading5 = ({children, ...rest}) => (
  <Heading as="h5" data-testid="text-style--h5" size={1} {...rest}>
    <TextContainer>{children}</TextContainer>
  </Heading>
)

export const Heading6 = ({children, ...rest}) => (
  <Heading as="h6" data-testid="text-style--h6" size={0} {...rest}>
    <TextContainer>{children}</TextContainer>
  </Heading>
)

const BlockQuoteRoot = styled.blockquote`
  position: relative;
  display: block;
  margin: 0;
  padding-left: ${({theme}) => theme.sanity.space[3]}px;

  &::before {
    content: '';
    position: absolute;
    left: 0;
    top: -4px;
    bottom: -4px;
    width: 3px;
    background: var(--card-border-color);
  }
`

export const BlockQuote = ({children, ...rest}) => (
  <BlockQuoteRoot data-testid="text-style--blockquote" {...rest}>
    <Text as="p">{children}</Text>
  </BlockQuoteRoot>
)

export const TEXT_STYLES = {
  normal: Normal,
  h1: Heading1,
  h2: Heading2,
  h3: Heading3,
  h4: Heading4,
  h5: Heading5,
  h6: Heading6,
  blockquote: BlockQuote,
}


text:
#pragma once
#include <aws/ec2/EC2_EXPORTS.h>
#include <aws/core/utils/memory/stl/AWSStreamFwd.h>
#include <aws/core/utils/memory/stl/AWSString.h>

namespace Aws
{
namespace Utils
{
namespace Xml
{
  class XmlNode;
} // namespace Xml
} // namespace Utils
namespace EC2
{
namespace Model
{
  /*

Describes a Spot Instance state change.

  */
  class AWS_EC2_API SpotInstanceStateFault
  {
  public:
    SpotInstanceStateFault();
    SpotInstanceStateFault(const Aws::Utils::Xml::XmlNode& xmlNode);
    SpotInstanceStateFault& operator=(const Aws::Utils::Xml::XmlNode& xmlNode);

    void OutputToStream(Aws::OStream& ostream, const char* location, unsigned index, const char* locationValue) const;
    void OutputToStream(Aws::OStream& oStream, const char* location) const;

    /*

The reason code for the Spot Instance state change.

    */
    inline const Aws::String& GetCode() const{ return m_code; }

    /*

The reason code for the Spot Instance state change.

    */
    inline void SetCode(const Aws::String& value) { m_codeHasBeenSet = true; m_code = value; }

    /*

The reason code for the Spot Instance state change.

    */
    inline void SetCode(Aws::String&& value) { m_codeHasBeenSet = true; m_code = value; }

    /*

The reason code for the Spot Instance state change.

    */
    inline void SetCode(const char* value) { m_codeHasBeenSet = true; m_code.assign(value); }

    /*

The reason code for the Spot Instance state change.

    */
    inline SpotInstanceStateFault& WithCode(const Aws::String& value) { SetCode(value); return *this;}

    /*

The reason code for the Spot Instance state change.

    */
    inline SpotInstanceStateFault& WithCode(Aws::String&& value) { SetCode(value); return *this;}

    /*

The reason code for the Spot Instance state change.

    */
    inline SpotInstanceStateFault& WithCode(const char* value) { SetCode(value); return *this;}

    /*

The message for the Spot Instance state change.

    */
    inline const Aws::String& GetMessage() const{ return m_message; }

    /*

The message for the Spot Instance state change.

    */
    inline void SetMessage(const Aws::String& value) { m_messageHasBeenSet = true; m_message = value; }

    /*

The message for the Spot Instance state change.

    */
    inline void SetMessage(Aws::String&& value) { m_messageHasBeenSet = true; m_message = value; }

    /*

The message for the Spot Instance state change.

    */
    inline void SetMessage(const char* value) { m_messageHasBeenSet = true; m_message.assign(value); }

    /*

The message for the Spot Instance state change.

    */
    inline SpotInstanceStateFault& WithMessage(const Aws::String& value) { SetMessage(value); return *this;}

    /*

The message for the Spot Instance state change.

    */
    inline SpotInstanceStateFault& WithMessage(Aws::String&& value) { SetMessage(value); return *this;}

    /*

The message for the Spot Instance state change.

    */
    inline SpotInstanceStateFault& WithMessage(const char* value) { SetMessage(value); return *this;}

  private:
    Aws::String m_code;
    bool m_codeHasBeenSet;
    Aws::String m_message;
    bool m_messageHasBeenSet;
  };

} // namespace Model
} // namespace EC2
} // namespace Aws


text:
package ru.obolensk.afff.beetle.request;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Multimap;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import ru.obolensk.afff.beetle.log.LoggablePrintWriter;
import ru.obolensk.afff.beetle.log.Logger;
import ru.obolensk.afff.beetle.log.Writer;
import ru.obolensk.afff.beetle.protocol.HttpHeader;
import ru.obolensk.afff.beetle.protocol.HttpHeaderValue;
import ru.obolensk.afff.beetle.protocol.HttpHeaderValueAttribute;
import ru.obolensk.afff.beetle.protocol.HttpMethod;
import ru.obolensk.afff.beetle.protocol.HttpVersion;
import ru.obolensk.afff.beetle.protocol.MimeType;
import ru.obolensk.afff.beetle.stream.LimitedBufferedReader;
import ru.obolensk.afff.beetle.util.RequestUtil;
import ru.obolensk.afff.beetle.util.UriUtil;

import static lombok.AccessLevel.PROTECTED;
import static ru.obolensk.afff.beetle.core.Storage.ROOT;
import static ru.obolensk.afff.beetle.protocol.HttpMethod.GET;
import static ru.obolensk.afff.beetle.protocol.HttpMethod.HEAD;
import static ru.obolensk.afff.beetle.util.UriUtil.decode;

/**
 * Created by Afff on 10.04.2017.
 */
public class Request {

    private static final Logger logger = new Logger(Request.class);

    @Nonnull @Getter
    private final LimitedBufferedReader reader;

    @Nonnull @Getter
    private final OutputStream outputStream;

    @Nonnull @Getter
    private final Writer writer;

    @Nonnull @Getter @Setter(AccessLevel.MODULE)
    private String rawData;

    @Nonnull @Getter
    private final InetAddress ip;

    @Nonnull @Getter
    private final HttpMethod method;

    @Nullable @Getter
    private final URI uri;

    @Nonnull @Getter
    private final HttpVersion version;

    @Nonnull @Getter
    private final Map<String, String> parameters = new HashMap<>();

    @Nonnull @Getter
    private final Multimap<HttpHeader, AttributedValue> headers = LinkedListMultimap.create();

    @Nonnull @Getter
    private final List<MultipartData> multipartData = new ArrayList<>();

    @Getter
    private final boolean invalid;

    @Nullable @Getter @Setter(PROTECTED)
    private int entitySize;

    private Request(@Nonnull final LimitedBufferedReader reader,
                    @Nonnull final OutputStream outputStream,
                    @Nonnull final InetAddress ip,
                    @Nonnull final String method,
                    @Nonnull final String uri,
                    @Nonnull final String version) {
        this(reader, outputStream, ip, HttpMethod.decode(method), uri, HttpVersion.decode(version));
    }

    private Request(@Nonnull final LimitedBufferedReader reader,
                    @Nonnull final OutputStream outputStream,
                    @Nonnull final InetAddress ip,
                    @Nonnull final HttpMethod method,
                    @Nullable final String uri,
                    @Nonnull final HttpVersion version) {
        this.reader = reader;
        this.outputStream = outputStream;
        this.writer = new LoggablePrintWriter(outputStream, logger);
        this.ip = ip;
        this.method = method;
        this.uri = readUriAndParams(uri);
        this.version = version;
        this.invalid = method == HttpMethod.UNKNOWN || uri == null || version == HttpVersion.UNKNOWN;
    }

    static Request makeNew(@Nonnull final LimitedBufferedReader reader, @Nonnull final OutputStream outputStream, @Nonnull final InetAddress ip, @Nonnull final String method, @Nonnull final String uri, @Nonnull final String version) {
        return new Request(reader, outputStream, ip, method, uri, version);
    }

    boolean addHeader(@Nonnull final String line) {
        return RequestUtil.addHeader(headers, line);
    }

    @Nullable
    String getHeaderValue(@Nonnull final HttpHeader header) {
        return RequestUtil.getHeaderValue(headers, header);
    }

    @Nullable
    public String getHeaderAttribute(@Nonnull final HttpHeader header,
                                     @Nonnull final HttpHeaderValueAttribute attr) {
        return RequestUtil.getHeaderAttribute(headers, header, attr);
    }

    public boolean hasHeaderValue(@Nonnull final HttpHeader header,
                                  @Nonnull final HttpHeaderValue value) {
        return RequestUtil.hasHeaderValue(headers, header, value);
    }

    @Nullable
    private URI readUriAndParams(@Nullable String uri) {
        if (uri == null) {
            return null;
        }
        if (method == GET || method == HEAD) {
            final String[] params = uri.split("[?;]");
            uri = params[0];
            if (params.length > 1) {
                parseParams(params[1]);
            }
        }
        return UriUtil.toURI(uri);
    }

    public void parseParams(@Nonnull final String params) {
        final String[] paramsArr = params.split("&");
        for (final String param : paramsArr) {
            final String[] parts = param.split("=");
            addParameter(parts[0].trim(), parts.length > 1 ? decode(parts[1]).trim() : null);
        }
    }

    void addParameter(@Nonnull final String name, @Nullable final String value) {
        this.parameters.put(name, value);
    }

    public boolean shouldWriteBody() {
        return method != HttpMethod.HEAD;
    }

    public boolean hasEntity() {
        return entitySize != 0;
    }

    public void skipEntityQuietly() {
        if (hasEntity()) {
            try {
                long actualSkipped = reader.skip(entitySize);
                if (actualSkipped != entitySize) {
                    logger.warn("Malformed HTTP request: entity should have "
                            + entitySize + " but it has only " + actualSkipped + " bytes.");
                }
            } catch (IOException e) {
                logger.error(e);
            }
        }
    }

    @Nonnull
    public String getLocalPath() {
        final String path = uri != null ? uri.getPath() : "";
        return path.isEmpty() ? ROOT.toString() : path;
    }

    @Nonnull
    public String getPathForFile(@Nonnull final String fileName) {
        final String path = uri != null ? uri.resolve(fileName).getPath() : "";
        return path.isEmpty() ? ROOT.resolve(fileName).toString() : path;
    }

    @Nonnull
    public MimeType getContentType() {
        return MimeType.getByName(getHeaderValue(HttpHeader.CONTENT_TYPE));
    }

}


text:
@implementation MWI18N

static NSString *language_;
static MWMessageStore *store_;

+ (void)setLanguage:(NSString *)language
{
    language_ = [MWI18N filterLanguage:language];
    MWMessageStore *fallback;
    if ([language_ isEqualToString:@"en"]) {
        fallback = nil;
    } else {
        // fixme use the fallbacks table
        fallback = [[MWMessageStore alloc] initWithLanguageCode:@"en" fallback:nil];
    }
    store_ = [[MWMessageStore alloc] initWithLanguageCode:language_ fallback:fallback];
}

+ (NSString *)fetchMessage:(NSString *)key inLanguage:(NSString *)language
{
    // fixme use the language thingy
    return [store_ fetchMessage:key];
}

// Take an iOS locale string and turn it into one of ours.
// Warning: not always idempotent!
+ (NSString *)filterLanguage:(NSString *)language
{
    // Force to lowercase to fix eg 'zh-Hans' -> 'zh-hans'
    NSString *filtered = [language lowercaseString];

    // Some awful special cases :)
    if ([language isEqualToString:@"pt-pt"]) {
        filtered = @"pt";
    } else if ([language isEqualToString:@"pt"]) {
        filtered = @"pt-br";
    }
    return filtered;
}

@end


text:
CRPCalendar
===========

Calendar Component for iOS platforms.


text:
// Copyright 2016 Twitter. All rights reserved.
//
// Licensed 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.

package com.twitter.heron.common.basics;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Matchers;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

/**
 * FileUtils Tester.
 */
@RunWith(PowerMockRunner.class)
@PrepareForTest(FileUtils.class)
public class FileUtilsTest {

  @Before
  public void before() throws Exception {
  }

  @After
  public void after() throws Exception {
  }

  /**
   * Method: deleteFile(String filename)
   */
  @Test
  public void testDeleteFile() throws Exception {
    PowerMockito.mockStatic(Files.class);

    Assert.assertTrue(FileUtils.deleteFile(""));
  }

  /**
   * Method: copyFile(String source, String target)
   */
  @Test
  public void testCopyFile() throws Exception {
    PowerMockito.mockStatic(Files.class);

    Assert.assertTrue(FileUtils.copyFile("", ""));
  }

  /**
   * Method: writeToFile(String filename, byte[] contents)
   */
  @Test
  public void testWriteToFile() throws Exception {
    String currentWorkingDir = Paths.get("").toAbsolutePath().normalize().toString();
    Assert.assertFalse(FileUtils.writeToFile(currentWorkingDir, new byte[]{}, false));

    PowerMockito.mockStatic(Files.class);
    String randomString = UUID.randomUUID().toString();
    Assert.assertTrue(FileUtils.writeToFile(randomString, null, false));

    // We can overwrite it
    Assert.assertTrue(FileUtils.writeToFile(randomString, null, true));
  }

  /**
   * Method: readFromFile(String filename)
   */
  @Test
  public void testReadFromFile() throws Exception {
    String toRead = "abc";
    PowerMockito.mockStatic(Files.class);
    PowerMockito.when(Files.readAllBytes(Matchers.any(Path.class))).thenReturn(toRead.getBytes());

    Assert.assertEquals(new String(FileUtils.readFromFile("")), toRead);
  }

  /**
   * Method: createDirectory(String directory)
   */
  @Test
  public void testCreateDirectory() throws Exception {
    String currentWorkingDir = Paths.get("").toAbsolutePath().normalize().toString();
    Assert.assertFalse(FileUtils.createDirectory(currentWorkingDir));

    String newDir = String.format("%s/%s", currentWorkingDir, UUID.randomUUID().toString());
    Assert.assertTrue(FileUtils.createDirectory(newDir));

    Assert.assertTrue(FileUtils.deleteFile(newDir));
  }

  /**
   * Method: isDirectoryExists(String directory)
   */
  @Test
  public void testIsDirectoryExists() throws Exception {
    PowerMockito.mockStatic(Files.class);
    PowerMockito.when(Files.isDirectory(Matchers.any(Path.class))).thenReturn(true);

    Assert.assertTrue(FileUtils.isDirectoryExists(""));

    PowerMockito.when(Files.isDirectory(Matchers.any(Path.class))).thenReturn(false);

    Assert.assertFalse(FileUtils.isDirectoryExists(""));
  }

  /**
   * Method: getBaseName(String file)
   */
  @Test
  public void testGetBaseName() throws Exception {
    String filename = "a/b";
    Assert.assertEquals("b", FileUtils.getBaseName(filename));

    filename = "b";
    Assert.assertEquals("b", FileUtils.getBaseName(filename));
  }
}


text:
package org.apache.activemq.artemis.core.io.aio;

import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.nio.ByteBuffer;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;

import io.netty.util.internal.PlatformDependent;
import org.apache.activemq.artemis.ArtemisConstants;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.ActiveMQExceptionType;
import org.apache.activemq.artemis.api.core.ActiveMQInterruptedException;
import org.apache.activemq.artemis.core.io.AbstractSequentialFileFactory;
import org.apache.activemq.artemis.core.io.IOCallback;
import org.apache.activemq.artemis.core.io.IOCriticalErrorListener;
import org.apache.activemq.artemis.core.io.SequentialFile;
import org.apache.activemq.artemis.journal.ActiveMQJournalLogger;
import org.apache.activemq.artemis.nativo.jlibaio.LibaioContext;
import org.apache.activemq.artemis.nativo.jlibaio.LibaioFile;
import org.apache.activemq.artemis.nativo.jlibaio.SubmitInfo;
import org.apache.activemq.artemis.utils.ByteUtil;
import org.apache.activemq.artemis.utils.PowerOf2Util;
import org.apache.activemq.artemis.utils.critical.CriticalAnalyzer;
import org.jboss.logging.Logger;
import org.jctools.queues.MpmcArrayQueue;
import org.jctools.queues.atomic.MpmcAtomicArrayQueue;

public final class AIOSequentialFileFactory extends AbstractSequentialFileFactory {

   private static final Logger logger = Logger.getLogger(AIOSequentialFileFactory.class);

   // This is useful in cases where you want to disable loading the native library. (e.g. testsuite)
   private static final boolean DISABLED = System.getProperty(AIOSequentialFileFactory.class.getName() + ".DISABLED") != null;

   static {
      // This is usually only used on testsuite.
      // In case it's used, I would rather have it on the loggers so we know what's happening
      if (DISABLED) {

         // This is only used in tests, hence I'm not creating a Logger for this
         logger.info(AIOSequentialFileFactory.class.getName() + ".DISABLED = true");
      }
   }

   private final ReuseBuffersController buffersControl = new ReuseBuffersController();

   private volatile boolean reuseBuffers = true;

   private Thread pollerThread;

   volatile LibaioContext<AIOSequentialCallback> libaioContext;

   private final Queue<AIOSequentialCallback> callbackPool;

   private final AtomicBoolean running = new AtomicBoolean(false);

   private static final String AIO_TEST_FILE = ".aio-test";

   public void beforeClose() {
   }

   public void afterClose() {
   }

   public AIOSequentialFileFactory(final File journalDir, int maxIO) {
      this(journalDir, ArtemisConstants.DEFAULT_JOURNAL_BUFFER_SIZE_AIO, ArtemisConstants.DEFAULT_JOURNAL_BUFFER_TIMEOUT_AIO, maxIO, false, null, null);
   }

   public AIOSequentialFileFactory(final File journalDir, final IOCriticalErrorListener listener, int maxIO) {
      this(journalDir, ArtemisConstants.DEFAULT_JOURNAL_BUFFER_SIZE_AIO, ArtemisConstants.DEFAULT_JOURNAL_BUFFER_TIMEOUT_AIO, maxIO, false, listener, null);
   }

   public AIOSequentialFileFactory(final File journalDir,
                                   final int bufferSize,
                                   final int bufferTimeout,
                                   final int maxIO,
                                   final boolean logRates) {
      this(journalDir, bufferSize, bufferTimeout, maxIO, logRates, null, null);
   }

   public AIOSequentialFileFactory(final File journalDir,
                                   final int bufferSize,
                                   final int bufferTimeout,
                                   final int maxIO,
                                   final boolean logRates,
                                   final IOCriticalErrorListener listener,
                                   final CriticalAnalyzer analyzer) {
      super(journalDir, true, bufferSize, bufferTimeout, maxIO, logRates, listener, analyzer);
      if (maxIO == 1) {
         ActiveMQJournalLogger.LOGGER.warn("Using journal-max-io 1 isn't a proper use of ASYNCIO journal: consider rise this value or use NIO.");
      }
      final int adjustedMaxIO = Math.max(2, maxIO);
      callbackPool = PlatformDependent.hasUnsafe() ? new MpmcArrayQueue<>(adjustedMaxIO) : new MpmcAtomicArrayQueue<>(adjustedMaxIO);
      if (logger.isTraceEnabled()) {
         logger.trace("New AIO File Created");
      }
   }

   public AIOSequentialCallback getCallback() {
      AIOSequentialCallback callback = callbackPool.poll();
      if (callback == null) {
         callback = new AIOSequentialCallback();
      }

      return callback;
   }

   public void enableBufferReuse() {
      this.reuseBuffers = true;
   }

   public void disableBufferReuse() {
      this.reuseBuffers = false;
   }

   @Override
   public SequentialFile createSequentialFile(final String fileName) {
      return new AIOSequentialFile(this, bufferSize, bufferTimeout, journalDir, fileName, writeExecutor);
   }

   @Override
   public boolean isSupportsCallbacks() {
      return true;
   }

   public static boolean isSupported() {
      return !DISABLED && LibaioContext.isLoaded();
   }

   public static boolean isSupported(File journalPath) {
      if (!isSupported()) {
         return false;
      }

      File aioTestFile = new File(journalPath, AIO_TEST_FILE);
      try {
         int fd = LibaioContext.open(aioTestFile.getAbsolutePath(), true);
         LibaioContext.close(fd);
         aioTestFile.delete();
      } catch (Exception e) {
         // try to handle the file using plain Java
         // return false if and only if we can create/remove the file using
         // plain Java but not using AIO
         try {
            if (!aioTestFile.exists()) {
               if (!aioTestFile.createNewFile())
                  return true;
            }
            if (!aioTestFile.delete())
               return true;
         } catch (Exception ie) {
            // we can not even create the test file using plain java
            return true;
         }
         return false;
      }
      return true;
   }

   @Override
   public ByteBuffer allocateDirectBuffer(final int size) {

      final int alignedSize = calculateBlockSize(size);

      // The buffer on AIO has to be a multiple of getAlignment()
      ByteBuffer buffer = LibaioContext.newAlignedBuffer(alignedSize, getAlignment());

      buffer.limit(size);

      return buffer;
   }

   @Override
   public void releaseDirectBuffer(final ByteBuffer buffer) {
      LibaioContext.freeBuffer(buffer);
   }

   @Override
   public ByteBuffer newBuffer(int size) {
      return newBuffer(size, true);
   }

   @Override
   public ByteBuffer newBuffer(int size, boolean zeroed) {
      final int alignedSize = calculateBlockSize(size);
      return buffersControl.newBuffer(alignedSize, zeroed);
   }

   @Override
   public void clearBuffer(final ByteBuffer directByteBuffer) {
      directByteBuffer.position(0);
      if (PlatformDependent.hasUnsafe()) {
         // that's the same semantic of libaioContext.memsetBuffer: it hasn't any JNI cost
         ByteUtil.zeros(directByteBuffer, 0, directByteBuffer.limit());
      } else {
         // JNI cost
         libaioContext.memsetBuffer(directByteBuffer);
      }
   }

   @Override
   public int getAlignment() {
      if (alignment < 0) {
         alignment = calculateAlignment(journalDir);
      }
      return alignment;
   }

   private static int calculateAlignment(File journalDir) {
      File checkFile = null;
      int alignment;
      try {
         journalDir.mkdirs();
         checkFile = File.createTempFile("journalCheck", ".tmp", journalDir);
         checkFile.mkdirs();
         checkFile.createNewFile();
         alignment = LibaioContext.getBlockSize(checkFile);
      } catch (Throwable e) {
         logger.warn(e.getMessage(), e);
         alignment = 512;
      } finally {
         if (checkFile != null) {
            checkFile.delete();
         }
      }
      return alignment;
   }

   // For tests only
   @Override
   public ByteBuffer wrapBuffer(final byte[] bytes) {
      ByteBuffer newbuffer = newBuffer(bytes.length);
      newbuffer.put(bytes);
      return newbuffer;
   }

   @Override
   public int calculateBlockSize(final int position) {
      final int alignment = getAlignment();
      if (!PowerOf2Util.isPowOf2(alignment)) {
         return align(position, alignment);
      } else {
         return PowerOf2Util.align(position, alignment);
      }
   }

   /**
    * It can be used to align {@code size} if alignment is not a power of 2: otherwise better to use {@link PowerOf2Util#align(int, int)} instead.
    */
   private static int align(int size, int alignment) {
      return (size / alignment + (size % alignment != 0 ? 1 : 0)) * alignment;
   }

   /* (non-Javadoc)
    * @see org.apache.activemq.artemis.core.io.SequentialFileFactory#releaseBuffer(java.nio.ByteBuffer)
    */
   @Override
   public synchronized void releaseBuffer(final ByteBuffer buffer) {
      LibaioContext.freeBuffer(buffer);
   }

   @Override
   public void start() {
      if (running.compareAndSet(false, true)) {
         super.start();

         this.libaioContext = new LibaioContext(maxIO, true, dataSync);

         this.running.set(true);

         pollerThread = new PollerThread();
         pollerThread.start();
      }

   }

   @Override
   public void stop() {
      if (this.running.compareAndSet(true, false)) {
         buffersControl.stop();

         libaioContext.close();
         libaioContext = null;

         if (pollerThread != null) {
            try {
               pollerThread.join(AbstractSequentialFileFactory.EXECUTOR_TIMEOUT * 1000);

               if (pollerThread.isAlive()) {
                  ActiveMQJournalLogger.LOGGER.timeoutOnPollerShutdown(new Exception("trace"));
               }
            } catch (InterruptedException e) {
               throw new ActiveMQInterruptedException(e);
            }
         }

         super.stop();
      }
   }

   static void threadDump(String message) {
      ActiveMQJournalLogger.LOGGER.warn(message);
      final ThreadInfo[] threads = ManagementFactory.getThreadMXBean().dumpAllThreads(true, true);
      for (ThreadInfo threadInfo : threads) {
         ActiveMQJournalLogger.LOGGER.warn(threadInfo.toString());
      }
   }

   /**
    * The same callback is used for Runnable executor.
    * This way we can save some memory over the pool.
    */
   public class AIOSequentialCallback implements SubmitInfo, Runnable, Comparable<AIOSequentialCallback> {

      IOCallback callback;
      boolean error = false;
      AIOSequentialFile sequentialFile;
      ByteBuffer buffer;
      LibaioFile libaioFile;
      String errorMessage;
      int errorCode = -1;
      long writeSequence;
      boolean releaseBuffer;
      long position;
      int bytes;

      @Override
      public String toString() {
         return "AIOSequentialCallback{" +
            "error=" + error +
            ", errorMessage='" + errorMessage + '\'' +
            ", errorCode=" + errorCode +
            ", writeSequence=" + writeSequence +
            ", releaseBuffer=" + releaseBuffer +
            ", position=" + position +
            '}';
      }

      public AIOSequentialCallback initWrite(long positionToWrite, int bytesToWrite) {
         this.position = positionToWrite;
         this.bytes = bytesToWrite;
         return this;
      }

      @Override
      public void run() {
         try {
            libaioFile.write(position, bytes, buffer, this);
         } catch (IOException e) {
            callback.onError(ActiveMQExceptionType.IO_ERROR.getCode(), e.getMessage());
            onIOError(e, "Failed to write to file", sequentialFile);
         }
      }

      @Override
      public int compareTo(AIOSequentialCallback other) {
         if (this == other || this.writeSequence == other.writeSequence) {
            return 0;
         } else if (other.writeSequence < this.writeSequence) {
            return 1;
         } else {
            return -1;
         }
      }

      public AIOSequentialCallback init(long writeSequence,
                                        IOCallback IOCallback,
                                        LibaioFile libaioFile,
                                        AIOSequentialFile sequentialFile,
                                        ByteBuffer usedBuffer,
                                        boolean releaseBuffer) {
         this.callback = IOCallback;
         this.sequentialFile = sequentialFile;
         this.error = false;
         this.buffer = usedBuffer;
         this.libaioFile = libaioFile;
         this.writeSequence = writeSequence;
         this.errorMessage = null;
         this.releaseBuffer = releaseBuffer;
         return this;
      }

      @Override
      public void onError(int errno, String message) {
         if (logger.isDebugEnabled()) {
            logger.trace("AIO on error issued. Error(code: " + errno + " msg: " + message + ")");
         }
         this.error = true;
         this.errorCode = errno;
         this.errorMessage = message;
      }

      /**
       * this is called by libaio.
       */
      @Override
      public void done() {
         this.sequentialFile.done(this);
      }

      /**
       * This is callbed by the AIOSequentialFile, after determined the callbacks were returned in sequence
       */
      public void sequentialDone() {

         if (error) {
            if (callback != null) {
               callback.onError(errorCode, errorMessage);
            }
            onIOError(new ActiveMQException(errorCode, errorMessage), errorMessage, null);
            errorMessage = null;
         } else {
            if (callback != null) {
               callback.done();
            }

            if (buffer != null && reuseBuffers && releaseBuffer) {
               buffersControl.bufferDone(buffer);
            }

            callbackPool.offer(AIOSequentialCallback.this);
         }
      }
   }

   private class PollerThread extends Thread {

      private PollerThread() {
         super("Apache ActiveMQ Artemis libaio poller");
      }

      @Override
      public void run() {
         while (running.get()) {
            try {
               libaioContext.poll();
            } catch (Throwable e) {
               ActiveMQJournalLogger.LOGGER.warn(e.getMessage(), e);
               onIOError(new ActiveMQException("Error on libaio poll"), e.getMessage(), null);
            }
         }
      }
   }

   /**
    * Class that will control buffer-reuse
    */
   private class ReuseBuffersController {

      private volatile long bufferReuseLastTime = System.currentTimeMillis();

      private final ConcurrentLinkedQueue<ByteBuffer> reuseBuffersQueue = new ConcurrentLinkedQueue<>();

      private boolean stopped = false;

      private int alignedBufferSize = 0;

      private int getAlignedBufferSize() {
         if (alignedBufferSize == 0) {
            alignedBufferSize = calculateBlockSize(bufferSize);
         }

         return alignedBufferSize;
      }

      public ByteBuffer newBuffer(final int size, final boolean zeroed) {
         // if a new buffer wasn't requested in 10 seconds, we clear the queue
         // This is being done this way as we don't need another Timeout Thread
         // just to cleanup this
         if (bufferSize > 0 && System.currentTimeMillis() - bufferReuseLastTime > 10000) {
            if (logger.isTraceEnabled()) {
               logger.trace("Clearing reuse buffers queue with " + reuseBuffersQueue.size() +
                               " elements");
            }

            bufferReuseLastTime = System.currentTimeMillis();

            clearPoll();
         }

         // if a buffer is bigger than the configured-bufferSize, we just create a new
         // buffer.
         if (size > getAlignedBufferSize()) {
            return LibaioContext.newAlignedBuffer(size, getAlignment());
         } else {
            // We need to allocate buffers following the rules of the storage
            // being used (AIO/NIO)
            final int alignedSize;

            if (size < getAlignedBufferSize()) {
               alignedSize = getAlignedBufferSize();
            } else {
               alignedSize = calculateBlockSize(size);
            }

            // Try getting a buffer from the queue...
            ByteBuffer buffer = reuseBuffersQueue.poll();

            if (buffer == null) {
               // if empty create a new one.
               buffer = LibaioContext.newAlignedBuffer(alignedSize, getAlignment());

               buffer.limit(calculateBlockSize(size));
            } else {
               if (zeroed) {
                  clearBuffer(buffer);
               } else {
                  buffer.position(0);
               }

               // set the limit of the buffer to the bufferSize being required
               buffer.limit(calculateBlockSize(size));
            }

            buffer.rewind();

            return buffer;
         }
      }

      public synchronized void stop() {
         stopped = true;
         clearPoll();
      }

      public synchronized void clearPoll() {
         ByteBuffer reusedBuffer;

         while ((reusedBuffer = reuseBuffersQueue.poll()) != null) {
            releaseBuffer(reusedBuffer);
         }
      }

      public void bufferDone(final ByteBuffer buffer) {
         synchronized (this) {

            if (stopped) {
               releaseBuffer(buffer);
            } else {
               bufferReuseLastTime = System.currentTimeMillis();

               // If a buffer has any other than the configured bufferSize, the buffer
               // will be just sent to GC
               if (buffer.capacity() == getAlignedBufferSize()) {
                  reuseBuffersQueue.offer(buffer);
               } else {
                  releaseBuffer(buffer);
               }
            }
         }
      }
   }

   @Override
   public String toString() {
      return AIOSequentialFileFactory.class.getSimpleName() + "(buffersControl.stopped=" + buffersControl.stopped +
         "):" + super.toString();
   }
}