You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by kw...@apache.org on 2018/02/23 15:29:58 UTC

[3/3] qpid-broker-j git commit: QPID-8102: [Broker-J] Add UI for virtual host node auto-creation policies

QPID-8102: [Broker-J] Add UI for virtual host node auto-creation policies


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/2a378704
Tree: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/tree/2a378704
Diff: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/diff/2a378704

Branch: refs/heads/7.0.x
Commit: 2a378704c0b26878711726f5b71a599717c554c3
Parents: 969f7a3
Author: Alex Rudyy <or...@apache.org>
Authored: Sun Feb 18 23:24:42 2018 +0000
Committer: Keith Wall <kw...@apache.org>
Committed: Fri Feb 23 15:01:44 2018 +0000

----------------------------------------------------------------------
 .../src/main/java/resources/css/common.css      |  21 ++
 .../main/java/resources/editVirtualHost.html    |  20 +-
 .../resources/js/qpid/management/VirtualHost.js | 114 +++++-
 .../js/qpid/management/editVirtualHost.js       | 184 +++++++++-
 .../virtualhost/NodeAutoCreationPolicyForm.js   | 355 +++++++++++++++++++
 .../main/java/resources/showVirtualHost.html    |   6 +
 .../virtualhost/NodeAutoCreationPolicyForm.html | 129 +++++++
 7 files changed, 822 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/2a378704/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 cac53f6..e4b2511 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
@@ -789,3 +789,24 @@ td.advancedSearchField, col.autoWidth {
 {
     margin-bottom: 10px !important;
 }
+
+#editVirtualHostDialog
+{
+    width: 550px;
+}
+.nodeAutoCreationPolicies .field-selected { width: 2em; }
+.nodeAutoCreationPolicies .field-nodeType { width: 10%; }
+.nodeAutoCreationPolicies .field-pattern { width: 10%; }
+.nodeAutoCreationPolicies .field-createdOnPublish { width: 10%; }
+.nodeAutoCreationPolicies .field-createdOnConsume { width: 10% }
+.nodeAutoCreationPolicies .field-attributes { width: auto }
+
+.nodeAutoCreationPolicyAttributes { height: 100px;}
+.keyValuePair {
+    overflow: auto;
+}
+
+.sequentialPanel
+{
+    margin-bottom: 0.2em !important;
+}

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/2a378704/broker-plugins/management-http/src/main/java/resources/editVirtualHost.html
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/editVirtualHost.html b/broker-plugins/management-http/src/main/java/resources/editVirtualHost.html
index 74ca047..042e05b 100644
--- a/broker-plugins/management-http/src/main/java/resources/editVirtualHost.html
+++ b/broker-plugins/management-http/src/main/java/resources/editVirtualHost.html
@@ -107,10 +107,6 @@
                                      promptMessage="Number of threads used to perform housekeeping"/>
                           </div>
                       </div>
-                  </fieldset>
-              </div>
-              <div class="clear"></div>
-
                 <div class="clear">
                     <div class="formLabel-labelCell tableContainer-labelCell">Number of connection threads:</div>
                     <div class="tableContainer-valueCell formLabel-controlCell">
@@ -135,6 +131,22 @@
                               promptMessage: 'Period with which statistics are reported to the log.'" />
                     </div>
                 </div>
+                  </fieldset>
+              </div>
+              <div class="clear"></div>
+              <div data-dojo-type="dijit/TitlePane"
+                 data-dojo-props="title: 'Node Auto-Creation Policies',  open: false"
+                 class="sequentialPanel">
+                <div id="editVirtualHost.policies"></div>
+                <button data-dojo-type="dijit.form.Button"
+                        data-dojo-props="promptMessage:'Add Node Auto Creation Policy'"
+                        id="editVirtualHost.addAutoCreationPolicy">+
+                </button>
+                <button data-dojo-type="dijit.form.Button"
+                        data-dojo-props="promptMessage:'Delete Node Auto Creation Policy', disabled: true"
+                        id="editVirtualHost.deleteAutoCreationPolicy">-
+                </button>
+              </div>
               <div class="clear"></div>
 
               <div data-dojo-type="dijit/TitlePane" data-dojo-props="title: 'Context variables',  open: false">

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/2a378704/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js
index dd7a2fc..6df7870 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js
@@ -33,8 +33,18 @@ define(["dojo/parser",
         "qpid/management/query/QueryGrid",
         "qpid/management/editVirtualHost",
         "qpid/common/StatisticsWidget",
-        "dgrid/Selector",
         "dojo/text!showVirtualHost.html",
+        "dijit/Dialog",
+        "dgrid/Grid",
+        "dgrid/Selector",
+        "dgrid/Keyboard",
+        "dgrid/Selection",
+        "dgrid/extensions/Pagination",
+        "dgrid/extensions/ColumnResizer",
+        "dgrid/extensions/DijitRegistry",
+        "dstore/Memory",
+        "dstore/Trackable",
+        "dojo/aspect",
         "dojo/domReady!"],
     function (parser,
               query,
@@ -51,8 +61,18 @@ define(["dojo/parser",
               QueryGrid,
               editVirtualHost,
               StatisticsWidget,
+              template,
+              Dialog,
+              Grid,
               Selector,
-              template)
+              Keyboard,
+              Selection,
+              Pagination,
+              ColumnResizer,
+              DijitRegistry,
+              MemoryStore,
+              TrackableStore,
+              aspect)
     {
 
         function VirtualHost(kwArgs)
@@ -447,6 +467,72 @@ define(["dojo/parser",
             }, findNode("loggers"));
             this.virtualHostLoggersGrid.on('rowBrowsed', function(event){controller.showById(event.id);});
             this.virtualHostLoggersGrid.startup();
+
+            var Store = MemoryStore.createSubclass(TrackableStore);
+            this._policyStore = new Store({
+                data: [],
+                idProperty: "pattern"
+            });
+
+            var PolicyGrid = declare([Grid, Keyboard, Selection, Pagination, ColumnResizer, DijitRegistry]);
+            this._policyGrid = new PolicyGrid({
+                rowsPerPage: 10,
+                selectionMode: 'none',
+                deselectOnRefresh: false,
+                allowSelectAll: true,
+                cellNavigation: true,
+                className: 'dgrid-autoheight',
+                pageSizeOptions: [10, 20, 30, 40, 50, 100],
+                adjustLastColumn: true,
+                collection: this._policyStore,
+                highlightRow: function (){},
+                columns: [
+                    {
+                        label: 'Node Type',
+                        field: "nodeType"
+                    }, {
+                        label: "Pattern",
+                        field: "pattern"
+                    }, {
+                        label: "Create On Publish",
+                        field: "createdOnPublish",
+                        selector: 'checkbox'
+                    }, {
+                        label: "Create On Consume",
+                        field: "createdOnConsume",
+                        selector: 'checkbox'
+                    }, {
+                        label: "Attributes",
+                        field: "attributes",
+                        sortable: false,
+                        formatter: function(value, object)
+                        {
+                            var markup = "";
+                            if (value)
+                            {
+                                markup = "<div class='keyValuePair'>";
+                                for(var key in value)
+                                {
+                                    markup += "<div>" + key + "=" + value[key] + "</div>";
+                                }
+                                markup += "</div>"
+                            }
+                            return markup;
+                        }
+                    }
+                ]
+            }, findNode("policies"));
+
+            this._policyGrid.startup();
+            this._nodeAutoCreationPolicies = registry.byNode(findNode("nodeAutoCreationPolicies"));
+
+            aspect.after(this._nodeAutoCreationPolicies, "toggle", lang.hitch(this, function() {
+                if (this._nodeAutoCreationPolicies.get("open") === true)
+                {
+                    this._policyGrid.refresh();
+                }
+            }));
+
         }
 
         Updater.prototype.update = function (callback)
@@ -549,6 +635,7 @@ define(["dojo/parser",
                         thisObj.details.update(thisObj.vhostData);
                     });
             }
+            this._updateDStore(this._policyStore, this.vhostData.nodeAutoCreationPolicies || [], "pattern");
         };
 
         Updater.prototype._updateHeader = function ()
@@ -617,6 +704,29 @@ define(["dojo/parser",
             return connections;
         };
 
+        Updater.prototype._updateDStore = function (dstore, data, idProperty) {
+            if (data)
+            {
+                for (var i = 0; i < data.length; i++)
+                {
+                    dstore.put(data[i]);
+                }
+            }
+            dstore.fetch()
+                .forEach(function (object) {
+                    if (data)
+                    {
+                        for (var i = 0; i < data.length; i++)
+                        {
+                            if (data[i][idProperty] === object[idProperty])
+                            {
+                                return;
+                            }
+                        }
+                    }
+                    dstore.remove(object[idProperty]);
+                });
+        };
 
         return VirtualHost;
     });

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/2a378704/broker-plugins/management-http/src/main/java/resources/js/qpid/management/editVirtualHost.js
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/editVirtualHost.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/editVirtualHost.js
index 93c358d..f59ae31 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/editVirtualHost.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/editVirtualHost.js
@@ -20,6 +20,7 @@
  */
 define(["dojox/html/entities",
         "dojo/_base/array",
+        "dojo/_base/declare",
         "dojo/_base/event",
         "dojo/_base/lang",
         "dojo/_base/window",
@@ -33,6 +34,16 @@ define(["dojox/html/entities",
         "dojo/data/ObjectStore",
         "qpid/common/util",
         "dojo/text!editVirtualHost.html",
+        "dgrid/OnDemandGrid",
+        "dgrid/Selector",
+        "dgrid/Keyboard",
+        "dgrid/Selection",
+        "dgrid/extensions/Pagination",
+        "dgrid/extensions/ColumnResizer",
+        "dgrid/extensions/DijitRegistry",
+        "dstore/Memory",
+        "dstore/Trackable",
+        "dojo/keys",
         "qpid/common/ContextVariablesEditor",
         "dijit/Dialog",
         "dijit/form/CheckBox",
@@ -45,6 +56,7 @@ define(["dojox/html/entities",
         "dojo/domReady!"],
     function (entities,
               array,
+              declare,
               event,
               lang,
               win,
@@ -57,7 +69,17 @@ define(["dojox/html/entities",
               Memory,
               ObjectStore,
               util,
-              template)
+              template,
+              Grid,
+              Selector,
+              Keyboard,
+              Selection,
+              Pagination,
+              ColumnResizer,
+              DijitRegistry,
+              MemoryStore,
+              TrackableStore,
+              keys)
     {
         var fields = ["name",
                       "connectionThreadPoolSize",
@@ -112,6 +134,7 @@ define(["dojox/html/entities",
                 {
                     return false;
                 });
+                this._createNodeAutoCreationPolicyUI();
             },
             show: function (management, modelObj)
             {
@@ -158,6 +181,7 @@ define(["dojox/html/entities",
                     {
                         data["context"] = context;
                     }
+                    data.nodeAutoCreationPolicies = this._getNodeAutoCreationPolicies();
                     var that = this;
                     this.management.update(that.modelObj, data)
                         .then(function (x)
@@ -234,13 +258,171 @@ define(["dojox/html/entities",
                     }
                 });
 
+                this._initNodeAutoCreationPolicies(data);
                 this.dialog.startup();
                 this.dialog.show();
+                this.dialog.reset();
                 if (!this.resizeEventRegistered)
                 {
                     this.resizeEventRegistered = true;
                     util.resizeContentAreaAndRepositionDialog(dom.byId("editVirtualHost.contentPane"), this.dialog);
                 }
+                this._policyGrid.startup();
+                this._policyGrid.refresh();
+            },
+            _createNodeAutoCreationPolicyUI: function () {
+                this.addNodeAutoCreationPolicyButton =
+                    registry.byId("editVirtualHost.addAutoCreationPolicy");
+                this.addNodeAutoCreationPolicyButton.on("click",
+                    lang.hitch(this, this._addNodeAutoCreationPolicy));
+
+                this.deleteNodeAutoCreationPolicyButton =
+                    registry.byId("editVirtualHost.deleteAutoCreationPolicy");
+                this.deleteNodeAutoCreationPolicyButton.on("click",
+                    lang.hitch(this, this._deleteNodeAutoCreationPolicy));
+                this._policies = [];
+                var Store = MemoryStore.createSubclass(TrackableStore);
+                this._policyStore = new Store({
+                    data: this._policies,
+                    idProperty: "pattern"
+                });
+                var PolicyGrid = declare([Grid, Keyboard, Selector, Selection, ColumnResizer, DijitRegistry]);
+                this._policyGrid = new PolicyGrid({
+                    rowsPerPage: 10,
+                    selectionMode: 'none',
+                    deselectOnRefresh: false,
+                    allowSelectAll: true,
+                    cellNavigation: true,
+                    className: 'dgrid-autoheight',
+                    pageSizeOptions: [10, 20, 30, 40, 50, 100],
+                    adjustLastColumn: true,
+                    collection: this._policyStore,
+                    highlightRow: function (){},
+                    columns: {
+                        selected: {
+                            label: 'All',
+                            selector: 'checkbox'
+                        },
+                        nodeType: {
+                            label: "Node Type"
+                        },
+                        pattern: {
+                            label: "Pattern"
+                        },
+                        createdOnPublish: {
+                            label: "Create On Publish"
+                        },
+                        createdOnConsume: {
+                            label: "Create On Consume"
+                        },
+                        attributes: {
+                            label: "Attributes",
+                            sortable: false,
+                            formatter: function(value, object)
+                            {
+                                var markup = "";
+                                if (value)
+                                {
+                                    markup = "<div class='keyValuePair'>";
+                                    for(var key in value)
+                                    {
+                                        markup += "<div>" + key + "=" + value[key] + "</div>";
+                                    }
+                                    markup +="</div>"
+                                }
+                                return markup;
+                            }
+                        }
+                    }
+                }, dom.byId("editVirtualHost.policies"));
+
+                this._policyGrid.on('.dgrid-row:dblclick', lang.hitch(this, this._policySelected));
+                this._policyGrid.on('.dgrid-row:keypress', lang.hitch(this, function (event) {
+                    if (event.keyCode === keys.ENTER)
+                    {
+                        this._policySelected(event);
+                    }
+                }));
+                this._policyGrid.on('dgrid-select', lang.hitch(this, this._policySelectionChanged));
+                this._policyGrid.on('dgrid-deselect', lang.hitch(this, this._policySelectionChanged));
+
+            },
+            _initNodeAutoCreationPolicies: function (data) {
+                this._policies =
+                    data.actual && data.actual.nodeAutoCreationPolicies ? data.actual.nodeAutoCreationPolicies : [];
+                var Store = MemoryStore.createSubclass(TrackableStore);
+                this._policyStore = new Store({
+                    data: this._policies,
+                    idProperty: "pattern"
+                });
+                this._policyGrid.set("collection", this._policyStore);
+            },
+            _addNodeAutoCreationPolicy: function () {
+                this._showNodeAutoCreationPolicyForm({});
+            },
+            _showNodeAutoCreationPolicyForm: function (item) {
+                if (this.nodeAutoCreationPolicyForm)
+                {
+                    this.nodeAutoCreationPolicyForm.show(item, this._getNodeAutoCreationPolicies());
+                }
+                else
+                {
+                    require(["qpid/management/virtualhost/NodeAutoCreationPolicyForm"],
+                        lang.hitch(this, function (NodeAutoCreationPolicyForm) {
+                            this.nodeAutoCreationPolicyForm =
+                                new NodeAutoCreationPolicyForm({management: this.management});
+                            this.nodeAutoCreationPolicyForm.on("create", lang.hitch(this, function (e) {
+                                try
+                                {
+                                    this._policyStore.putSync(e.data);
+                                }
+                                catch (e)
+                                {
+                                    console.warn("Unexpected error" + e);
+                                }
+                                this._policyGrid.refresh({keepScrollPosition: true});
+                            }));
+                            this.nodeAutoCreationPolicyForm.show(item, this._getNodeAutoCreationPolicies());
+                        }));
+                }
+            },
+            _policySelected: function (event) {
+                var row = this._policyGrid.row(event);
+                this._showNodeAutoCreationPolicyForm(row.data);
+            },
+            _deleteNodeAutoCreationPolicy: function () {
+                var selected = this._getSelectedPolicies();
+                if (selected.length > 0)
+                {
+                    for (var s in selected)
+                    {
+                        this._policyStore.removeSync(selected[s]);
+                    }
+                    this._policyGrid.clearSelection();
+                }
+            },
+            _getSelectedPolicies: function () {
+                var selected = [];
+                var selection = this._policyGrid.selection;
+                for (var item in selection)
+                {
+                    if (selection.hasOwnProperty(item) && selection[item])
+                    {
+                        selected.push(item);
+                    }
+                }
+                return selected;
+            },
+            _policySelectionChanged: function () {
+                var selected = this._getSelectedPolicies();
+                this.deleteNodeAutoCreationPolicyButton.set("disabled", selected.length === 0);
+            },
+            _getNodeAutoCreationPolicies: function () {
+                var policies = [];
+                this._policyStore.fetchSync().forEach(function (policy) {
+                    policies.push(policy);
+                });
+                return policies;
             }
         };
 

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/2a378704/broker-plugins/management-http/src/main/java/resources/js/qpid/management/virtualhost/NodeAutoCreationPolicyForm.js
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/virtualhost/NodeAutoCreationPolicyForm.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/virtualhost/NodeAutoCreationPolicyForm.js
new file mode 100644
index 0000000..c250063
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/virtualhost/NodeAutoCreationPolicyForm.js
@@ -0,0 +1,355 @@
+/*
+ *
+ * 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/Evented",
+        "dojo/keys",
+        "dojo/text!virtualhost/NodeAutoCreationPolicyForm.html",
+        "dgrid/OnDemandGrid",
+        "dgrid/Selector",
+        "dgrid/Keyboard",
+        "dgrid/Selection",
+        "dgrid/Editor",
+        "dgrid/extensions/ColumnResizer",
+        "dgrid/extensions/DijitRegistry",
+        "dstore/Memory",
+        "dstore/Trackable",
+        "dstore/legacy/DstoreAdapter",
+        "dijit/Dialog",
+        "dojox/validate/us",
+        "dojox/validate/web",
+        "dijit/_WidgetBase",
+        "dijit/_TemplatedMixin",
+        "dijit/_WidgetsInTemplateMixin",
+        "dijit/form/CheckBox",
+        "dijit/form/ComboBox",
+        "dijit/form/ValidationTextBox",
+        "dijit/form/Button",
+        "dijit/form/Form",
+        "dojo/domReady!"],
+    function (declare,
+              lang,
+              Evented,
+              keys,
+              template,
+              Grid,
+              Selector,
+              Keyboard,
+              Selection,
+              Editor,
+              ColumnResizer,
+              DijitRegistry,
+              Memory,
+              Trackable) {
+
+        var Store = Memory.createSubclass(Trackable);
+        return declare("qpid.management.virtualhost.NodeAutoCreationPolicyForm",
+            [dijit._WidgetBase, dijit._TemplatedMixin, dijit._WidgetsInTemplateMixin, Evented],
+            {
+                /**
+                 * dijit._TemplatedMixin enforced fields
+                 */
+                //Strip out the apache comment header from the template html as comments unsupported.
+                templateString: template.replace(/<!--[\s\S]*?-->/g, ""),
+
+                /**
+                 * template attach points
+                 */
+                pattern: null,
+                attributes: null,
+                createdOnPublish: null,
+                createdOnConsume: null,
+                okButton: null,
+                cancelButton: null,
+                nodeAutoCreationPolicyForm: null,
+                addAttributeButton: null,
+                deleteAttributeButton: null,
+                nodeAutoCreationPolicyDialog: null,
+                type: null,
+
+                /**
+                 * constructor arguments
+                 */
+                management: null,
+                /**
+                 * private fields
+                 */
+                _store: null,
+                _policy: null,
+                _attributesGrid: null,
+                _id: 0,
+                _nodeAutoCreationPolicyDialog: null,
+
+                postCreate: function () {
+                    this.inherited(arguments);
+                    this.cancelButton.on("click", lang.hitch(this, this._onCancel));
+                    this.okButton.on("click", lang.hitch(this, this._onFormSubmit));
+                    this.pattern.on("change", lang.hitch(this, this._onChange));
+                    this.createdOnPublish.on("change", lang.hitch(this, this._onChange));
+                    this.createdOnConsume.on("change", lang.hitch(this, this._onChange));
+                    this.addAttributeButton.on("click", lang.hitch(this, this._addAttribute));
+                    this.deleteAttributeButton.on("click", lang.hitch(this, this._deleteAttribute));
+                    this.okButton.set("disabled", true);
+                    this.deleteAttributeButton.set("disabled", true);
+                    this.type.on("change", lang.hitch(this, this._onChange));
+                    this._store = new Store({data: [], idProperty: "id"});
+                },
+                show: function(policyData, policies)
+                {
+                    this._policy = policyData ? policyData: {};
+                    this._policies = policies || [];
+                    var attributes = [];
+                    this._id = 0;
+                    if (this._policy.attributes)
+                    {
+                        for(var a in this._policy.attributes)
+                        {
+                            if (this._policy.attributes.hasOwnProperty(a))
+                            {
+                                var id = (++this._id);
+                                attributes.push({
+                                    id: id,
+                                    name: a,
+                                    value: this._policy.attributes[a]
+                                });
+                            }
+                        }
+                    }
+                    this._store = new Store({data: attributes, idProperty: "id"});
+                    this.type.set("value", this._policy.nodeType ? this._policy.nodeType : "Queue");
+                    this.pattern.set("value", this._policy.pattern ? this._policy.pattern : "");
+                    this.createdOnPublish.set("checked", this._policy.createdOnPublish);
+                    this.createdOnConsume.set("checked", this._policy.createdOnConsume);
+                    this.addAttributeButton.set("disabled", false);
+                    this.nodeAutoCreationPolicyDialog.show();
+                    this._initAttributesGrid();
+                },
+                _onCancel: function () {
+                    this.nodeAutoCreationPolicyDialog.hide();
+                    this.emit("cancel");
+                },
+                _onChange: function () {
+                    var invalid = !this.pattern.value ||
+                                  !(this.type.value) ||
+                                  !(this.createdOnPublish.checked || this.createdOnConsume.checked) ||
+                                  this.addAttributeButton.get("disabled");
+                    this.okButton.set("disabled", invalid);
+                },
+                _onFormSubmit: function () {
+                    try
+                    {
+                        if (this.nodeAutoCreationPolicyForm.validate())
+                        {
+                            var nodeType = this.type.value;
+                            var category = nodeType.charAt(0).toUpperCase() + nodeType.substring(1);
+                            if (this.management.metadata.metadata[category])
+                            {
+                                if (this._isUniquePattern(this.pattern.value))
+                                {
+                                    var data = {
+                                        pattern: this.pattern.value,
+                                        nodeType: nodeType,
+                                        createdOnPublish: this.createdOnPublish.checked,
+                                        createdOnConsume: this.createdOnConsume.checked,
+                                        attributes: this._getObjectAttributes()
+                                    };
+                                    this.emit("create", {data: data});
+                                    this.nodeAutoCreationPolicyDialog.hide();
+                                }
+                                else
+                                {
+                                    alert('The auto-creation policy with the same pattern already exists');
+                                }
+                            }
+                            else
+                            {
+                                alert('Specified node type does not exist. Please enter valid node type');
+                            }
+                        }
+                        else
+                        {
+                            alert('Form contains invalid data.  Please correct first');
+                        }
+                    }
+                    catch (e)
+                    {
+                        console.warn(e);
+                    }
+                    return false;
+                },
+                _addAttribute: function () {
+                    var id = (++this._id);
+                    var item = {
+                        name: "<new>",
+                        value: "<new>",
+                        id: id
+                    };
+                    this.addAttributeButton.set("disabled", true);
+                    try
+                    {
+                        this._store.addSync(item);
+                        this._attributesGrid.edit(this._attributesGrid.cell(item, "name"));
+                    }
+                    catch(e)
+                    {
+                        console.error("failure to add new attribute:" + e);
+                    }
+                },
+                _deleteAttribute: function () {
+                    var selected = this._getSelectedAttributes();
+                    var newDeleted = false;
+                    if (selected.length > 0)
+                    {
+                        for (var s in selected)
+                        {
+                            if (selected.hasOwnProperty(s))
+                            {
+                                var id = selected[s];
+                                var item =  this._store.getSync(id);
+                                if (item)
+                                {
+                                    if (item.name === "<new>")
+                                    {
+                                        newDeleted = true;
+                                    }
+                                    this._store.removeSync(selected[s]);
+                                }
+                            }
+                        }
+                        this._attributesGrid.clearSelection();
+                    }
+                    if (newDeleted)
+                    {
+                        this.addAttributeButton.set("disabled", false);
+                    }
+                },
+                _getSelectedAttributes: function () {
+                    var selected = [];
+                    var selection = this._attributesGrid.selection;
+                    for(var item in selection)
+                    {
+                        if (selection.hasOwnProperty(item) && selection[item])
+                        {
+                            selected.push(item);
+                        }
+                    }
+                    return selected;
+                },
+                _onGridEdit: function (e) {
+                        if (e.value !== "<new>")
+                        {
+                            if (e.cell.column.field==="name" && e.oldValue === "<new>" && e.value !== "<new>")
+                            {
+                                this.addAttributeButton.set("disabled", false);
+                            }
+                        }
+                },
+                _gridSelectionChanged: function () {
+                    var selected = this._getSelectedAttributes();
+                    this.deleteAttributeButton.set("disabled", selected.length === 0);
+                },
+                _getObjectAttributes: function () {
+                    var attributes = {};
+                    this._store.fetchSync().forEach(function (entry) {
+                        attributes[entry.name] = entry.value;
+                    });
+                    return attributes;
+                },
+                _isUniquePattern: function(pattern)
+                {
+                    if (this._policy && this._policy.pattern === pattern)
+                    {
+                        // no change to the pattern
+                        return true;
+                    }
+                    for (var i=0;i<this._policies.length;i++)
+                    {
+                        if (this._policies[i].pattern === pattern)
+                        {
+                            return false;
+                        }
+                    }
+                    return true;
+                },
+                _initAttributesGrid: function()
+                {
+                    if (this._attributesGrid )
+                    {
+                        this._attributesGrid.set("collection", this._store);
+                    }
+                    else
+                    {
+                        var CustomGrid = declare([Grid, Selector, Editor, Keyboard, DijitRegistry]);
+                        this._attributesGrid = new CustomGrid({
+                            selectionMode: 'none',
+                            deselectOnRefresh: false,
+                            allowSelectAll: true,
+                            cellNavigation: true,
+                            adjustLastColumn: true,
+                            collection: this._store,
+                            sort: "id",
+                            showHeader: true,
+                            highlightRow: function (){},
+                            columns: {
+                                selected: {
+                                    label: 'All',
+                                    selector: 'checkbox'
+                                },
+                                name: {
+                                    label: 'Name',
+                                    editor: 'text',
+                                    autoSelect: true,
+                                    autoSave: true,
+                                    editOn  : "click,dgrid-cellfocusin"
+                                },
+                                value: {
+                                    label: "Value",
+                                    editor: 'text',
+                                    autoSelect: true,
+                                    autoSave: true,
+                                    editOn: "click,dgrid-cellfocusin"
+                                }
+                            }
+                        }, this.attributes);
+                        this._attributesGrid.on("dgrid-datachange", lang.hitch(this, this._onGridEdit));
+                        this._attributesGrid.on('dgrid-select', lang.hitch(this, this._gridSelectionChanged));
+                        this._attributesGrid.on('dgrid-deselect', lang.hitch(this, this._gridSelectionChanged));
+
+                        // Header TAB navigation does not work reliably with Editor and Selector
+                        // This is a work around to always focus first cell in first row if grid is not empty
+                        this._attributesGrid.addKeyHandler(keys.TAB, lang.hitch(this, function (event) {
+                            var range = this._store.fetchRangeSync({start: 0, end: 1});
+                            if (range && range[0])
+                            {
+                                var cell = this._attributesGrid.cell(range[0], "selected");
+                                if (cell)
+                                {
+                                    this._attributesGrid.focus(cell);
+                                    event.preventDefault();
+                                    event.stopPropagation();
+                                }
+                            }
+                        }), true);
+                        this._attributesGrid.startup();
+                    }
+                }
+            });
+    });

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/2a378704/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html b/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html
index 9be2a60..beda11e 100644
--- a/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html
+++ b/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html
@@ -95,6 +95,12 @@
             </div>
             <div class="clear"></div>
         </div>
+        <br/>
+        <div data-dojo-type="dijit.TitlePane"
+             data-dojo-props="title: 'Node Auto-Creation Policies',  open: false"
+             class="nodeAutoCreationPolicies">
+            <div class="policies"></div>
+        </div>
 
     </div>
     <br/>

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/2a378704/broker-plugins/management-http/src/main/java/resources/virtualhost/NodeAutoCreationPolicyForm.html
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/virtualhost/NodeAutoCreationPolicyForm.html b/broker-plugins/management-http/src/main/java/resources/virtualhost/NodeAutoCreationPolicyForm.html
new file mode 100644
index 0000000..bef23eb
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/resources/virtualhost/NodeAutoCreationPolicyForm.html
@@ -0,0 +1,129 @@
+<!--
+  ~ 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="dijitHidden">
+    <div data-dojo-type="dijit/Dialog"
+         data-dojo-props="title:'Node Auto-Creation Policy'"
+         data-dojo-attach-point="nodeAutoCreationPolicyDialog">
+        <div>
+            <form data-dojo-attach-point="nodeAutoCreationPolicyForm"
+                  data-dojo-type="dijit/form/Form"
+                  id="${id}_nodeAutoCreationPolicyForm"
+                  class="nodeAutoCreationPolicyForm">
+                <div>
+                    <div class="clear">
+                        <label class="formLabel-labelCell tableContainer-labelCell"
+                               for="${id}_pattern">Pattern*: </label>
+                        <input id="${id}_pattern"
+                               type="text"
+                               class="formLabel-controlCell tableContainer-valueCell"
+                               data-dojo-attach-point="pattern"
+                               data-dojo-type="dijit/form/ValidationTextBox"
+                               data-dojo-props="name: 'pattern',
+                        required: true,
+                        intermediateChanges: true,
+                        placeHolder: 'Name matching regular expression',
+                        title: 'Enter name matching regular expression'"/>
+                    </div>
+                    <div class="clear">
+                        <label class="formLabel-labelCell tableContainer-labelCell" for="${id}_nodeType"
+                               id="${id}_nodeTypeLabel">Node Type*: </label>
+                        <select id="${id}_nodeType" class="formLabel-controlCell tableContainer-valueCell"
+                                data-dojo-attach-point="type"
+                                data-dojo-type='dijit/form/ComboBox'
+                                data-dojo-props=" name: 'type',
+                                          placeHolder: 'Type of Node',
+                                          required: true,
+                                          value: 'Queue',
+                                          title: 'Type of node to create.',
+                                          promptMessage: 'Select type of node to create.',
+                                          intermediateChanges: true">
+                            <option value="Queue" selected="true">Queue</option>
+                            <option value="Exchange">Exchange</option>
+                        </select>
+                    </div>
+                    <div class="clear formBox">
+                        <fieldset>
+                            <legend>Create On*:</legend>
+                            <div class="clear">
+                                <label class="formLabel-labelCell tableContainer-labelCell"
+                                       for="${id}_createdOnPublish">Create On Publish:</label>
+                                <input id="${id}_createdOnPublish"
+                                       class="formLabel-controlCell tableContainer-valueCell"
+                                       type="checkbox"
+                                       data-dojo-type="dijit/form/CheckBox"
+                                       data-dojo-attach-point="createdOnPublish"
+                                       data-dojo-props="name: 'createdOnPublish', intermediateChanges: true"/>
+                                <div data-dojo-type="dijit/Tooltip"
+                                     data-dojo-props="connectId: ['${id}_createdOnPublish'],
+                              label: 'If selected, node is created by publisher'">
+                                </div>
+                            </div>
+                            <div class="clear">
+                                <label class="formLabel-labelCell tableContainer-labelCell"
+                                       for="${id}_createdOnConsume">Create On Consume:</label>
+                                <input id="${id}_createdOnConsume"
+                                       class="formLabel-controlCell tableContainer-valueCell"
+                                       type="checkbox"
+                                       data-dojo-type="dijit/form/CheckBox"
+                                       data-dojo-attach-point="createdOnConsume"
+                                       data-dojo-props="name: 'createdOnConsume',intermediateChanges: true"/>
+                                <div data-dojo-type="dijit/Tooltip"
+                                     data-dojo-props="connectId: ['${id}_createdOnConsume'],
+                              label: 'If selected, node is created by consumer'">
+                                </div>
+                            </div>
+                        </fieldset>
+                    </div>
+                    <div class="clear formBox">
+                        <fieldset>
+                            <legend>Attributes:</legend>
+                            <div data-dojo-attach-point="attributes" id="${id}_attributes"
+                                 class="nodeAutoCreationPolicyAttributes"></div>
+                            <div>
+                                <button data-dojo-type="dijit/form/Button"
+                                        id="${id}_addAttributeButton"
+                                        type="button"
+                                        data-dojo-props="title:'Add new attribute'"
+                                        data-dojo-attach-point="addAttributeButton">+</button>
+                                <button data-dojo-type="dijit/form/Button"
+                                        id="${id}_deleteAttributeButton"
+                                        type="button"
+                                        data-dojo-props="title:'Remove selected attribute(s)'"
+                                        data-dojo-attach-point="deleteAttributeButton">-</button>
+                            </div>
+                        </fieldset>
+                    </div>
+                    <div class="clear"></div>
+                </div>
+                <div class="dijitDialogPaneActionBar">
+                    <input id="${id}_cancelButton"
+                           type="button"
+                           data-dojo-attach-point="cancelButton"
+                           data-dojo-type="dijit/form/Button"
+                           data-dojo-props="label: 'Cancel'"/>
+                    <input id="${id}_okButton"
+                           type="submit"
+                           data-dojo-attach-point="okButton"
+                           data-dojo-type="dijit/form/Button"
+                           data-dojo-props="label: 'Ok'"/>
+                </div>
+            </form>
+        </div>
+    </div>
+</div>


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