diff options
author | Robert Gemmell <robbie@apache.org> | 2012-07-20 14:46:19 +0000 |
---|---|---|
committer | Robert Gemmell <robbie@apache.org> | 2012-07-20 14:46:19 +0000 |
commit | 373c004d206575dd21d37ee9cba1cea9ef66b881 (patch) | |
tree | 1336bc51ff7c1a58c7d5b7ca7ea30fc04534a961 | |
parent | 3595a98e8527e16ab078dfe45b602dc42d21430b (diff) | |
download | qpid-python-373c004d206575dd21d37ee9cba1cea9ef66b881.tar.gz |
QPID-4149: Add REST functionality to delete exchanges, queues and bindings, add queue/exchange/binding delete operations into web UI
Applied patch from Oleksandr Rudyy <orudyy@gmail.com> and myself.
merged from trunk r1363298
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/0.18@1363810 13f79535-47bb-0310-9956-ffa450edef68
18 files changed, 450 insertions, 59 deletions
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js index d7917b640e..08fdf5c99b 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js @@ -18,8 +18,8 @@ * under the License. * */ -define([], - function () { +define(["dojo/_base/xhr"], + function (xhr) { var util = {}; if (Array.isArray) { util.isArray = function (object) { @@ -52,5 +52,69 @@ define([], } } }; + + util.isReservedExchangeName = function(exchangeName) + { + return exchangeName == null || exchangeName == "" || "<<default>>" == exchangeName || exchangeName.indexOf("amq.") == 0 || exchangeName.indexOf("qpid.") == 0; + }; + + util.deleteGridSelections = function(updater, gridName, url, confirmationMessageStart) + { + var grid = updater[gridName].grid; + var data = grid.selection.getSelected(); + if(data.length) + { + var confirmationMessage = null; + if (data.length == 1) + { + confirmationMessage = confirmationMessageStart + " '" + data[0].name + "'?"; + } + else + { + var names = ''; + for(var i = 0; i<data.length; i++) + { + if (names) + { + names += ', '; + } + names += "\""+ data[i].name + "\""; + } + confirmationMessage = confirmationMessageStart + "s " + names + "?"; + } + if(confirm(confirmationMessage)) + { + var i, queryParam; + for(i = 0; i<data.length; i++) + { + if(queryParam) + { + queryParam += "&"; + } + else + { + queryParam = "?"; + } + queryParam += "id=" + data[i].id; + } + var query = url + queryParam; + var success = true + var failureReason = ""; + xhr.del({url: query, sync: true, handleAs: "json"}).then( + function(data) + { + grid.setQuery({id: "*"}); + grid.selection.deselectAll(); + updater.update(); + }, + function(error) {success = false; failureReason = error;}); + if(!success ) + { + alert("Error:" + failureReason); + } + } + } + } + return util; });
\ No newline at end of file diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Exchange.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Exchange.js index 0450ef53ac..37bae1ef8e 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Exchange.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Exchange.js @@ -29,8 +29,9 @@ define(["dojo/_base/xhr", "qpid/common/formatter", "qpid/common/UpdatableStore", "qpid/management/addBinding", + "dojox/grid/EnhancedGrid", "dojo/domReady!"], - function (xhr, parser, query, connect, registry, properties, updater, util, formatter, UpdatableStore, addBinding) { + function (xhr, parser, query, connect, registry, properties, updater, util, formatter, UpdatableStore, addBinding, EnhancedGrid) { function Exchange(name, parent, controller) { this.name = name; @@ -82,6 +83,27 @@ define(["dojo/_base/xhr", exchange: that.getExchangeName()}); }); + var deleteBindingButton = query(".deleteBindingButton", contentPane.containerNode)[0]; + connect.connect(registry.byNode(deleteBindingButton), "onClick", + function(evt){ + that.deleteBindings(); + }); + + var isStandard = util.isReservedExchangeName(that.name); + var deleteExchangeButton = query(".deleteExchangeButton", contentPane.containerNode)[0]; + var node = registry.byNode(deleteExchangeButton); + if(isStandard) + { + node.set('disabled', true); + } + else + { + connect.connect(node, "onClick", + function(evt){ + that.deleteExchange(); + }); + } + }}); }; @@ -89,6 +111,15 @@ define(["dojo/_base/xhr", updater.remove( this.exchangeUpdater ); }; + Exchange.prototype.deleteBindings = function() + { + util.deleteGridSelections( + this.exchangeUpdater, + "bindingsGrid", + "rest/binding/"+ encodeURIComponent(this.getVirtualHostName()) + "/" + encodeURIComponent(this.name), + "Are you sure you want to delete binding for queue"); + } + function ExchangeUpdater(containerNode, exchangeObj, controller) { var that = this; @@ -138,7 +169,21 @@ define(["dojo/_base/xhr", [ { name: "Queue", field: "queue", width: "90px"}, { name: "Binding Key", field: "name", width: "120px"}, { name: "Arguments", field: "argumentString", width: "100%"} - ]); + ], null, { + keepSelection: true, + plugins: { + pagination: { + pageSizes: ["10", "25", "50", "100"], + description: true, + sizeSwitch: true, + pageStepper: true, + gotoButton: true, + maxPageStep: 4, + position: "bottom" + }, + indirectSelection: true + + }}, EnhancedGrid); }); @@ -224,6 +269,23 @@ define(["dojo/_base/xhr", }); }; + Exchange.prototype.deleteExchange = function() { + if(confirm("Are you sure you want to delete exchange '" +this.name+"'?")) { + var query = "rest/exchange/"+ encodeURIComponent(this.getVirtualHostName()) + "/" + encodeURIComponent(this.name); + this.success = true + var that = this; + xhr.del({url: query, sync: true, handleAs: "json"}).then( + function(data) { + that.contentPane.onClose() + that.controller.tabContainer.removeChild(that.contentPane); + that.contentPane.destroyRecursive(); + }, + function(error) {that.success = false; that.failureReason = error;}); + if(!this.success ) { + alert("Error:" + this.failureReason); + } + } + } return Exchange; }); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js index 3ac8b0057d..b812ca2a0b 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js @@ -157,6 +157,12 @@ define(["dojo/_base/xhr", queue: that.getQueueName()}); }); + var deleteQueueButton = query(".deleteQueueButton", contentPane.containerNode)[0]; + connect.connect(registry.byNode(deleteQueueButton), "onClick", + function(evt){ + event.stop(evt); + that.deleteQueue(); + }); }}); @@ -458,6 +464,23 @@ define(["dojo/_base/xhr", }); }; + Queue.prototype.deleteQueue = function() { + if(confirm("Are you sure you want to delete queue '" +this.name+"'?")) { + var query = "rest/queue/"+ encodeURIComponent(this.getVirtualHostName()) + "/" + encodeURIComponent(this.name); + this.success = true + var that = this; + xhr.del({url: query, sync: true, handleAs: "json"}).then( + function(data) { + that.contentPane.onClose() + that.controller.tabContainer.removeChild(that.contentPane); + that.contentPane.destroyRecursive(); + }, + function(error) {that.success = false; that.failureReason = error;}); + if(!this.success ) { + alert("Error:" + this.failureReason); + } + } + } return Queue; }); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js index ce24145930..957f2381cf 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js @@ -30,8 +30,9 @@ define(["dojo/_base/xhr", "qpid/common/UpdatableStore", "qpid/management/addQueue", "qpid/management/addExchange", + "dojox/grid/EnhancedGrid", "dojo/domReady!"], - function (xhr, parser, query, connect, registry, properties, updater, util, formatter, UpdatableStore, addQueue, addExchange) { + function (xhr, parser, query, connect, registry, properties, updater, util, formatter, UpdatableStore, addQueue, addExchange, EnhancedGrid) { function VirtualHost(name, parent, controller) { this.name = name; @@ -66,8 +67,31 @@ define(["dojo/_base/xhr", var addQueueButton = query(".addQueueButton", contentPane.containerNode)[0]; connect.connect(registry.byNode(addQueueButton), "onClick", function(evt){ addQueue.show(that.name) }); + var deleteQueueButton = query(".deleteQueueButton", contentPane.containerNode)[0]; + connect.connect(registry.byNode(deleteQueueButton), "onClick", + function(evt){ + util.deleteGridSelections( + that.vhostUpdater, + "queuesGrid", + "rest/queue/"+ encodeURIComponent(that.name), + "Are you sure you want to delete queue"); + } + ); + var addExchangeButton = query(".addExchangeButton", contentPane.containerNode)[0]; connect.connect(registry.byNode(addExchangeButton), "onClick", function(evt){ addExchange.show(that.name) }); + + var deleteExchangeButton = query(".deleteExchangeButton", contentPane.containerNode)[0]; + connect.connect(registry.byNode(deleteExchangeButton), "onClick", + function(evt) + { + util.deleteGridSelections( + that.vhostUpdater, + "exchangesGrid", + "rest/exchange/"+ encodeURIComponent(that.name), + "Are you sure you want to delete exchange"); + } + ); }}); }; @@ -76,7 +100,6 @@ define(["dojo/_base/xhr", updater.remove( this.vhostUpdater ); }; - function Updater(node, vhost, controller) { @@ -123,6 +146,22 @@ define(["dojo/_base/xhr", // flatten statistics into attributes util.flattenStatistics( that.vhostData ); + var gridProperties = { + keepSelection: true, + plugins: { + pagination: { + pageSizes: ["10", "25", "50", "100"], + description: true, + sizeSwitch: true, + pageStepper: true, + gotoButton: true, + maxPageStep: 4, + position: "bottom" + }, + indirectSelection: true + + }}; + that.updateHeader(); that.queuesGrid = new UpdatableStore(that.vhostData.queues, findNode("queues"), [ { name: "Name", field: "name", width: "90px"}, @@ -138,24 +177,24 @@ define(["dojo/_base/xhr", var queueName = obj.dataStore.getValue(theItem,"name"); controller.show("queue", queueName, vhost); }); - } ); + } , gridProperties, EnhancedGrid); that.exchangesGrid = new UpdatableStore(that.vhostData.exchanges, findNode("exchanges"), - [ { name: "Name", field: "name", width: "120px"}, - { name: "Type", field: "type", width: "120px"}, - { name: "Binding Count", field: "bindingCount", - width: "100%"} + [ + { name: "Name", field: "name", width: "120px"}, + { name: "Type", field: "type", width: "120px"}, + { name: "Binding Count", field: "bindingCount", width: "100%"} ], function(obj) { connect.connect(obj.grid, "onRowDblClick", obj.grid, function(evt){ var idx = evt.rowIndex, - theItem = this.getItem(idx); + theItem = this.getItem(idx); var exchangeName = obj.dataStore.getValue(theItem,"name"); controller.show("exchange", exchangeName, vhost); }); - } ); + } , gridProperties, EnhancedGrid); that.connectionsGrid = new UpdatableStore(that.vhostData.connections, @@ -315,6 +354,18 @@ define(["dojo/_base/xhr", // update exchanges thisObj.exchangesGrid.update(thisObj.vhostData.exchanges); + var exchangesGrid = thisObj.exchangesGrid.grid; + for(var i=0; i< thisObj.vhostData.exchanges.length; i++) + { + var data = exchangesGrid.getItem(i); + var isStandard = false; + if (data && data.name) + { + isStandard = util.isReservedExchangeName(data.name); + } + exchangesGrid.rowSelectCell.setDisabled(i, isStandard); + } + // update connections thisObj.connectionsGrid.update(thisObj.vhostData.connections) diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addExchange.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addExchange.js index f88daa54bb..915092a9d1 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addExchange.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addExchange.js @@ -109,7 +109,6 @@ define(["dojo/_base/xhr", var newExchange = convertToExchange(theForm.getValues()); var that = this; - xhr.put({url: "rest/exchange/"+encodeURIComponent(addExchange.vhost) + "/"+encodeURIComponent(newExchange.name), sync: true, handleAs: "json", headers: { "Content-Type": "application/json"}, diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showExchange.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showExchange.html index b0aa302782..f33b029026 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/showExchange.html +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showExchange.html @@ -41,6 +41,10 @@ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Bindings'"> <div class="bindings"></div> <button data-dojo-type="dijit.form.Button" class="addBindingButton">Add Binding</button> + <button data-dojo-type="dijit.form.Button" class="deleteBindingButton">Delete Binding</button> </div> <br/> + <div class="dijitDialogPaneActionBar"> + <button data-dojo-type="dijit.form.Button" class="deleteExchangeButton" type="button">Delete Exchange</button> + </div> </div> diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showQueue.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showQueue.html index 3be53a45a2..f4960055b0 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/showQueue.html +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showQueue.html @@ -97,5 +97,9 @@ </div> + + <div class="dijitDialogPaneActionBar"> + <button data-dojo-type="dijit.form.Button" class="deleteQueueButton" type="button">Delete Queue</button> + </div> </div> diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html index 9d16d523d6..f4d998458f 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html @@ -43,11 +43,13 @@ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Exchanges'"> <div class="exchanges"></div> <button data-dojo-type="dijit.form.Button" class="addExchangeButton">Add Exchange</button> + <button data-dojo-type="dijit.form.Button" class="deleteExchangeButton">Delete Exchange</button> </div> <br/> <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Queues'"> <div class="queues"></div> <button data-dojo-type="dijit.form.Button" class="addQueueButton">Add Queue</button> + <button data-dojo-type="dijit.form.Button" class="deleteQueueButton">Delete Queue</button> </div> <br/> <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Connections'"> diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BindingRestTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BindingRestTest.java index 91b41c3476..527eb16927 100644 --- a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BindingRestTest.java +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BindingRestTest.java @@ -1,5 +1,6 @@ package org.apache.qpid.server.management.plugin.servlet.rest; +import java.net.HttpURLConnection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -61,4 +62,48 @@ public class BindingRestTest extends QpidRestTestCase Asserts.assertBinding("queue", "amq.direct", bindings.get(0)); } + + public void testDeleteBinding() throws Exception + { + List<Map<String, Object>> bindings = getJsonAsList("/rest/binding/test/amq.direct/queue/queue"); + assertEquals("Unexpected number of bindings", 1, bindings.size()); + Asserts.assertBinding("queue", "amq.direct", bindings.get(0)); + + HttpURLConnection connection = openManagementConection("/rest/binding/test/amq.direct/queue/queue", "DELETE"); + connection.connect(); + assertEquals("Unexpected response code", 200, connection.getResponseCode()); + + bindings = getJsonAsList("/rest/binding/test/amq.direct/queue/queue"); + assertEquals("Binding should be deleted", 0, bindings.size()); + } + + public void testDeleteBindingById() throws Exception + { + Map<String, Object> binding = getJsonAsSingletonList("/rest/binding/test/amq.direct/queue"); + HttpURLConnection connection = openManagementConection("/rest/binding/test/amq.direct?id=" + binding.get(Binding.ID), "DELETE"); + connection.connect(); + assertEquals("Unexpected response code", 200, connection.getResponseCode()); + List<Map<String, Object>> bindings = getJsonAsList("/rest/binding/test/amq.direct/queue"); + assertEquals("Binding should be deleted", 0, bindings.size()); + } + + public void testCreateBinding() throws Exception + { + String bindingName = getTestName(); + Map<String, Object> bindingData = new HashMap<String, Object>(); + bindingData.put(Binding.NAME, bindingName); + bindingData.put(Binding.QUEUE, "queue"); + bindingData.put(Binding.EXCHANGE, "amq.direct"); + + HttpURLConnection connection = openManagementConection("/rest/binding/test/amq.direct/queue/" + bindingName, "PUT"); + connection.connect(); + writeJsonRequest(connection, bindingData); + int responseCode = connection.getResponseCode(); + connection.disconnect(); + assertEquals("Unexpected response code", 201, responseCode); + Map<String, Object> binding = getJsonAsSingletonList("/rest/binding/test/amq.direct/queue/" + bindingName); + + Asserts.assertBinding(bindingName, "queue", "amq.direct", binding); + } + } diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostRestTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostRestTest.java index 71e85d389e..eaf2e60478 100644 --- a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostRestTest.java +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostRestTest.java @@ -246,6 +246,56 @@ public class VirtualHostRestTest extends QpidRestTestCase assertNull("Queue of unsupported type was created", queue); } + public void testDeleteQueue() throws Exception + { + String queueName = getTestQueueName(); + createQueue(queueName, null, null); + + HttpURLConnection connection = openManagementConection("/rest/queue/test/" + queueName, "DELETE"); + connection.connect(); + assertEquals("Unexpected response code", 200, connection.getResponseCode()); + List<Map<String, Object>> queues = getJsonAsList("/rest/queue/test/" + queueName); + assertEquals("Queue should be deleted", 0, queues.size()); + } + + public void testDeleteQueueById() throws Exception + { + String queueName = getTestQueueName(); + createQueue(queueName, null, null); + Map<String, Object> queueDetails = getJsonAsSingletonList("/rest/queue/test/" + queueName); + + HttpURLConnection connection = openManagementConection("/rest/queue/test?id=" + queueDetails.get(Queue.ID), "DELETE"); + connection.connect(); + assertEquals("Unexpected response code", 200, connection.getResponseCode()); + List<Map<String, Object>> queues = getJsonAsList("/rest/queue/test/" + queueName); + assertEquals("Queue should be deleted", 0, queues.size()); + } + + public void testDeleteExchange() throws Exception + { + String exchangeName = getTestName(); + createExchange(exchangeName, "direct"); + + HttpURLConnection connection = openManagementConection("/rest/exchange/test/" + exchangeName, "DELETE"); + connection.connect(); + assertEquals("Unexpected response code", 200, connection.getResponseCode()); + List<Map<String, Object>> queues = getJsonAsList("/rest/exchange/test/" + exchangeName); + assertEquals("Exchange should be deleted", 0, queues.size()); + } + + public void testDeleteExchangeById() throws Exception + { + String exchangeName = getTestName(); + createExchange(exchangeName, "direct"); + Map<String, Object> echangeDetails = getJsonAsSingletonList("/rest/exchange/test/" + exchangeName); + + HttpURLConnection connection = openManagementConection("/rest/exchange/test?id=" + echangeDetails.get(Exchange.ID), "DELETE"); + connection.connect(); + assertEquals("Unexpected response code", 200, connection.getResponseCode()); + List<Map<String, Object>> queues = getJsonAsList("/rest/exchange/test/" + exchangeName); + assertEquals("Exchange should be deleted", 0, queues.size()); + } + private void createExchange(String exchangeName, String exchangeType) throws IOException { HttpURLConnection connection = openManagementConection("/rest/exchange/test/" + exchangeName, "PUT"); diff --git a/qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java b/qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java index 2c341b7f2e..7473a4d3e7 100644 --- a/qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java +++ b/qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java @@ -24,9 +24,6 @@ import org.apache.qpid.management.common.mbeans.ManagedExchange; import org.apache.qpid.test.utils.JMXTestUtils; import org.apache.qpid.test.utils.QpidBrokerTestCase; -import javax.management.MBeanException; -import javax.management.ObjectName; - /** * Tests the JMX API for the Managed Broker. * @@ -115,11 +112,10 @@ public class BrokerManagementTest extends QpidBrokerTestCase _managedBroker.unregisterExchange(defaultExchangeName); fail("Exception not thrown"); } - catch (MBeanException mbe) + catch (UnsupportedOperationException e) { // PASS - assertEquals("Error in unregistering exchange " + defaultExchangeName, mbe.getMessage()); - assertTrue(mbe.getCause().getMessage().contains("Cannot unregister the default exchange")); + assertEquals("'<<default>>' is a reserved exchange and can't be deleted", e.getMessage()); } final ManagedExchange defaultExchange = _jmxUtils.getManagedExchange(defaultExchangeName); assertNotNull("Exchange should exist", defaultExchange); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java index baf9cc3d09..07813b073b 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java @@ -225,4 +225,21 @@ public class DefaultExchangeRegistry implements ExchangeRegistry } } + public boolean isReservedExchangeName(String name) + { + if (name == null || "".equals(name) || ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString().equals(name) + || name.startsWith("amq.") || name.startsWith("qpid.")) + { + return true; + } + Collection<ExchangeType<? extends Exchange>> registeredTypes = _host.getExchangeFactory().getRegisteredTypes(); + for (ExchangeType<? extends Exchange> type : registeredTypes) + { + if (type.getDefaultExchangeName().toString().equals(name)) + { + return true; + } + } + return false; + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java index 692a2b2b0d..4dcedb4797 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java @@ -62,6 +62,13 @@ public interface ExchangeRegistry void addRegistryChangeListener(RegistryChangeListener listener); + /** + * Validates the name of user custom exchange. + * <p> + * Return true if the exchange name is reserved and false otherwise. + */ + boolean isReservedExchangeName(String name); + interface RegistryChangeListener { void exchangeRegistered(Exchange exchange); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHost.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHost.java index 53faefc954..24a3d43386 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHost.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHost.java @@ -131,8 +131,6 @@ public interface VirtualHost extends ConfiguredObject boolean exclusive, LifetimePolicy lifetime, long ttl, Map<String, Object> attributes) throws AccessControlException, IllegalArgumentException; - void deleteQueue(Queue queue) throws AccessControlException, IllegalStateException; - Collection<String> getExchangeTypes(); public static interface Transaction diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BindingAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BindingAdapter.java index f041494781..abd3160686 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BindingAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BindingAdapter.java @@ -31,6 +31,7 @@ import org.apache.qpid.AMQSecurityException; import org.apache.qpid.server.model.Binding; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.Exchange; +import org.apache.qpid.server.model.IllegalStateTransitionException; import org.apache.qpid.server.model.LifetimePolicy; import org.apache.qpid.server.model.Queue; import org.apache.qpid.server.model.State; @@ -216,4 +217,16 @@ final class BindingAdapter extends AbstractAdapter implements Binding { return Binding.AVAILABLE_ATTRIBUTES; } + + @Override + public State setDesiredState(State currentState, State desiredState) throws IllegalStateTransitionException, + AccessControlException + { + if (desiredState == State.DELETED) + { + delete(); + return State.DELETED; + } + return super.setDesiredState(currentState, desiredState); + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java index c0d85845d6..df0f29fbc3 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java @@ -30,9 +30,13 @@ import java.util.Map; import org.apache.qpid.AMQException; import org.apache.qpid.AMQInternalException; import org.apache.qpid.AMQSecurityException; +import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.server.binding.Binding; +import org.apache.qpid.server.exchange.ExchangeRegistry; +import org.apache.qpid.server.exchange.ExchangeType; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.Exchange; +import org.apache.qpid.server.model.IllegalStateTransitionException; import org.apache.qpid.server.model.LifetimePolicy; import org.apache.qpid.server.model.Publisher; import org.apache.qpid.server.model.Queue; @@ -50,7 +54,6 @@ final class ExchangeAdapter extends AbstractAdapter implements Exchange, org.apa private VirtualHostAdapter _vhost; private final ExchangeStatistics _statistics; - public ExchangeAdapter(final VirtualHostAdapter virtualHostAdapter, final org.apache.qpid.server.exchange.Exchange exchange) { @@ -164,7 +167,21 @@ final class ExchangeAdapter extends AbstractAdapter implements Exchange, org.apa { try { - _vhost.getVirtualHost().getExchangeRegistry().unregisterExchange(getName(), false); + ExchangeRegistry exchangeRegistry = _vhost.getVirtualHost().getExchangeRegistry(); + if (exchangeRegistry.isReservedExchangeName(getName())) + { + throw new UnsupportedOperationException("'" + getName() + "' is a reserved exchange and can't be deleted"); + } + + if(_exchange.hasReferrers()) + { + throw new AMQException( AMQConstant.NOT_ALLOWED, "Exchange in use as an alternate exchange", null); + } + + synchronized(exchangeRegistry) + { + exchangeRegistry.unregisterExchange(getName(), false); + } } catch(AMQException e) { @@ -364,6 +381,18 @@ final class ExchangeAdapter extends AbstractAdapter implements Exchange, org.apa return AVAILABLE_ATTRIBUTES; } + @Override + public State setDesiredState(State currentState, State desiredState) throws IllegalStateTransitionException, + AccessControlException + { + if (desiredState == State.DELETED) + { + delete(); + return State.DELETED; + } + return super.setDesiredState(currentState, desiredState); + } + private class ExchangeStatistics implements Statistics { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java index 21c4aef323..5a5f7435a2 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java @@ -27,6 +27,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; + import org.apache.qpid.AMQException; import org.apache.qpid.AMQStoreException; import org.apache.qpid.server.binding.Binding; @@ -34,6 +35,7 @@ import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.ConfiguredObjectFinder; import org.apache.qpid.server.model.Consumer; import org.apache.qpid.server.model.Exchange; +import org.apache.qpid.server.model.IllegalStateTransitionException; import org.apache.qpid.server.model.LifetimePolicy; import org.apache.qpid.server.model.Queue; import org.apache.qpid.server.model.QueueNotificationListener; @@ -130,11 +132,14 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs { try { - _queue.delete(); - if (_queue.isDurable()) + QueueRegistry queueRegistry = _queue.getVirtualHost().getQueueRegistry(); + synchronized(queueRegistry) { - - _queue.getVirtualHost().getMessageStore().removeQueue(_queue); + _queue.delete(); + if (_queue.isDurable()) + { + _queue.getVirtualHost().getMessageStore().removeQueue(_queue); + } } } catch(AMQException e) @@ -705,4 +710,17 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs listener.notifyClients(notification, this, notificationMsg); } } + + @Override + public State setDesiredState(State currentState, State desiredState) throws IllegalStateTransitionException, + AccessControlException + { + if (desiredState == State.DELETED) + { + delete(); + return State.DELETED; + } + return super.setDesiredState(currentState, desiredState); + } + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java index bcfdb22fa9..35838e51d2 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java @@ -228,18 +228,29 @@ final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, E try { - org.apache.qpid.server.exchange.Exchange exchange = - _virtualHost.getExchangeFactory().createExchange(name, type, durable, - lifetime == LifetimePolicy.AUTO_DELETE); - _virtualHost.getExchangeRegistry().registerExchange(exchange); - if(durable) + ExchangeRegistry exchangeRegistry = _virtualHost.getExchangeRegistry(); + if (exchangeRegistry.isReservedExchangeName(name)) { - _virtualHost.getMessageStore().createExchange(exchange); + throw new UnsupportedOperationException("'" + name + "' is a reserved exchange name"); } - - synchronized (_exchangeAdapters) + synchronized(exchangeRegistry) { - return _exchangeAdapters.get(exchange); + org.apache.qpid.server.exchange.Exchange exchange = exchangeRegistry.getExchange(name); + if (exchange != null) + { + throw new IllegalArgumentException("Exchange with name '" + name + "' already exists"); + } + exchange = _virtualHost.getExchangeFactory().createExchange(name, type, durable, + lifetime == LifetimePolicy.AUTO_DELETE); + _virtualHost.getExchangeRegistry().registerExchange(exchange); + if(durable) + { + _virtualHost.getMessageStore().createExchange(exchange); + } + synchronized (_exchangeAdapters) + { + return _exchangeAdapters.get(exchange); + } } } catch(AMQException e) @@ -326,23 +337,27 @@ final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, E } try { - if(_virtualHost.getQueueRegistry().getQueue(name)!=null) + QueueRegistry queueRegistry = _virtualHost.getQueueRegistry(); + synchronized (queueRegistry) { - throw new IllegalArgumentException("Queue with name "+name+" already exists"); - } - AMQQueue queue = - AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateQueueUUID(name, _virtualHost.getName()), name, - durable, owner, lifetime == LifetimePolicy.AUTO_DELETE, - exclusive, _virtualHost, attributes); - _virtualHost.getBindingFactory().addBinding(name, queue, _virtualHost.getExchangeRegistry().getDefaultExchange(), null); + if(_virtualHost.getQueueRegistry().getQueue(name)!=null) + { + throw new IllegalArgumentException("Queue with name "+name+" already exists"); + } + AMQQueue queue = + AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateQueueUUID(name, _virtualHost.getName()), name, + durable, owner, lifetime == LifetimePolicy.AUTO_DELETE, + exclusive, _virtualHost, attributes); + _virtualHost.getBindingFactory().addBinding(name, queue, _virtualHost.getExchangeRegistry().getDefaultExchange(), null); - if(durable) - { - _virtualHost.getMessageStore().createQueue(queue, FieldTable.convertToFieldTable(attributes)); - } - synchronized (_queueAdapters) - { - return _queueAdapters.get(queue); + if(durable) + { + _virtualHost.getMessageStore().createQueue(queue, FieldTable.convertToFieldTable(attributes)); + } + synchronized (_queueAdapters) + { + return _queueAdapters.get(queue); + } } } @@ -569,13 +584,6 @@ final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, E } } - public void deleteQueue(Queue queue) - throws AccessControlException, IllegalStateException - { - // TODO - throw new UnsupportedOperationException("Not Yet Implemented"); - } - public Collection<String> getExchangeTypes() { Collection<ExchangeType<? extends org.apache.qpid.server.exchange.Exchange>> types = @@ -880,4 +888,5 @@ final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, E } } } + } |