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/03/22 18:25:23 UTC

qpid-broker-j git commit: QPID-7925: [Java Broker] [WMC] Add ability to maintain rule-based access control provider for virtualhost

Repository: qpid-broker-j
Updated Branches:
  refs/heads/master c5e5cd2ab -> 03b08426e


QPID-7925: [Java Broker] [WMC] Add ability to maintain rule-based access control provider for virtualhost


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

Branch: refs/heads/master
Commit: 03b08426e3cc75ee43adbb18bd110dd908cfce51
Parents: c5e5cd2
Author: Alex Rudyy <or...@apache.org>
Authored: Wed Mar 21 18:05:23 2018 +0000
Committer: Alex Rudyy <or...@apache.org>
Committed: Thu Mar 22 18:24:49 2018 +0000

----------------------------------------------------------------------
 ...actCommonRuleBasedAccessControlProvider.java |  16 +-
 .../rulebased/LoadForm.html                     |  59 ++++++
 .../accesscontrolprovider/rulebased/add.html    |  33 +++
 .../accesscontrolprovider/showRuleBased.html    |  37 ++++
 .../src/main/java/resources/css/common.css      |  12 ++
 .../resources/js/qpid/common/ResourceWidget.js  |   4 +
 .../main/java/resources/js/qpid/common/util.js  |  33 +++
 .../js/qpid/management/AccessControlProvider.js |  88 +++++---
 .../resources/js/qpid/management/VirtualHost.js |  94 +++++----
 .../management/accesscontrolprovider/AclFile.js | 116 ++---------
 .../accesscontrolprovider/RuleBased.js          | 201 +++++++++++++++++++
 .../accesscontrolprovider/rulebased/LoadForm.js | 103 ++++++++++
 .../accesscontrolprovider/rulebased/add.js      |  52 +++++
 .../qpid/management/addAccessControlProvider.js |  22 +-
 .../resources/js/qpid/management/controller.js  |   1 +
 .../js/qpid/management/query/QueryWidget.js     |   8 +-
 .../main/java/resources/showVirtualHost.html    |  10 +
 17 files changed, 712 insertions(+), 177 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/03b08426/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AbstractCommonRuleBasedAccessControlProvider.java
----------------------------------------------------------------------
diff --git a/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AbstractCommonRuleBasedAccessControlProvider.java b/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AbstractCommonRuleBasedAccessControlProvider.java
index 315f297..0719e67 100644
--- a/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AbstractCommonRuleBasedAccessControlProvider.java
+++ b/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AbstractCommonRuleBasedAccessControlProvider.java
@@ -26,6 +26,8 @@ import static org.apache.qpid.server.security.access.plugins.RuleBasedAccessCont
 import java.io.IOException;
 import java.io.OutputStream;
 import java.nio.charset.StandardCharsets;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -190,17 +192,19 @@ abstract class AbstractCommonRuleBasedAccessControlProvider<X extends AbstractCo
             }
             sb.append('\n');
         }
-        return new StringContent(sb.toString());
+        return new StringContent(getName(), sb.toString());
     }
 
     private static class StringContent implements Content, CustomRestHeaders
     {
-
+        private final static DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd-HHmmss");
         private final String _content;
+        private final String _name;
 
-        public StringContent(final String content)
+        public StringContent(final String name, final String content)
         {
             _content = content;
+            _name = name;
         }
 
         @Override
@@ -215,6 +219,12 @@ abstract class AbstractCommonRuleBasedAccessControlProvider<X extends AbstractCo
             return "text/plain";
         }
 
+        @RestContentHeader("Content-Disposition")
+        public String getContentDisposition()
+        {
+            return String.format("attachment; filename=\"%s-%s.acl\"", _name, FORMATTER.format(LocalDateTime.now()));
+        }
+
         @Override
         public void release()
         {

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/03b08426/broker-plugins/management-http/src/main/java/resources/accesscontrolprovider/rulebased/LoadForm.html
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/accesscontrolprovider/rulebased/LoadForm.html b/broker-plugins/management-http/src/main/java/resources/accesscontrolprovider/rulebased/LoadForm.html
new file mode 100644
index 0000000..9601696
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/resources/accesscontrolprovider/rulebased/LoadForm.html
@@ -0,0 +1,59 @@
+<!--
+  ~ 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:'Select file to load'"
+         data-dojo-attach-point="loadDialog">
+        <div>
+            <div id="${id}_warning" class="infoMessage hidden clear" data-dojo-attach-point="warning"></div>
+            <form data-dojo-attach-point="loadForm"
+                  data-dojo-type="dijit/form/Form"
+                  id="${id}_loadForm"
+                  class="loadForm">
+                <div>
+                    <div class="clear">
+                        <div class="formLabel-labelCell tableContainer-labelCell">Server path or upload*:</div>
+                        <input type="text" id="${id}_loadFormPath"
+                               data-dojo-type="qpid/common/ResourceWidget"
+                               data-dojo-attach-point="path"
+                               data-dojo-props="
+                              name: 'path',
+                              placeHolder: 'access control provider file server path',
+                              required: true,
+                              promptMessage: 'Location of the access control provider file',
+                              title: 'Enter the access control provider file path'" />
+                    </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>

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/03b08426/broker-plugins/management-http/src/main/java/resources/accesscontrolprovider/rulebased/add.html
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/accesscontrolprovider/rulebased/add.html b/broker-plugins/management-http/src/main/java/resources/accesscontrolprovider/rulebased/add.html
new file mode 100644
index 0000000..671a81a
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/resources/accesscontrolprovider/rulebased/add.html
@@ -0,0 +1,33 @@
+<!--
+  ~ 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>
+    <div class="clear">
+        <div class="formLabel-labelCell tableContainer-labelCell">Default Result:</div>
+        <input type="text" id="addAccessControlProvider.ruleBased.defaultResult"
+               data-dojo-type="dijit/form/FilteringSelect"
+               data-dojo-props="
+                              name: 'defaultResult',
+                              required: true,
+                              placeHolder: 'default result',
+                              promptMessage: 'the default result to use if no rules match the requested operation',
+                              title: 'the default result to use if no rules match the requested operation'"/>
+    </div>
+    <div class="clear"></div>
+</div>

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/03b08426/broker-plugins/management-http/src/main/java/resources/accesscontrolprovider/showRuleBased.html
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/accesscontrolprovider/showRuleBased.html b/broker-plugins/management-http/src/main/java/resources/accesscontrolprovider/showRuleBased.html
new file mode 100644
index 0000000..d527d30
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/resources/accesscontrolprovider/showRuleBased.html
@@ -0,0 +1,37 @@
+<!--
+ -
+ - 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="RuleBasedAclProvider">
+
+    <div class="clear">
+        <div class="formLabel-labelCell">Default Result:</div>
+        <div class="defaultResult"></div>
+    </div>
+    <div class="clear"></div>
+    <div data-dojo-type="dijit/TitlePane"
+         data-dojo-props="title: 'Access Control Rules'" class="accessControlRules">
+        <div class="rules"></div>
+    </div>
+    <div class="alignRight">
+        <button data-dojo-type="dijit/form/Button" class="load">Load</button>
+        <button data-dojo-type="dijit/form/Button" class="extract">Extract</button>
+    </div>
+    <div class="clear"></div>
+</div>

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/03b08426/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 b2577c7..09765a5 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
@@ -814,3 +814,15 @@ td.advancedSearchField, col.autoWidth {
 {
     margin-bottom: 0.2em !important;
 }
+
+.accessControlProviders .field-selected { width: 2em; }
+.accessControlProviders .field-name { width: 20%; }
+.accessControlProviders .field-state { width: 20%; }
+.accessControlProviders .field-type { width: auto; }
+.accessControlProviders .field-priority { width: 20% }
+
+.accessControlRules .field-identity { width: 20%; }
+.accessControlRules .field-objectType { width: 20%; }
+.accessControlRules .field-operation { width: 10%; }
+.accessControlRules .field-outcome { width: 10%; }
+.accessControlRules .field-attributes { width: auto; }

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/03b08426/broker-plugins/management-http/src/main/java/resources/js/qpid/common/ResourceWidget.js
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/common/ResourceWidget.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/common/ResourceWidget.js
index efd72b4..a0f84bc 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/common/ResourceWidget.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/common/ResourceWidget.js
@@ -136,6 +136,10 @@ define(["dojo/_base/declare",
                     }
                     this.inherited(arguments);
                 },
+                reset: function () {
+                    this.inherited(arguments);
+                    this.uploader.reset();
+                },
                 _fileChanged: function (evt)
                 {
                     var file = this.uploader.domNode.children[0].files[0];

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/03b08426/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 948129b..91272b7 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
@@ -1020,5 +1020,38 @@ define(["dojo/_base/xhr",
                 }
             });
         };
+
+        util.updateSyncDStore = function (dstore, data, idProperty) {
+            if (data)
+            {
+                for (var i = 0; i < data.length; i++)
+                {
+                    dstore.putSync(data[i]);
+                }
+            }
+            var objectsToRemove = [];
+            dstore.fetchSync()
+                .forEach(function (object) {
+                    if (object)
+                    {
+                        if (data)
+                        {
+                            for (var i = 0; i < data.length; i++)
+                            {
+                                if (data[i][idProperty] === object[idProperty])
+                                {
+                                    return;
+                                }
+                            }
+                        }
+                        objectsToRemove.push(object[idProperty]);
+                    }
+                });
+            for (var i = 0 ; i < objectsToRemove.length; i++)
+            {
+                dstore.removeSync(objectsToRemove[i]);
+            }
+        };
+
         return util;
     });

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/03b08426/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AccessControlProvider.js
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AccessControlProvider.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AccessControlProvider.js
index 7e34988..0a5b921 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AccessControlProvider.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AccessControlProvider.js
@@ -20,6 +20,7 @@
  */
 define(["dojo/parser",
         "dojo/query",
+        "dojo/_base/lang",
         "dojo/_base/connect",
         "qpid/common/properties",
         "qpid/common/updater",
@@ -35,6 +36,7 @@ define(["dojo/parser",
         "dojo/domReady!"],
     function (parser,
               query,
+              lang,
               connect,
               properties,
               updater,
@@ -77,15 +79,17 @@ define(["dojo/parser",
                         event.stop(evt);
                         that.deleteAccessControlProvider();
                     });
+
+                    that.accessControlProviderUpdater.update(function ()
+                    {
+                        updater.add(that.accessControlProviderUpdater);
+                    });
                 });
         };
 
         AccessControlProvider.prototype.close = function ()
         {
-            if (this.accessControlProviderUpdater.details)
-            {
-                this.accessControlProviderUpdater.details.close();
-            }
+           updater.remove(this.accessControlProviderUpdater);
         };
 
         AccessControlProvider.prototype.deleteAccessControlProvider = function ()
@@ -115,34 +119,7 @@ define(["dojo/parser",
             this.type = query(".type", node)[0];
             this.state = query(".state", node)[0];
             this.priority = query(".priority", node)[0];
-
-            var that = this;
-
-            this.management.load(this.modelObj, {excludeInheritedContext: true})
-                .then(function (data)
-                {
-                    that.accessControlProviderData = data;
-
-                    util.flattenStatistics(that.accessControlProviderData);
-
-                    that.updateHeader();
-
-                    var ui = that.accessControlProviderData.type;
-                    require(["qpid/management/accesscontrolprovider/" + ui], function (SpecificProvider)
-                    {
-                        that.details = new SpecificProvider(query(".providerDetails",
-                            node)[0], that.modelObj, that.controller, aclTab);
-                    });
-                }, function (error)
-                {
-                    util.tabErrorHandler(error, {
-                        updater: that,
-                        contentPane: that.contentPane,
-                        tabContainer: that.controller.tabContainer,
-                        name: that.modelObj.name,
-                        category: "Access Control Provider"
-                    });
-                });
+            this.providerDetailsDiv = query(".providerDetails", node)[0];
         }
 
         AccessControlProviderUpdater.prototype.updateHeader = function ()
@@ -154,5 +131,52 @@ define(["dojo/parser",
 
         };
 
+        AccessControlProviderUpdater.prototype.update = function (callback) {
+            if (!this.contentPane.selected && !callback)
+            {
+                return;
+            }
+
+            this.management.load(this.modelObj)
+                .then(lang.hitch(this, function (data) {
+                        this._update(data, callback);
+                    }),
+                    lang.hitch(this, function (error) {
+                        util.tabErrorHandler(error, {
+                            updater: this,
+                            contentPane: this.contentPane,
+                            tabContainer: this.controller.tabContainer,
+                            name: this.modelObj.name,
+                            category: "Access Control Provider"
+                        });
+                    }));
+
+        };
+
+        AccessControlProviderUpdater.prototype._update = function (data, callback) {
+            this.accessControlProviderData = data;
+            this.updateHeader();
+            if (this.details)
+            {
+                this.details.update(data);
+            }
+            else
+            {
+                require(["qpid/management/accesscontrolprovider/" + data.type],
+                    lang.hitch(this, function (SpecificProvider) {
+                        this.details = new SpecificProvider(this.providerDetailsDiv,
+                            this.modelObj,
+                            this.controller);
+
+                        this.details.update(data);
+
+                        if (callback)
+                        {
+                            callback();
+                        }
+                    }));
+            }
+        };
+
         return AccessControlProvider;
     });

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/03b08426/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 7a96baa..344d455 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
@@ -110,7 +110,7 @@ define(["dojo/parser",
                     registry.byNode(deleteQueueButton).on("click", function (evt)
                     {
                         that._deleteSelectedItems(that.vhostUpdater.queuesGrid,
-                                                  {type: "queue", parent: this.modelObj},
+                                                  {type: "queue", parent: that.modelObj},
                                                   "delete", "queue");
                     });
 
@@ -202,6 +202,28 @@ define(["dojo/parser",
                         editVirtualHost.show(that.management, that.modelObj);
                     });
 
+                    var addVirtualHostAccessControlProviderButton = registry.byNode(query(
+                        ".addVirtualHostAccessControlProvider",
+                        contentPane.containerNode)[0]);
+                    addVirtualHostAccessControlProviderButton.on("click", function () {
+                        require(["qpid/management/addAccessControlProvider"],
+                            function (addAccessControlProvider) {
+                                addAccessControlProvider.show(that.management, that.modelObj);
+                            });
+                    });
+
+                    var deleteVirtualHostAccessControlProviderButton = registry.byNode(query(
+                        ".deleteVirtualHostAccessControlProvider",
+                        contentPane.containerNode)[0]);
+                    deleteVirtualHostAccessControlProviderButton.on("click", function () {
+                        that._deleteSelectedItems(that.vhostUpdater.virtualHostAccessControlProviderGrid,
+                            {
+                                type: "virtualhostaccesscontrolprovider",
+                                parent: that.modelObj
+                            },
+                            "delete", "virtual host access control provider");
+                    });
+
                     that.vhostUpdater.update(function ()
                     {
                         updater.add(that.vhostUpdater);
@@ -534,6 +556,41 @@ define(["dojo/parser",
                 }
             }));
 
+            this.virtualHostAccessControlProviderGrid = new CustomGrid({
+                detectChanges: true,
+                rowsPerPage: 10,
+                transformer: util.queryResultToObjects,
+                management: this.management,
+                parentObject: this.modelObj,
+                category: "VirtualHostAccessControlProvider",
+                selectClause: "id, name, state, type, priority",
+                orderBy: "name",
+                selectionMode: 'none',
+                deselectOnRefresh: false,
+                allowSelectAll: true,
+                columns: [
+                    {
+                        field: "selected",
+                        label: 'All',
+                        selector: 'checkbox'
+                    },  {
+                        label: "Name",
+                        field: "name"
+                    }, {
+                        label: "State",
+                        field: "state"
+                    }, {
+                        label: "Type",
+                        field: "type"
+                    }, {
+                        label: "Priority",
+                        field: "priority"
+                    }
+                ]
+            }, findNode("virtualHostAccessControlProviders"));
+            this.virtualHostAccessControlProviderGrid.on('rowBrowsed', function(event){controller.showById(event.id);});
+            this.virtualHostAccessControlProviderGrid.startup();
+
         }
 
         Updater.prototype.update = function (callback)
@@ -617,6 +674,7 @@ define(["dojo/parser",
                 this.queuesGrid.updateData();
                 this.exchangesGrid.updateData();
                 this.virtualHostLoggersGrid.updateData();
+                this.virtualHostAccessControlProviderGrid.updateData();
             }
 
             if (this.details)
@@ -636,7 +694,7 @@ define(["dojo/parser",
                         thisObj.details.update(thisObj.vhostData);
                     });
             }
-            this._updateDStore(this._policyStore, this.vhostData.nodeAutoCreationPolicies || [], "pattern");
+            util.updateSyncDStore(this._policyStore, this.vhostData.nodeAutoCreationPolicies || [], "pattern");
         };
 
         Updater.prototype._updateHeader = function ()
@@ -705,37 +763,5 @@ define(["dojo/parser",
             return connections;
         };
 
-        Updater.prototype._updateDStore = function (dstore, data, idProperty) {
-            if (data)
-            {
-                for (var i = 0; i < data.length; i++)
-                {
-                    dstore.putSync(data[i]);
-                }
-            }
-            var objectsToRemove = [];
-            dstore.fetchSync()
-                .forEach(function (object) {
-                    if (object)
-                    {
-                        if (data)
-                        {
-                            for (var i = 0; i < data.length; i++)
-                            {
-                                if (data[i][idProperty] === object[idProperty])
-                                {
-                                    return;
-                                }
-                            }
-                        }
-                        objectsToRemove.push(object[idProperty]);
-                    }
-                });
-            for (var i = 0 ; i < objectsToRemove.length; i++)
-            {
-                dstore.removeSync(objectsToRemove[i]);
-            }
-        };
-
         return VirtualHost;
     });

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/03b08426/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/AclFile.js
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/AclFile.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/AclFile.js
index c9064a1..70f3a5f 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/AclFile.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/AclFile.js
@@ -18,128 +18,46 @@
  * under the License.
  *
  */
-define(["dojo/_base/xhr",
-        "dojo/_base/lang",
+define(["dojo/_base/lang",
         "dojo/dom",
         "dojo/parser",
         "dojo/query",
         "dojo/dom-construct",
-        "dojo/_base/connect",
-        "dojo/_base/window",
-        "dojo/_base/event",
-        "dojo/_base/json",
-        "dojo/_base/lang",
         "dijit/registry",
         "dojox/html/entities",
-        "qpid/common/util",
-        "qpid/common/properties",
-        "qpid/common/updater",
-        "qpid/common/UpdatableStore",
-        "dojox/grid/EnhancedGrid",
-        "dojox/grid/enhanced/plugins/Pagination",
-        "dojox/grid/enhanced/plugins/IndirectSelection",
-        "dojox/validate/us",
-        "dojox/validate/web",
-        "dijit/Dialog",
-        "dijit/form/TextBox",
-        "dijit/form/ValidationTextBox",
-        "dijit/form/TimeTextBox",
+        "dojo/text!accesscontrolprovider/showAclFile.html",
         "dijit/form/Button",
-        "dijit/form/Form",
-        "dijit/form/DateTextBox",
         "dojo/domReady!"],
-    function (xhr,
-              lang,
+    function (lang,
               dom,
               parser,
               query,
               construct,
-              connect,
-              win,
-              event,
-              json,
-              lang,
               registry,
               entities,
-              util,
-              properties,
-              updater,
-              UpdatableStore,
-              EnhancedGrid)
+              template)
     {
-        function AclFile(containerNode, aclProviderObj, controller, tabObject)
+        function AclFile(containerNode, aclProviderObj, controller)
         {
-            var node = construct.create("div", null, containerNode, "last");
-            this.modelObj = aclProviderObj;
-            var that = this;
-            this.name = aclProviderObj.name;
-            xhr.get({
-                url: "accesscontrolprovider/showAclFile.html",
-                load: function (data)
-                {
-                    node.innerHTML = data;
-                    parser.parse(node)
-                        .then(function (instances)
-                        {
-                            that.groupDatabaseUpdater = new AclFileUpdater(node, tabObject);
-
-                            updater.add(that.groupDatabaseUpdater);
-
-                            that.groupDatabaseUpdater.update();
-                        });
-
-                }
-            });
-        }
-
-        AclFile.prototype.close = function ()
-        {
-            updater.remove(this.groupDatabaseUpdater);
-        };
-
-        function AclFileUpdater(node, tabObject)
-        {
-            this.tabObject = tabObject;
-            this.contentPane = tabObject.contentPane;
-            var aclProviderObj = tabObject.modelObj;
-            var controller = tabObject.controller;
-            this.controller = controller;
             this.modelObj = aclProviderObj;
             this.management = controller.management;
-            this.name = aclProviderObj.name;
-            this.path = query(".path", node)[0];
-            this.reloadButton = registry.byNode(query(".reload", node)[0]);
-            this.reloadButton.on("click", lang.hitch(this, this.reload));
+            var node = construct.create("div", null, containerNode, "last");
+            node.innerHTML = template;
+            parser.parse(containerNode)
+                .then(lang.hitch(this, lang.hitch(this, function (instances)
+                {
+                    this.path = query(".path", node)[0];
+                    this.reloadButton = registry.byNode(query(".reload", node)[0]);
+                    this.reloadButton.on("click", lang.hitch(this, this.reload));
+                })));
         }
 
-        AclFileUpdater.prototype.update = function ()
+        AclFile.prototype.update = function (data)
         {
-            if (!this.contentPane.selected)
-            {
-                return;
-            }
-
-            var that = this;
-
-            this.management.load(this.modelObj, {excludeInheritedContext: true})
-                .then(function (data)
-                {
-                    that.aclProviderData = data;
-                    that.path.innerHTML = entities.encode(String(that.aclProviderData.path));
-                }, function (error)
-                {
-                    util.tabErrorHandler(error, {
-                        updater: that,
-                        contentPane: that.tabObject.contentPane,
-                        tabContainer: that.tabObject.controller.tabContainer,
-                        name: that.modelObj.name,
-                        category: "Access Control Provider"
-                    });
-                });
-
+            this.path.innerHTML = entities.encode(String(data.path));
         };
 
-        AclFileUpdater.prototype.reload = function ()
+        AclFile.prototype.reload = function ()
         {
             this.reloadButton.set("disabled", true);
             var parentModelObj = this.modelObj;

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/03b08426/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/RuleBased.js
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/RuleBased.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/RuleBased.js
new file mode 100644
index 0000000..b1c17f7
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/RuleBased.js
@@ -0,0 +1,201 @@
+/*
+ *
+ * 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/dom",
+        "dojo/parser",
+        "dojo/query",
+        "dojo/dom-construct",
+        "dijit/registry",
+        "dojox/html/entities",
+        "dojo/text!accesscontrolprovider/showRuleBased.html",
+        "dgrid/Grid",
+        "dgrid/Keyboard",
+        "dgrid/Selection",
+        "dgrid/extensions/Pagination",
+        "dgrid/extensions/ColumnResizer",
+        "dgrid/extensions/DijitRegistry",
+        "dstore/Memory",
+        "dstore/Trackable",
+        "qpid/common/util",
+        "dijit/TitlePane",
+        "dijit/form/Button",
+        "dojo/domReady!"],
+    function (declare,
+              lang,
+              dom,
+              parser,
+              query,
+              construct,
+              registry,
+              entities,
+              template,
+              Grid,
+              Keyboard,
+              Selection,
+              Pagination,
+              ColumnResizer,
+              DijitRegistry,
+              MemoryStore,
+              TrackableStore,
+              util) {
+        function RuleBased(containerNode, aclProviderObj, controller)
+        {
+            this.modelObj = aclProviderObj;
+            this.management = controller.management;
+            var node = construct.create("div", null, containerNode, "last");
+            node.innerHTML = template;
+            parser.parse(containerNode)
+                .then(lang.hitch(this, function (instances) {
+
+                    this.defaultResult = query(".defaultResult", node)[0];
+
+                    var Store = MemoryStore.createSubclass(TrackableStore);
+                    this._rulesStore = new Store({
+                        data: [],
+                        idProperty: "id"
+                    });
+
+                    var GridConstructor = declare([Grid,
+                                                   Keyboard,
+                                                   Selection,
+                                                   Pagination,
+                                                   ColumnResizer,
+                                                   DijitRegistry]);
+                    this._rulesGrid = new GridConstructor({
+                        rowsPerPage: 20,
+                        selectionMode: 'none',
+                        deselectOnRefresh: false,
+                        allowSelectAll: true,
+                        cellNavigation: true,
+                        className: 'dgrid-autoheight',
+                        pageSizeOptions: [10, 20, 30, 40, 50, 100],
+                        adjustLastColumn: true,
+                        collection: this._rulesStore,
+                        highlightRow: function () {
+                        },
+                        columns: [
+                            {
+                                label: 'Identity',
+                                field: "identity"
+                            }, {
+                                label: "Object Type",
+                                field: "objectType"
+                            }, {
+                                label: "Operation",
+                                field: "operation"
+                            }, {
+                                label: "Outcome",
+                                field: "outcome"
+                            }, {
+                                label: "Attributes",
+                                field: "attributes",
+                                sortable: false,
+                                formatter: function (value, object) {
+                                    var markup = "";
+                                    if (value)
+                                    {
+                                        markup = "<div class='keyValuePair'>";
+                                        for (var key in value)
+                                        {
+                                            if (value.hasOwnProperty(key))
+                                            {
+                                                markup += "<div>" + entities.encode(String(key)) + "="
+                                                          + entities.encode(String(value[key])) + "</div>";
+                                            }
+                                        }
+                                        markup += "</div>"
+                                    }
+                                    return markup;
+                                }
+                            }
+                        ]
+                    }, query(".rules", node)[0]);
+
+                    this._rulesGrid.startup();
+
+                    this.loadButton = registry.byNode(query(".load", node)[0]);
+                    this.loadButton.on("click", lang.hitch(this, this.load));
+
+                    this.extractButton = registry.byNode(query(".extract", node)[0]);
+                    this.extractButton.on("click", lang.hitch(this, this.extractRules));
+                }));
+        }
+
+        RuleBased.prototype.update = function (data) {
+            this.defaultResult.innerHTML = entities.encode(String(data.defaultResult));
+
+            var rules = [];
+            if (data && data.rules)
+            {
+                for (var i = 0; i < data.rules.length; i++)
+                {
+                    var rule = {id: Number(i)};
+                    lang.mixin(rule, data.rules[i]);
+                    rules.push(rule);
+                }
+            }
+
+            util.updateSyncDStore(this._rulesStore, rules, "id");
+        };
+
+        RuleBased.prototype.load = function () {
+            this.loadButton.set("disabled", true);
+            if (this.loadForm)
+            {
+                this.loadForm.show();
+            }
+            else
+            {
+                require(["qpid/management/accesscontrolprovider/rulebased/LoadForm"],
+                    lang.hitch(this, function (LoadForm) {
+                        this.loadForm = new LoadForm();
+                        this.loadForm.on("load", lang.hitch(this, this.loadFromFile));
+                        this.loadForm.show();
+                    }));
+            }
+        };
+
+        RuleBased.prototype.loadFromFile = function (event) {
+            this.management.update({
+                type: this.modelObj.type,
+                name: "loadFromFile",
+                parent: this.modelObj
+            }, {path: event.path})
+                .then(lang.hitch(this, function(){
+                    this.loadForm.hide();
+                    }),
+                      this.management.xhrErrorHandler)
+                .always(lang.hitch(this, function () {
+                    this.loadButton.set("disabled", false);
+                }));
+        };
+
+        RuleBased.prototype.extractRules = function () {
+            this.management.downloadIntoFrame({
+                type: this.modelObj.type,
+                name: "extractRules",
+                parent: this.modelObj
+            });
+        };
+
+        return RuleBased;
+    });

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/03b08426/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/rulebased/LoadForm.js
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/rulebased/LoadForm.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/rulebased/LoadForm.js
new file mode 100644
index 0000000..364caf6
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/rulebased/LoadForm.js
@@ -0,0 +1,103 @@
+/*
+ *
+ * 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!accesscontrolprovider/rulebased/LoadForm.html",
+        "qpid/common/ResourceWidget",
+        "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) {
+
+        return declare("qpid.management.accesscontrolprovider.rulebased.LoadForm",
+            [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
+                 */
+                path: null,
+                loadDialog: null,
+                loadForm: null,
+                okButton: null,
+                cancelButton: null,
+                warning: null,
+
+                postCreate: function () {
+                    this.inherited(arguments);
+                    this.cancelButton.on("click", lang.hitch(this, this._onCancel));
+                    this.okButton.on("click", lang.hitch(this, this._onFormSubmit));
+
+                    var reader = window.FileReader ? new FileReader() : undefined;
+                    if (!reader)
+                    {
+                        this.warning.innerHTML = "File upload requires a more recent browser with HTML5 support";
+                        this.warning.className = this.warning.className.replace("hidden", "");
+                    }
+                },
+                show: function()
+                {
+                    this.path.reset();
+                    this.loadDialog.show();
+                },
+                hide: function()
+                {
+                    this.loadDialog.hide();
+                },
+                _onCancel: function () {
+                    this.emit("cancel");
+                    this.hide();
+                },
+                _onFormSubmit: function () {
+                    if (this.loadForm.validate())
+                    {
+                        var path = this.path.get("value");
+                        this.emit("load", {path: path});
+                    }
+                    else
+                    {
+                        alert('Form contains invalid data.  Please correct first');
+                    }
+
+                    return false;
+                }
+            });
+    });

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/03b08426/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/rulebased/add.js
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/rulebased/add.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/rulebased/add.js
new file mode 100644
index 0000000..9e4558e
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/rulebased/add.js
@@ -0,0 +1,52 @@
+/*
+ *
+ * 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/dom", "qpid/common/util", "dijit/registry", "dijit/form/FilteringSelect"],
+    function (dom, util, registry)
+    {
+        return {
+            show: function (data)
+            {
+                var that = this;
+                util.parseHtmlIntoDiv(data.containerNode,
+                    "accesscontrolprovider/rulebased/add.html",
+                    function ()
+                    {
+                        that._postParse(data);
+                    });
+            },
+            _postParse: function (data)
+            {
+                var validValues = data.metadata.getMetaData(data.category, data.type).attributes.defaultResult.validValues;
+                var validValueStore = util.makeTypeStore(validValues);
+
+                var defaultResult = registry.byId("addAccessControlProvider.ruleBased.defaultResult");
+                defaultResult.set("store", validValueStore);
+
+                util.applyToWidgets(data.containerNode,
+                    data.category,
+                    data.type,
+                    data.initialData,
+                    data.metadata,
+                    data.effectiveData);
+
+            }
+        };
+    });

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/03b08426/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAccessControlProvider.js
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAccessControlProvider.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAccessControlProvider.js
index 7eef299..dd5a2fa 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAccessControlProvider.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAccessControlProvider.js
@@ -86,11 +86,21 @@ define(["dojo/_base/lang",
             this.management = management;
             this.modelObj = modelObj;
             this.accessControlProviderForm.reset();
-            this.supportedAccessControlProviderTypes = management.metadata.getTypesForCategory("AccessControlProvider");
+            this.category =
+                modelObj && (modelObj.type === "virtualhost" || modelObj.type === "virtualhostaccesscontrolprovider")
+                    ? "VirtualHostAccessControlProvider"
+                    : "AccessControlProvider";
+            this.supportedAccessControlProviderTypes = management.metadata.getTypesForCategory(this.category);
             this.supportedAccessControlProviderTypes.sort();
             var accessControlProviderTypeStore = util.makeTypeStore(this.supportedAccessControlProviderTypes);
             this.accessControlProviderType.set("store", accessControlProviderTypeStore);
-            util.applyMetadataToWidgets(dom.byId("addAccessControlProvider.contentPane"), "AccessControlProvider", "AllowAll", management.metadata);
+            if (this.supportedAccessControlProviderTypes.length > 0)
+            {
+                util.applyMetadataToWidgets(dom.byId("addAccessControlProvider.contentPane"),
+                    this.category,
+                    this.supportedAccessControlProviderTypes[0],
+                    management.metadata);
+            }
 
             this.dialog.show();
         },
@@ -112,7 +122,7 @@ define(["dojo/_base/lang",
                 var accessControlProviderData = util.getFormWidgetValues(this.accessControlProviderForm,
                     this.initialData);
                 var that = this;
-                this.management.create("accesscontrolprovider", this.modelObj, accessControlProviderData)
+                this.management.create(this.category, this.modelObj, accessControlProviderData)
                     .then(function (x)
                     {
                         that.dialog.hide();
@@ -128,7 +138,7 @@ define(["dojo/_base/lang",
             this._typeChanged(type,
                 this.accessControlProviderTypeFieldsContainer,
                 "qpid/management/accesscontrolprovider/",
-                "AccessControlProvider");
+                this.category);
         },
         _destroyTypeFields: function (typeFieldsContainer)
         {
@@ -155,7 +165,9 @@ define(["dojo/_base/lang",
                             parent: that,
                             data: that.initialData,
                             effectiveData: that.effectiveData,
-                            metadata: that.management.metadata
+                            metadata: that.management.metadata,
+                            category: category,
+                            type: type
                         });
                         util.applyMetadataToWidgets(typeFieldsContainer, category, type, that.management.metadata);
                     }

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/03b08426/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js
index ac8a695..83a152c 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js
@@ -91,6 +91,7 @@ define(["dojo/dom",
             keystore: KeyStore,
             truststore: TrustStore,
             accesscontrolprovider: AccessControlProvider,
+            virtualhostaccesscontrolprovider: AccessControlProvider,
             port: Port,
             plugin: Plugin,
             virtualhostnode: VirtualHostNode,

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/03b08426/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..f87f61c 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
@@ -185,7 +185,7 @@ define(["dojo/_base/declare",
                 cloneButtonTooltip: null,
                 deleteButtonTooltip: null,
                 searchForm: null,
-                exportButton: null,
+                extractButton: null,
                 exportButtonTooltip: null,
 
                 /**
@@ -245,7 +245,7 @@ define(["dojo/_base/declare",
                     this.saveButton.on("click", lang.hitch(this, this._saveQuery));
                     this.cloneButton.on("click", lang.hitch(this, this._cloneQuery));
                     this.deleteButton.on("click", lang.hitch(this, this._deleteQuery));
-                    this.exportButton.on("click", lang.hitch(this, this._exportQueryResults));
+                    this.extractButton.on("click", lang.hitch(this, this._exportQueryResults));
 
                     this._ownQuery = !this.preference
                                      || !this.preference.owner
@@ -253,7 +253,7 @@ define(["dojo/_base/declare",
                     var newQuery = !this.preference || !this.preference.createdDate;
                     this.saveButton.set("disabled", !this._ownQuery);
                     this.deleteButton.set("disabled", !this._ownQuery || newQuery);
-                    this.exportButton.set("disabled", true);
+                    this.extractButton.set("disabled", true);
 
                     if (!this._ownQuery)
                     {
@@ -592,7 +592,7 @@ define(["dojo/_base/declare",
                 _queryCompleted: function (e)
                 {
                     this._buildColumnsIfHeadersChanged(e.data);
-                    this.exportButton.set("disabled", !(e.data.total && e.data.total > 0));
+                    this.extractButton.set("disabled", !(e.data.total && e.data.total > 0));
                 },
                 _buildColumnsIfHeadersChanged: function (data)
                 {

http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/03b08426/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 beda11e..62bb2fd 100644
--- a/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html
+++ b/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html
@@ -140,6 +140,16 @@
             <button data-dojo-type="dijit.form.Button" class="deleteVirtualHostLogger">Delete Virtual Host Logger</button>
         </div>
         <br/>
+        <div data-dojo-type="dijit.TitlePane"
+             data-dojo-props="title: 'Virtual Host Access Control Providers'"
+             class="accessControlProviders">
+            <div class="virtualHostAccessControlProviders"></div>
+            <button data-dojo-type="dijit.form.Button"
+                    class="addVirtualHostAccessControlProvider">Add Access Control Provider</button>
+            <button data-dojo-type="dijit.form.Button"
+                    class="deleteVirtualHostAccessControlProvider">Delete Access Control Provider</button>
+        </div>
+        <br/>
     </div>
 </div>
 


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