You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by or...@apache.org on 2018/11/08 13:43:01 UTC

[4/4] qpid-broker-j git commit: QPID-8191: [Broker-J] Change log viewer UI to use dgrid and query UI for building filters

QPID-8191: [Broker-J] Change log viewer UI to use dgrid and query UI for building filters


Project: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/commit/dfaeddae
Tree: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/tree/dfaeddae
Diff: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/diff/dfaeddae

Branch: refs/heads/master
Commit: dfaeddae5f66982d912b7eb65fb29eafc441249f
Parents: 4b743ae
Author: Alex Rudyy <or...@apache.org>
Authored: Thu Nov 8 10:52:32 2018 +0000
Committer: Alex Rudyy <or...@apache.org>
Committed: Thu Nov 8 13:42:18 2018 +0000

----------------------------------------------------------------------
 .../qpid/management/logger/LogViewerWidget.js   | 637 +++++++++++++++++++
 .../logger/brokerlogger/memory/show.js          |  40 +-
 .../logger/memory/LogViewerWidget.html          |  89 +++
 .../src/main/java/resources/css/common.css      |  11 +
 .../js/qpid/common/TypeTabExtension.js          |  41 +-
 .../main/java/resources/js/qpid/common/util.js  |  43 ++
 .../js/qpid/management/query/CriteriaPane.js    |  12 +
 .../js/qpid/management/query/DropDownSelect.js  |   3 +-
 .../js/qpid/management/query/QueryWidget.js     |   2 +-
 .../js/qpid/management/query/WhereCriteria.js   |  22 +
 .../js/qpid/management/query/WhereExpression.js |  25 +-
 11 files changed, 872 insertions(+), 53 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/dfaeddae/broker-plugins/logging-logback/src/main/java/resources/js/qpid/management/logger/LogViewerWidget.js
----------------------------------------------------------------------
diff --git a/broker-plugins/logging-logback/src/main/java/resources/js/qpid/management/logger/LogViewerWidget.js b/broker-plugins/logging-logback/src/main/java/resources/js/qpid/management/logger/LogViewerWidget.js
new file mode 100644
index 0000000..78e8689
--- /dev/null
+++ b/broker-plugins/logging-logback/src/main/java/resources/js/qpid/management/logger/LogViewerWidget.js
@@ -0,0 +1,637 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+define(["dojo/_base/declare",
+        "dojo/_base/lang",
+        "dojo/_base/array",
+        "dojo/Evented",
+        "dojo/date/locale",
+        "dojo/text!logger/memory/LogViewerWidget.html",
+        "qpid/common/util",
+        "dgrid/Grid",
+        "dgrid/Selector",
+        "dgrid/Keyboard",
+        "dgrid/Selection",
+        "dgrid/extensions/Pagination",
+        "dgrid/extensions/ColumnResizer",
+        "dgrid/extensions/ColumnHider",
+        "dgrid/extensions/DijitRegistry",
+        "dstore/Memory",
+        "dijit/registry",
+        "dijit/_WidgetBase",
+        "dijit/_TemplatedMixin",
+        "dijit/_WidgetsInTemplateMixin",
+        "dijit/form/Button",
+        "dijit/Toolbar",
+        "dijit/ToolbarSeparator",
+        "dijit/form/ToggleButton",
+        "dijit/form/NumberTextBox",
+        "dijit/ConfirmDialog",
+        "qpid/management/query/DropDownSelect",
+        "qpid/management/query/WhereExpression"
+    ],
+    function (declare,
+              lang,
+              array,
+              Evented,
+              locale,
+              template,
+              util,
+              Grid,
+              Selector,
+              Keyboard,
+              Selection,
+              Pagination,
+              ColumnResizer,
+              ColumnHider,
+              DijitRegistry,
+              MemoryStore) {
+
+        function escapeRegExp(text)
+        {
+            return text.replace(/[-[\]{}()*+?.,\\/^$|#\s]/g, '\\$&');
+        }
+
+        return declare("qpid.management.logger.LogViewerWidget",
+            [dijit._WidgetBase, dijit._TemplatedMixin, dijit._WidgetsInTemplateMixin, Evented],
+            {
+                //Strip out the apache comment header from the template html as comments unsupported.
+                templateString: template.replace(/<!--[\s\S]*?-->/g, ""),
+
+                // template fields
+                lastUpdateTime: null,
+                updateTimeNode: null,
+                browserTimeNode: null,
+                logsToolbar: null,
+                refreshButton: null,
+                autoRefreshButton: null,
+                clearFilterButton: null,
+                logEntries: null,
+                columnChooser: null,
+                filterChooser: null,
+                filterBuilder: null,
+                rowLimitDialog: null,
+                limit: null,
+                limitButton: null,
+
+                // constructor mixed in fields
+                controller: null,
+                management: null,
+                userPreferences: null,
+                modelObj: null,
+                maxRecords: null,
+
+                // inner fields
+                _autoRefresh: false,
+                _columns: null,
+                _filter: null,
+
+                _lastSeenLogId: 0,
+                _logsLimit: 0,
+
+                postCreate: function () {
+                    this.inherited(arguments);
+
+                    this._logsLimit = this.maxRecords || 4096;
+                    this.autoRefreshButton.on("change", lang.hitch(this, function (value) {
+                        this._autoRefresh = value;
+                        this.refreshButton.set("disabled", value);
+                        if (value)
+                        {
+                            this._refreshGridEntries();
+                        }
+                    }));
+
+                    this.refreshButton.on("click", lang.hitch(this, function () {
+                        this._refreshGridEntries();
+                    }));
+                    this.clearFilterButton.on("click", lang.hitch(this, this._clearFilter));
+
+                    this._logsStore = new MemoryStore({
+                        data: [],
+                        idProperty: 'id'
+                    });
+
+                    var userPreferences = this.userPreferences;
+                    this._columns = [
+                        {
+                            label: 'ID',
+                            field: "id",
+                            hidden: false,
+                            id: 0,
+                            attributeName: "id",
+                            type: "Long"
+                        }, {
+                            label: "Date",
+                            field: "timestamp",
+                            formatter: function (value) {
+                                return userPreferences.formatDateTime(value, {appendTimeZone: true});
+                            },
+                            hidden: false,
+                            id: 1,
+                            attributeName: "timestamp",
+                            type: "Date"
+                        }, {
+                            label: "Level",
+                            field: "level",
+                            hidden: true,
+                            id: 2,
+                            attributeName: "level",
+                            validValues: ["TRACE", "DEBUG", "INFO", "WARN", "ERROR"]
+                        }, {
+                            label: "Logger",
+                            field: "logger",
+                            hidden: true,
+                            id: 3,
+                            attributeName: "logger"
+                        }, {
+                            label: "Thread",
+                            field: "threadName",
+                            hidden: true,
+                            id: 4,
+                            attributeName: "threadName"
+                        }, {
+                            label: "Log Message",
+                            field: "message",
+                            hidden: false,
+                            id: 5,
+                            attributeName: "message"
+                        }
+                    ];
+
+                    this._createGrid();
+
+                    this.columnChooser.on("change", lang.hitch(this, this._columnChanged));
+                    this.filterBuilder.set("whereFieldsSelector", this.filterChooser);
+                    this.filterBuilder.set("userPreferences", this.management.userPreferences);
+                    this.filterBuilder.on("change", lang.hitch(this, this._filterChanged));
+
+                    this.columnChooser.set("data", {
+                        items: this._columns,
+                        idProperty: "id",
+                        selected: array.filter(this._columns, function (item) {
+                            return !item.hidden;
+                        }),
+                        nameProperty: "label"
+                    });
+                    this.filterChooser.set("data", {
+                        items: this._columns,
+                        selected: [],
+                        idProperty: "id",
+                        nameProperty: "label"
+                    });
+
+                    this.limitButton.on("click", lang.hitch(this, this._showLimitDialog));
+                    this.rowLimitDialog.on("execute", lang.hitch(this, function () {
+                        var value = this.limit.get("value");
+                        if (typeof value === 'number' || (typeof value === 'string' && util.isInteger(value) ) )
+                        {
+                            this._logsLimit = value;
+                            this._deleteExcessiveRows();
+                        }
+                    }));
+
+
+                    this._refreshGridEntries();
+                },
+                startup: function () {
+                    this.inherited(arguments);
+                    if (!this._started)
+                    {
+                        if (this._logsGrid)
+                        {
+                            this._logsGrid.startup();
+                        }
+                        this._started = true;
+                    }
+                },
+                destroyRecursive: function (preserveDom) {
+                    this.inherited(arguments);
+                    if (this._logsGrid)
+                    {
+                        this._logsGrid.destroyRecursive(preserveDom);
+                        this._logsGrid = null;
+                    }
+                    if (this._logsStore)
+                    {
+                        this._logsStore = null;
+                    }
+                    if (this.refreshButton)
+                    {
+                        this.refreshButton.destroyRecursive(preserveDom);
+                        this.refreshButton = null;
+                    }
+                    if (this.autoRefreshButton)
+                    {
+                        this.autoRefreshButton.destroyRecursive(preserveDom);
+                        this.autoRefreshButton = null;
+                    }
+                    if (this.clearFilterButton)
+                    {
+                        this.clearFilterButton.destroyRecursive(preserveDom);
+                        this.clearFilterButton = null;
+                    }
+                    if (this.columnChooser)
+                    {
+                        this.columnChooser.destroyRecursive(preserveDom);
+                        this.columnChooser = null;
+                    }
+                    if (this.filterChooser)
+                    {
+                        this.filterChooser.destroyRecursive(preserveDom);
+                        this.filterChooser = null;
+                    }
+                    if (this.filterBuilder)
+                    {
+                        this.filterBuilder.destroyRecursive(preserveDom);
+                        this.filterBuilder = null;
+                    }
+                    if (this.rowLimitDialog)
+                    {
+                        this.rowLimitDialog.destroyRecursive(preserveDom);
+                        this.rowLimitDialog = null;
+                    }
+                },
+
+                updateLogs: function () {
+                    if (this._autoRefresh)
+                    {
+                        this._refreshGridEntries();
+                    }
+                },
+
+                _refreshGridEntries: function (useFetched) {
+                    if (!useFetched)
+                    {
+                        var modelObj = {
+                            "name": "getLogEntries",
+                            type: this.modelObj.type,
+                            parent: this.modelObj
+                        };
+
+                        this.management
+                            .load(modelObj, {lastLogId: this._lastSeenLogId})
+                            .then(lang.hitch(this, this._updateLogEntries));
+                    }
+                    else
+                    {
+                        this._refreshGridStore();
+                    }
+                },
+
+                _refreshGridStore: function () {
+                    var store = this._logsStore;
+                    if (store != null)
+                    {
+                        if (this._filter)
+                        {
+                            store = store.filter(this._filter);
+                        }
+                        if (this._logsGrid)
+                        {
+                            this._logsGrid.set("collection", store)
+                        }
+                    }
+
+                },
+
+                _updateLogEntries: function (logs) {
+                    var store = this._logsStore;
+                    if (store != null && logs)
+                    {
+                        for (var i = 0; i < logs.length; i++)
+                        {
+                            store.put(logs[i]);
+                            this._lastSeenLogId = logs[i].id;
+                        }
+
+                        this._deleteExcessiveRows();
+
+                        this._refreshGridStore();
+                    }
+                    this._refreshUpdateTime();
+                },
+
+                _deleteExcessiveRows: function () {
+                    var idToDelete = this._lastSeenLogId - this._logsLimit;
+                    var store = this._logsStore;
+                    if (idToDelete > 0 && store != null)
+                    {
+                        var items = [];
+                        store.filter(new store.Filter().lt("id", idToDelete))
+                            .forEach(function (item) {
+                                items.push(item.id);
+                            });
+                        for (var i = items.length - 1; i >= 0; i--)
+                        {
+                            store.remove(items[i]);
+                        }
+                    }
+                },
+
+                _columnChanged: function (selectedColumns) {
+                    for (var i = 0; i < this._columns.length; i++)
+                    {
+                        var selected = false;
+                        for (var it = 0; it < selectedColumns.length; it++)
+                        {
+                            var item = selectedColumns[it];
+                            if (item.id === this._columns[i].id)
+                            {
+                                selected = true;
+                                break;
+                            }
+                        }
+                        this._columns[i].hidden = !selected;
+                        this._logsGrid.toggleColumnHiddenState(i, !selected);
+                    }
+                },
+
+                _columnStateChange: function (event) {
+                    for (var i = 0; i < this._columns.length; i++)
+                    {
+                        if (event.column.label === this._columns[i].label)
+                        {
+                            this._columns[i].hidden = event.hidden;
+                            break;
+                        }
+                    }
+
+                    var selectedItems = [];
+                    for (var j = 0; j < this._columns.length; j++)
+                    {
+                        if (!this._columns[j].hidden)
+                        {
+                            selectedItems.push(this._columns[j]);
+                        }
+                    }
+
+                    this.columnChooser.set("data", {selected: selectedItems});
+                },
+
+                _filterChanged: function (event) {
+                    var conditions = event.conditions;
+                    var conditionsSet = conditions && conditions.hasOwnProperty("conditions")
+                                        && conditions.conditions.length > 0;
+                    this.clearFilterButton.set("disabled", !conditionsSet);
+                    this.filterBuilder.domNode.style.display = conditionsSet ? "" : "none";
+                    this._filter = this._buildFilter(conditions);
+                    this._refreshGridEntries(true);
+                },
+
+                _showLimitDialog: function () {
+                    this.limit.set("value", this._logsLimit);
+                    this.rowLimitDialog.show();
+                },
+
+                _createGrid: function () {
+                    var LogGrid = declare([Grid,
+                                           Keyboard,
+                                           Selection,
+                                           Pagination,
+                                           ColumnResizer,
+                                           ColumnHider,
+                                           DijitRegistry]);
+
+                    this._logsGrid = new LogGrid({
+                        rowsPerPage: 10,
+                        selectionMode: 'none',
+                        deselectOnRefresh: false,
+                        allowSelectAll: true,
+                        cellNavigation: true,
+                        className: 'dgrid-autoheight',
+                        pageSizeOptions: [10, 20, 30, 40, 50, 100],
+                        adjustLastColumn: true,
+                        collection: this._logsStore,
+                        //highlightRow: function () {},
+                        columns: lang.clone(this._columns),
+                        sort: "id"
+                    }, this.logEntries);
+                    this._logsGrid.on("dgrid-columnstatechange", lang.hitch(this, this._columnStateChange));
+                },
+
+                _clearFilter: function () {
+                    this.filterBuilder.clearWhereCriteria();
+                    this.clearFilterButton.set("disabled", true);
+                    this.filterBuilder.domNode.style.display = "none";
+                    this._filter = null;
+                    this._refreshGridEntries(true);
+                },
+
+                _refreshUpdateTime: function () {
+                    if (this.userPreferences)
+                    {
+                        var formatOptions = {
+                            selector: "time",
+                            timePattern: "HH:mm:ss.SSS",
+                            appendTimeZone: true,
+                            addOffset: true
+                        };
+                        var updateTime = new Date();
+                        this.updateTimeNode.innerHTML =
+                            this.userPreferences.formatDateTime(updateTime.getTime(), formatOptions);
+                        this.browserTimeNode.innerHTML = locale.format(updateTime, formatOptions);
+                    }
+                },
+
+                _buildFilter: function (conditions) {
+
+                    var filters = [];
+                    if (conditions && conditions.hasOwnProperty("conditions"))
+                    {
+                        var items = conditions.conditions;
+                        for (var i = 0; i < items.length; i++)
+                        {
+                            var item = items[i];
+                            var f = null;
+                            if (item.hasOwnProperty("conditions"))
+                            {
+                                f = this._buildFilter(item);
+                            }
+                            else
+                            {
+                                f = this._buildFilterForOperator(item.operator, item.type, item.name, item.value);
+                            }
+                            if (f)
+                            {
+                                filters.push(f);
+                            }
+                        }
+                    }
+
+                    var filter;
+                    for (var j = 0; j < filters.length; j++)
+                    {
+                        if (filter)
+                        {
+                            if (conditions.operator === "or")
+                            {
+
+                                filter = filter.or(filter, filters[j])
+                            }
+                            else if (conditions.operator === "and")
+                            {
+                                filter = filter.and(filter, filters[j])
+                            }
+                        }
+                        else
+                        {
+                            filter = filters[j];
+                        }
+                    }
+                    return filter;
+                },
+
+                _buildFilterForOperator: function (operator, type, name, value) {
+                    var f;
+                    var val = this._getConditionValue(type, value);
+                    switch (operator)
+                    {
+                        case '=':
+                        {
+                            f = new this._logsStore.Filter().eq(name, val);
+                            break;
+                        }
+                        case '<>':
+                        {
+                            f = new this._logsStore.Filter().ne(name, val);
+                            break;
+                        }
+                        case '>':
+                        {
+                            f = new this._logsStore.Filter().gt(name, val);
+                            break;
+                        }
+                        case '<':
+                        {
+                            f = new this._logsStore.Filter().lt(name, val);
+                            break;
+                        }
+                        case '>=':
+                        {
+                            f = new this._logsStore.Filter().gte(name, val);
+                            break;
+                        }
+                        case '<=':
+                        {
+                            f = new this._logsStore.Filter().lte(name, val);
+                            break;
+                        }
+                        case "contains":
+                        {
+                            if (typeof value === 'string' || value instanceof String)
+                            {
+                                f = new this._logsStore.Filter().match(name,
+                                    new RegExp("^.*" + escapeRegExp(val) + ".*$", "i"));
+                            }
+                            break;
+                        }
+                        case "starts with":
+                        {
+                            if (typeof value === 'string' || value instanceof String)
+                            {
+                                f = new this._logsStore.Filter().match(name,
+                                    new RegExp("^" + escapeRegExp(val) + ".*$", "i"));
+                            }
+                            break;
+                        }
+                        case "ends with":
+                        {
+                            if (typeof value === 'string' || value instanceof String)
+                            {
+                                f = new this._logsStore.Filter().match(name,
+                                    new RegExp("^.*" + escapeRegExp(val) + "$", "i"));
+                            }
+                            break;
+                        }
+                        case "not contains":
+                        {
+                            if (typeof value === 'string' || value instanceof String)
+                            {
+                                f = new this._logsStore.Filter().match(name,
+                                    new RegExp("^((?!" + escapeRegExp(val) + ").)*$", "i"));
+                            }
+                            break;
+                        }
+                        case "not starts with":
+                        {
+                            if (typeof value === 'string' || value instanceof String)
+                            {
+                                f = new this._logsStore.Filter().match(name,
+                                    new RegExp("^(?!" + escapeRegExp(val) + ".*$).*$", "i"));
+                            }
+                            break;
+                        }
+                        case "not ends with":
+                        {
+                            if (typeof value === 'string' || value instanceof String)
+                            {
+                                f = new this._logsStore.Filter().match(name,
+                                    new RegExp("^(.(?!" + escapeRegExp(val) + "$))+$", "i"));
+                            }
+                            break;
+                        }
+                        case "is null":
+                        {
+                            f = new this._logsStore.Filter().eq(name, null);
+                            f = f.or(f, f.eq(name, undefined));
+                            break;
+                        }
+                        case "is not null":
+                        {
+                            f = new this._logsStore.Filter().ne(name, null);
+                            f = f.and(f, f.ne(name, undefined));
+                            break;
+                        }
+                        case "in":
+                        {
+                            if (Array.isArray(val))
+                            {
+                                f = new this._logsStore.Filter()["in"](name, val);
+                            }
+                            break;
+                        }
+                        case "not in":
+                        {
+                            if (Array.isArray(val))
+                            {
+                                var fltr = function (data) {
+                                    return val.indexOf(data[name]) === -1
+                                };
+                                f = new this._logsStore.Filter(fltr);
+                            }
+                            break;
+                        }
+                    }
+                    return f;
+                },
+                _getConditionValue: function (type, value) {
+                    if (type === "Date" && (typeof value === 'string' || value instanceof String))
+                    {
+                        var groups = value.match(/^to_date\('(.*)'\)$/i);
+                        if (groups && groups.length === 2)
+                        {
+                            value = Date.parse(groups[1]);
+                        }
+                    }
+                    return value;
+                }
+            });
+    });

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/dfaeddae/broker-plugins/logging-logback/src/main/java/resources/js/qpid/management/logger/brokerlogger/memory/show.js
----------------------------------------------------------------------
diff --git a/broker-plugins/logging-logback/src/main/java/resources/js/qpid/management/logger/brokerlogger/memory/show.js b/broker-plugins/logging-logback/src/main/java/resources/js/qpid/management/logger/brokerlogger/memory/show.js
index 82d4248..3d826e0 100644
--- a/broker-plugins/logging-logback/src/main/java/resources/js/qpid/management/logger/brokerlogger/memory/show.js
+++ b/broker-plugins/logging-logback/src/main/java/resources/js/qpid/management/logger/brokerlogger/memory/show.js
@@ -22,23 +22,37 @@ define(["qpid/common/util",
         "dojo/query",
         "dojox/html/entities",
         "dojo/text!logger/memory/show.html",
-        "qpid/common/TypeTabExtension",
-        "qpid/management/logger/LogViewer",
-        "dojo/domReady!"], function (util, query, entities, template, TypeTabExtension, LogViewer)
-{
+        "qpid/management/logger/LogViewerWidget",
+        "dojo/domReady!"], function (util, query, entities, template, LogViewerWidget) {
     function BrokerMemoryLogger(params)
     {
-        this.logViewer = new LogViewer(params.modelObj, params.management, params.typeSpecificDetailsNode, params.contentPane);
-        TypeTabExtension.call(this,
-            params.containerNode,
-            template,
-            "BrokerLogger",
-            "Memory",
-            params.metadata,
-            params.data);
+        var that = this;
+        if (template)
+        {
+            util.parse(params.containerNode, template, function () {
+                if (params.metadata)
+                {
+                    that.attributeContainers =
+                        util.collectAttributeNodes(params.containerNode, params.metadata, "BrokerLogger", "Memory");
+                    var options = {
+                        controller: params.controller,
+                        management: params.management,
+                        userPreferences: params.management.userPreferences,
+                        modelObj: params.modelObj,
+                        maxRecords: params.data.maxRecords
+                    };
+                    that.logViewerWidget = new LogViewerWidget(options, params.typeSpecificDetailsNode);
+                    that.update(params.data);
+                }
+            });
+        }
     }
 
-    util.extend(BrokerMemoryLogger, TypeTabExtension);
+    BrokerMemoryLogger.prototype.update = function (restData) {
+        util.updateAttributeNodes(this.attributeContainers, restData);
+        this.logViewerWidget.maxRecords = restData.maxRecords;
+        this.logViewerWidget.updateLogs();
+    };
 
     return BrokerMemoryLogger;
 });

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/dfaeddae/broker-plugins/logging-logback/src/main/java/resources/logger/memory/LogViewerWidget.html
----------------------------------------------------------------------
diff --git a/broker-plugins/logging-logback/src/main/java/resources/logger/memory/LogViewerWidget.html b/broker-plugins/logging-logback/src/main/java/resources/logger/memory/LogViewerWidget.html
new file mode 100644
index 0000000..4e81fc2
--- /dev/null
+++ b/broker-plugins/logging-logback/src/main/java/resources/logger/memory/LogViewerWidget.html
@@ -0,0 +1,89 @@
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements.  See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership.  The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License.  You may obtain a copy of the License at
+ -
+ -   http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied.  See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<div class="logViewer">
+    <div data-dojo-type="dijit/TitlePane" data-dojo-props="title: 'Log Viewer'">
+        <div data-dojo-attach-point="logsToolbar">
+            <div data-dojo-attach-point="lastUpdateTime">
+                <span class="info-cell left-cell label-cell">Update time:</span>
+                <span class="info-cell" data-dojo-attach-point="updateTimeNode"></span>
+                <span class="info-cell">Browser time:</span>
+                <span class="info-cell" data-dojo-attach-point="browserTimeNode"></span>
+            </div>
+            <div data-dojo-type="dijit/Toolbar">
+                <div id="logViewer_refreshButton_${id}"
+                     data-dojo-type="dijit/form/Button"
+                     data-dojo-attach-point="refreshButton"
+                     data-dojo-props="iconClass: 'gridRefreshIcon',title: 'Manual Refresh'">Refresh
+                </div>
+                <div id="logViewer_autoRefreshButton_${id}"
+                     data-dojo-type="dijit/form/ToggleButton"
+                     data-dojo-attach-point="autoRefreshButton"
+                     data-dojo-props="iconClass: 'gridAutoRefreshIcon',title: 'Auto Refresh'">Auto Refresh
+                </div>
+
+                <div id="logViewer_limitButton_${id}"
+                     data-dojo-type="dijit/form/Button"
+                     data-dojo-attach-point="limitButton"
+                     data-dojo-props="iconClass: 'rowNumberLimitIcon', title: 'Set Row Limit'">Set Row Limit
+                </div>
+
+                <span data-dojo-type="qpid/management/query/DropDownSelect"
+                      data-dojo-attach-point="columnChooser"
+                      data-dojo-props="iconClass: 'columnDefDialogButtonIcon',
+                                       title: 'Select fields to display',
+                                       label:'Display Columns'">
+                </span>
+                <span data-dojo-type="qpid/management/query/DropDownSelect"
+                      data-dojo-attach-point="filterChooser"
+                      data-dojo-props="iconClass: 'dojoxGridFBarDefFilterBtnIcon',
+                                       title: 'Specify Filtering Conditions',
+                                       label:'Set Filter'">
+                </span>
+                <div id="logViewer_clearFilterButton_${id}"
+                     data-dojo-type="dijit/form/Button"
+                     data-dojo-attach-point="clearFilterButton"
+                     data-dojo-props="iconClass: 'dijitIconDelete',
+                                      title: 'Clear filter',
+                                      disabled: true">Clear Filter
+                </div>
+                <div data-dojo-attach-point="filterBuilder"
+                     data-dojo-type="qpid/management/query/WhereExpression" style="display:none"
+                     class="dijitToolbar"></div>
+            </div>
+        </div>
+        <div data-dojo-attach-point="logEntries"></div>
+
+        <div data-dojo-type="dijit/ConfirmDialog" data-dojo-attach-point="rowLimitDialog"
+             title="Set maximum number of logs to display">
+            <div>
+                <label class="formLabel-labelCell tableContainer-labelCell"
+                       for="logViewer_limit_${id}">Maximum number of logs to display:</label>
+                <input class="formLabel-controlCell tableContainer-valueCell"
+                       data-dojo-type="dijit/form/NumberTextBox"
+                       data-dojo-props="required: true"
+                       data-dojo-attach-point="limit"
+                       name="limit"
+                       id="logViewer_limit_${id}">
+                <div class="clear"></div>
+            </div>
+        </div>
+    </div>
+</div>

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/dfaeddae/broker-plugins/management-http/src/main/java/resources/css/common.css
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/css/common.css b/broker-plugins/management-http/src/main/java/resources/css/common.css
index 09765a5..a12ac7d 100644
--- a/broker-plugins/management-http/src/main/java/resources/css/common.css
+++ b/broker-plugins/management-http/src/main/java/resources/css/common.css
@@ -826,3 +826,14 @@ td.advancedSearchField, col.autoWidth {
 .accessControlRules .field-operation { width: 10%; }
 .accessControlRules .field-outcome { width: 10%; }
 .accessControlRules .field-attributes { width: auto; }
+
+.info-cell {padding-right: 5px;}
+.left-cell {padding-left: 5px;}
+.label-cell {font-weight: bold;}
+
+.logViewer .field-id { width: 4em; }
+.logViewer .field-timestamp { width: 20%;}
+.logViewer .field-level {width: 5em;}
+.logViewer .field-logger { width: 20%;}
+.logViewer .field-threadName { width: 10%;}
+.logViewer .field-message { width: auto;}

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/dfaeddae/broker-plugins/management-http/src/main/java/resources/js/qpid/common/TypeTabExtension.js
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/common/TypeTabExtension.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/common/TypeTabExtension.js
index a2b877e..370e6b6 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/common/TypeTabExtension.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/common/TypeTabExtension.js
@@ -18,57 +18,26 @@
  * under the License.
  *
  */
-define(["qpid/common/util", "dojo/query", "dojox/html/entities", "dojo/domReady!"], function (util, query, entities)
+define(["qpid/common/util", "dojo/domReady!"], function (util)
 {
 
     function TypeTabExtension(containerNode, template, category, type, metadata, data)
     {
         var that = this;
-        this.attributeContainers = {};
         if (template)
         {
             util.parse(containerNode, template, function ()
             {
-                if (metadata && category && type)
-                {
-                    var attributes = metadata.getMetaData(category, type).attributes;
-                    for (var attrName in attributes)
-                    {
-                        var queryResult = query("." + attrName, containerNode);
-                        if (queryResult && queryResult[0])
-                        {
-                            var attr = attributes[attrName];
-                            that.attributeContainers[attrName] = {
-                                containerNode: queryResult[0],
-                                attributeType: attr.type
-                            };
-                        }
-                    }
-                    that.update(data);
-                }
+                that.attributeContainers = util.collectAttributeNodes(containerNode, metadata, category, type);
+                that.update(data);
             });
         }
     }
 
     TypeTabExtension.prototype.update = function (restData)
     {
-        for (var attrName in this.attributeContainers)
-        {
-            if (attrName in restData)
-            {
-                var content = "";
-                if (this.attributeContainers[attrName].attributeType == "Boolean")
-                {
-                    content = util.buildCheckboxMarkup(restData[attrName]);
-                }
-                else
-                {
-                    content = entities.encode(String(restData[attrName]));
-                }
-                this.attributeContainers[attrName].containerNode.innerHTML = content;
-            }
-        }
-    }
+        util.updateAttributeNodes(this.attributeContainers, restData);
+    };
 
     return TypeTabExtension;
 });

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/dfaeddae/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js
index a214e35..10c1ac2 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js
@@ -1058,5 +1058,48 @@ define(["dojo/_base/xhr",
             }
         };
 
+        util.collectAttributeNodes = function (containerNode, metadata, category, type) {
+            var containerObject = {};
+            if (metadata && category && type)
+            {
+                var attributes = metadata.getMetaData(category, type).attributes;
+                for (var attrName in attributes)
+                {
+                    if (attributes.hasOwnProperty(attrName))
+                    {
+                        var queryResult = query("." + attrName, containerNode);
+                        if (queryResult && queryResult[0])
+                        {
+                            var attr = attributes[attrName];
+                            containerObject[attrName] = {
+                                containerNode: queryResult[0],
+                                attributeType: attr.type
+                            };
+                        }
+                    }
+                }
+            }
+            return containerObject;
+        };
+
+        util.updateAttributeNodes = function (containerObject, restData) {
+            for (var attrName in containerObject)
+            {
+                if (containerObject.hasOwnProperty(attrName) && attrName in restData)
+                {
+                    var content = "";
+                    if (containerObject[attrName].attributeType === "Boolean")
+                    {
+                        content = util.buildCheckboxMarkup(restData[attrName]);
+                    }
+                    else
+                    {
+                        content = entities.encode(String(restData[attrName]));
+                    }
+                    containerObject[attrName].containerNode.innerHTML = content;
+                }
+            }
+        };
+
         return util;
     });

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/dfaeddae/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/CriteriaPane.js
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/CriteriaPane.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/CriteriaPane.js
index 79935e6..2af73ce 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/CriteriaPane.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/CriteriaPane.js
@@ -629,6 +629,18 @@ define(["dojo/_base/declare",
                         this._getConditionValue(),
                         this.typeName);
                 },
+                getCondition: function () {
+                    if (this._removed)
+                    {
+                        return undefined;
+                    }
+                    return {
+                        name: this.criteriaName,
+                        value: this._getConditionValue(),
+                        operator: this.criteriaCondition.value,
+                        type: this.typeName
+                    };
+                },
                 _getConditionValue: function ()
                 {
                     return this.valueEditor.expression || this.valueEditor.value;

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/dfaeddae/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/DropDownSelect.js
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/DropDownSelect.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/DropDownSelect.js
index 2ac96ef..499ba56 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/DropDownSelect.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/DropDownSelect.js
@@ -59,7 +59,8 @@ define(["dojo/_base/declare",
                 this._optionsDialog = new dijit.TooltipDialog({content: this._optionsPanel}, this._createDomNode());
                 this._selectButton = new dijit.form.DropDownButton({
                     label: this.label || "Select",
-                    dropDown: this._optionsDialog
+                    dropDown: this._optionsDialog,
+                    iconClass: this.iconClass
                 }, this._createDomNode());
                 this._optionsPanel.doneButton.on("click", lang.hitch(this, this._onSelectionDone));
                 this._optionsPanel.cancelButton.on("click", lang.hitch(this, this._hideAndResetSearch));

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/dfaeddae/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/QueryWidget.js
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/QueryWidget.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/QueryWidget.js
index 21a616c..bbc021e 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/QueryWidget.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/QueryWidget.js
@@ -515,7 +515,7 @@ define(["dojo/_base/declare",
                 },
                 _standardModeWhereChanged: function (result)
                 {
-                    this._setWhereClause(result);
+                    this._setWhereClause(result.expression);
                     this.search();
                     this._queryChanged();
                 },

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/dfaeddae/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/WhereCriteria.js
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/WhereCriteria.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/WhereCriteria.js
index 1bbb270..66e33d0 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/WhereCriteria.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/WhereCriteria.js
@@ -244,6 +244,28 @@ define(["dojo/_base/declare",
                 }
                 return expression;
             },
+            getConditions: function () {
+                if (this._deleted)
+                {
+                    return undefined;
+                }
+
+                var conditions = [];
+                var criteriaArray = this.criteriaContainer.getChildren();
+                for (var i = 0; i < criteriaArray.length; i++)
+                {
+                    var condition = criteriaArray[i].getCondition();
+                    if (condition)
+                    {
+                        conditions.push(condition);
+                    }
+                }
+
+                return {
+                    operator: this.criteriaMatchCondition.value,
+                    conditions: conditions
+                };
+            },
             _destroy: function ()
             {
                 this._deleted = true;

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/dfaeddae/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/WhereExpression.js
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/WhereExpression.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/WhereExpression.js
index 91d6c9a..de27943 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/WhereExpression.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/WhereExpression.js
@@ -88,8 +88,13 @@ define(["dojo/_base/declare",
         },
         _notifyChanged: function ()
         {
-            this.whereExpression = this._getWhereExpression();
-            this.emit("change", this.whereExpression);
+            var expression = this._getWhereExpression();
+            this.whereExpression = expression;
+            this.emit("change",
+                {
+                    expression: expression,
+                    conditions: this._getConditions()
+                });
         },
         _whereCriteriaChanged: function (whereCriteria)
         {
@@ -131,6 +136,22 @@ define(["dojo/_base/declare",
             this.whereFieldsSelector.set("data", {selected: selected});
             return whereExpression;
         },
+        _getConditions: function () {
+            var conditions = [];
+            var children = this.getChildren();
+            for (var i = 0; i < children.length; i++)
+            {
+                if (!children[i].get("deleted"))
+                {
+                    var childConditions = children[i].getConditions();
+                    conditions.push(childConditions);
+                }
+            }
+            return {
+                operator: "and",
+                conditions: conditions
+            };
+        },
         clearWhereCriteria: function ()
         {
             this._whereItems = {};


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org