A Look at JamesCMS: WebSockets and FileWatchers

Posted Tuesday, March 12, 2013 in Old JamesCMS Posts

JamesCMS uses Fleck, a WebSocket server implementation. There are two uses of WebSockets in JamesCMS, a log watcher and a file previewer. Here's a preview of what the log watcher looks like:

Log Watcher

When called the log watcher will call the FileTail class with a specific log to start tracking. FileTail initializes a FileSystemWatcher that tracks file changes. The file is then read and each file change event triggered will cause the file to be read again starting from the last position. This is similar to other log watchers where the tail of the log is tracked so that incomming changes appear immediately. The WebSocket server is managed through the WebSocketFileTail class which uses the FileTail class events to send messages to the client.

On the client side a small bit of javascript and jQuery is used to communicate with the WebSocket server:

{{javascript}}
var socket;
$("#Files").change(function () {
    var file = $("#Files").val();
    if (file.length > 0 && file != "") {
        $("#logData").load('@Url.Action("GetLog")?logname=' + file, function () { establishConnection(); });
    };
});
function establishConnection() {
    if (socket != null) {
        socket.close();
    }
    socket = new WebSocket("ws://santiagodevelopment.com:8989/" +
        "@Html.Raw(Session.SessionID)");
    socket.onopen = function (connection) {
        $("#status").html("connected");
    };
    socket.onerror = function (error) {
        $("#status").html(error.data);
    };
    socket.onclose = function () {
        $("#data").append("closed");
    };
    socket.onmessage = function (message) {
        $("#data").append("\n" + message.data);
        $("#filedata").prop({ scrollTop: $("#filedata").prop("scrollHeight") });
        prettyPrint();
    };
};

Prettify is used to perform highlighting. I wrote a simple prettify highligher to perform entire line highlighting according to the presence of a few key words.

{{javascript}}
PR.registerLangHandler(
    PR.createSimpleLexer(
        [ // shortcutStylePatterns
        ],
        [ // fallthroughStylePatterns
            //Error lines
            [PR.PR_KEYWORD, /.*(?:ERROR| AT |WARN|FATAL|ISSUE|FAIL).*/i, null],
            //Normal lines
            [PR.PR_STRING, /.*(?:TRACE|DEBUG|INFO).*/i, null]            
        ]),
    ['logfile', 'log']);

The same file watcher to WebSocket to browser method is used to perform file previews of markdown files. JamesCMS has a SQL to file source control system that allows me to push and pull text files from a directory into the SQL database. So when I'm editing a file it's nice to have a preview of it on the website:

File Preview