CLI
Project: http://git-wip-us.apache.org/repos/asf/activemq-artemis/repo Commit: http://git-wip-us.apache.org/repos/asf/activemq-artemis/commit/6b441b74 Tree: http://git-wip-us.apache.org/repos/asf/activemq-artemis/tree/6b441b74 Diff: http://git-wip-us.apache.org/repos/asf/activemq-artemis/diff/6b441b74 Branch: refs/heads/ARTEMIS-780 Commit: 6b441b745e609b3bed41124e98888ebf7384075f Parents: bd4b7ce Author: Martyn Taylor <[email protected]> Authored: Wed Nov 16 15:22:41 2016 +0000 Committer: Martyn Taylor <[email protected]> Committed: Wed Nov 16 15:24:45 2016 +0000 ---------------------------------------------------------------------- .../artemis/cli/commands/AbstractAction.java | 62 ++++++++ .../cli/commands/address/AddressAction.java | 77 --------- .../cli/commands/address/CreateAddress.java | 71 ++++++--- .../cli/commands/address/DeleteAddress.java | 28 ++-- .../cli/commands/address/ShowAddress.java | 84 ++++++++++ .../artemis/cli/commands/queue/CreateQueue.java | 18 ++- .../artemis/cli/commands/queue/DeleteQueue.java | 20 ++- .../artemis/cli/commands/queue/QueueAction.java | 77 --------- .../ActiveMQAddressDoesNotExistException.java | 31 ++++ .../core/ActiveMQDeleteAddressException.java | 31 ++++ .../artemis/api/core/ActiveMQExceptionType.java | 12 ++ .../core/management/ActiveMQServerControl.java | 23 +++ .../impl/ActiveMQServerControlImpl.java | 47 +++++- .../artemis/core/postoffice/PostOffice.java | 3 + .../core/postoffice/impl/PostOfficeImpl.java | 57 +++++-- .../core/server/ActiveMQMessageBundle.java | 11 +- .../artemis/core/server/ActiveMQServer.java | 9 ++ .../activemq/artemis/core/server/Queue.java | 2 - .../core/server/impl/ActiveMQServerImpl.java | 87 ++++++----- .../artemis/core/server/impl/AddressInfo.java | 4 +- .../artemis/core/server/impl/QueueImpl.java | 6 +- .../integration/cli/AddressCommandTest.java | 155 +++++++++++++++++++ .../tests/integration/cli/QueueCommandTest.java | 7 +- .../ActiveMQServerControlUsingCoreTest.java | 25 +++ .../core/server/impl/fakes/FakePostOffice.java | 6 + 25 files changed, 691 insertions(+), 262 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b441b74/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/AbstractAction.java ---------------------------------------------------------------------- diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/AbstractAction.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/AbstractAction.java new file mode 100644 index 0000000..b4dbba8 --- /dev/null +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/AbstractAction.java @@ -0,0 +1,62 @@ +/* + * 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. + */ +package org.apache.activemq.artemis.cli.commands; + +import io.airlift.airline.Option; +import org.apache.activemq.artemis.api.core.client.ActiveMQClient; +import org.apache.activemq.artemis.api.core.client.ClientMessage; +import org.apache.activemq.artemis.api.core.client.ClientRequestor; +import org.apache.activemq.artemis.api.core.client.ClientSession; +import org.apache.activemq.artemis.api.core.client.ClientSessionFactory; +import org.apache.activemq.artemis.api.core.client.ServerLocator; +import org.apache.activemq.artemis.api.core.management.ManagementHelper; +import org.apache.activemq.artemis.cli.commands.messages.ConnectionAbstract; +import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory; + +public abstract class AbstractAction extends ConnectionAbstract { + + public void performCoreManagement(ManagementCallback<ClientMessage> cb) throws Exception { + + try (ActiveMQConnectionFactory factory = createConnectionFactory(); + ServerLocator locator = factory.getServerLocator(); + ClientSessionFactory sessionFactory = locator.createSessionFactory(); + ClientSession session = sessionFactory.createSession(user, password, false, true, true, false, ActiveMQClient.DEFAULT_ACK_BATCH_SIZE)) { + session.start(); + ClientRequestor requestor = new ClientRequestor(session, "activemq.management"); + ClientMessage message = session.createMessage(false); + + cb.setUpInvocation(message); + + ClientMessage reply = requestor.request(message); + + if (ManagementHelper.hasOperationSucceeded(reply)) { + cb.requestSuccessful(reply); + } else { + cb.requestFailed(reply); + } + } + } + + public interface ManagementCallback<T> { + + void setUpInvocation(T message) throws Exception; + + void requestSuccessful(T reply) throws Exception; + + void requestFailed(T reply) throws Exception; + } +} http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b441b74/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/AddressAction.java ---------------------------------------------------------------------- diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/AddressAction.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/AddressAction.java deleted file mode 100644 index c2f1716..0000000 --- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/AddressAction.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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. - */ -package org.apache.activemq.artemis.cli.commands.address; - -import io.airlift.airline.Option; -import org.apache.activemq.artemis.api.core.client.ActiveMQClient; -import org.apache.activemq.artemis.api.core.client.ClientMessage; -import org.apache.activemq.artemis.api.core.client.ClientRequestor; -import org.apache.activemq.artemis.api.core.client.ClientSession; -import org.apache.activemq.artemis.api.core.client.ClientSessionFactory; -import org.apache.activemq.artemis.api.core.client.ServerLocator; -import org.apache.activemq.artemis.api.core.management.ManagementHelper; -import org.apache.activemq.artemis.cli.commands.messages.ConnectionAbstract; -import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory; - -public abstract class AddressAction extends ConnectionAbstract { - - @Option(name = "--name", description = "address name") - String name; - - public void performCoreManagement(ManagementCallback<ClientMessage> cb) throws Exception { - - try (ActiveMQConnectionFactory factory = createConnectionFactory(); - ServerLocator locator = factory.getServerLocator(); - ClientSessionFactory sessionFactory = locator.createSessionFactory(); - ClientSession session = sessionFactory.createSession(user, password, false, true, true, false, ActiveMQClient.DEFAULT_ACK_BATCH_SIZE)) { - session.start(); - ClientRequestor requestor = new ClientRequestor(session, "activemq.management"); - ClientMessage message = session.createMessage(false); - - cb.setUpInvocation(message); - - ClientMessage reply = requestor.request(message); - - if (ManagementHelper.hasOperationSucceeded(reply)) { - cb.requestSuccessful(reply); - } else { - cb.requestFailed(reply); - } - } - } - - public void setName(String name) { - this.name = name; - } - - public String getName() { - if (name == null) { - name = input("--name", "Please provide the destination name:", ""); - } - - return name; - } - - public interface ManagementCallback<T> { - - void setUpInvocation(T message) throws Exception; - - void requestSuccessful(T reply) throws Exception; - - void requestFailed(T reply) throws Exception; - } -} http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b441b74/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/CreateAddress.java ---------------------------------------------------------------------- diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/CreateAddress.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/CreateAddress.java index 0474050..6c92dc6 100644 --- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/CreateAddress.java +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/CreateAddress.java @@ -21,52 +21,81 @@ import io.airlift.airline.Command; import io.airlift.airline.Option; import org.apache.activemq.artemis.api.core.client.ClientMessage; import org.apache.activemq.artemis.api.core.management.ManagementHelper; +import org.apache.activemq.artemis.cli.commands.AbstractAction; import org.apache.activemq.artemis.cli.commands.ActionContext; +import org.apache.activemq.artemis.core.server.impl.AddressInfo; -@Command(name = "create", description = "create a queue or topic") -public class CreateAddress extends AddressAction { +@Command(name = "create", description = "create an address") +public class CreateAddress extends AbstractAction { - @Option(name = "--address", description = "address of the core queue (default queue's name)") - String address; + @Option(name = "--name", description = "The name of this address") + String name; - @Option(name = "--durable", description = "whether the queue is durable or not (default false)") - boolean durable = false; + @Option(name = "--routingType", description = "The routing type of the address, options are 'anycast' or 'multicast', defaults to 1 = 'multicast'") + String routingType = "multicast"; - @Option(name = "--autoCreateAddress", description = "auto create an address for this queue if one doesn't exist") - boolean autoCreateAddress = true; + @Option(name = "--defaultMaxConsumers", description = "Sets the default max consumers for any queues created under this address, default = -1 (no limit)") + int defaultMaxConsumers = -1; + + @Option(name = "--defaultDeleteOnNoConsumers", description = "Sets the default delete on no consumers for any queues created under this address, default = false") + boolean defaultDeleteOnNoConsumers = false; @Override public Object execute(ActionContext context) throws Exception { super.execute(context); - createQueue(context); + createAddress(context); return null; } - public String getAddress() { - if (address == null || "".equals(address.trim())) { - address = getName(); - } - return address.trim(); - } - - private void createQueue(final ActionContext context) throws Exception { + private void createAddress(final ActionContext context) throws Exception { performCoreManagement(new ManagementCallback<ClientMessage>() { @Override public void setUpInvocation(ClientMessage message) throws Exception { - String address = getAddress(); - ManagementHelper.putOperationInvocation(message, "broker", "createQueue", address, getName(), durable); + ManagementHelper.putOperationInvocation(message, "broker", "createAddress", getName(), routingType, defaultDeleteOnNoConsumers, defaultMaxConsumers); } @Override public void requestSuccessful(ClientMessage reply) throws Exception { - context.out.println("Core queue " + getName() + " created successfully."); + context.out.println("Address " + getName() + " created successfully."); } @Override public void requestFailed(ClientMessage reply) throws Exception { String errMsg = (String) ManagementHelper.getResult(reply, String.class); - context.err.println("Failed to create queue " + getName() + ". Reason: " + errMsg); + context.err.println("Failed to create address " + getName() + ". Reason: " + errMsg); } }); } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public String getRoutingType() { + return routingType; + } + + public void setRoutingType(String routingType) { + this.routingType = routingType; + } + + public int getDefaultMaxConsumers() { + return defaultMaxConsumers; + } + + public void setDefaultMaxConsumers(int defaultMaxConsumers) { + this.defaultMaxConsumers = defaultMaxConsumers; + } + + public boolean getDefaultDeleteOnNoConsumers() { + return defaultDeleteOnNoConsumers; + } + + public void setDefaultDeleteOnNoConsumers(boolean defaultDeleteOnNoConsumers) { + this.defaultDeleteOnNoConsumers = defaultDeleteOnNoConsumers; + } } http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b441b74/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/DeleteAddress.java ---------------------------------------------------------------------- diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/DeleteAddress.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/DeleteAddress.java index d6ce7f6..36c9224 100644 --- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/DeleteAddress.java +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/DeleteAddress.java @@ -21,41 +21,47 @@ import io.airlift.airline.Command; import io.airlift.airline.Option; import org.apache.activemq.artemis.api.core.client.ClientMessage; import org.apache.activemq.artemis.api.core.management.ManagementHelper; +import org.apache.activemq.artemis.cli.commands.AbstractAction; import org.apache.activemq.artemis.cli.commands.ActionContext; @Command(name = "delete", description = "delete a queue") -public class DeleteAddress extends AddressAction { +public class DeleteAddress extends AbstractAction { - @Option(name = "--removeConsumers", description = "whether deleting destination with consumers or not (default false)") - boolean removeConsumers = false; - - @Option(name = "--autoDeleteAddress", description = "delete the address if this it's last last queue") - boolean autoDeleteAddress = false; + @Option(name = "--name", description = "The name of this address") + String name; @Override public Object execute(ActionContext context) throws Exception { super.execute(context); - deleteQueue(context); + deleteAddress(context); return null; } - private void deleteQueue(final ActionContext context) throws Exception { + private void deleteAddress(final ActionContext context) throws Exception { performCoreManagement(new ManagementCallback<ClientMessage>() { @Override public void setUpInvocation(ClientMessage message) throws Exception { - ManagementHelper.putOperationInvocation(message, "broker", "destroyQueue", getName(), removeConsumers); + ManagementHelper.putOperationInvocation(message, "broker", "deleteAddress", getName()); } @Override public void requestSuccessful(ClientMessage reply) throws Exception { - context.out.println("Queue " + getName() + " deleted successfully."); + context.out.println("Address " + getName() + " deleted successfully."); } @Override public void requestFailed(ClientMessage reply) throws Exception { String errMsg = (String) ManagementHelper.getResult(reply, String.class); - context.err.println("Failed to delete queue " + getName() + ". Reason: " + errMsg); + context.err.println("Failed to delete address " + getName() + ". Reason: " + errMsg); } }); } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } } http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b441b74/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/ShowAddress.java ---------------------------------------------------------------------- diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/ShowAddress.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/ShowAddress.java new file mode 100644 index 0000000..34331bb --- /dev/null +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/ShowAddress.java @@ -0,0 +1,84 @@ +/* + * 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. + */ + +package org.apache.activemq.artemis.cli.commands.address; + +import io.airlift.airline.Command; +import io.airlift.airline.Option; +import org.apache.activemq.artemis.api.core.client.ClientMessage; +import org.apache.activemq.artemis.api.core.management.ManagementHelper; +import org.apache.activemq.artemis.cli.commands.AbstractAction; +import org.apache.activemq.artemis.cli.commands.ActionContext; + +@Command(name = "show", description = "delete a queue") +public class ShowAddress extends AbstractAction { + + @Option(name = "--name", description = "The name of this address") + String name; + + @Option(name = "--bindings", description = "Shows the bindings for this address") + boolean bindings; + + @Override + public Object execute(ActionContext context) throws Exception { + super.execute(context); + showAddress(context); + return null; + } + + private void showAddress(final ActionContext context) throws Exception { + performCoreManagement(new ManagementCallback<ClientMessage>() { + @Override + public void setUpInvocation(ClientMessage message) throws Exception { + if (bindings) { + ManagementHelper.putOperationInvocation(message, "broker", "listBindingsForAddress", getName()); + } + else { + ManagementHelper.putOperationInvocation(message, "broker", "getAddressInfo", getName()); + } + } + + @Override + public void requestSuccessful(ClientMessage reply) throws Exception { + String result = (String) ManagementHelper.getResult(reply, String.class); + context.out.println(result); + } + + @Override + public void requestFailed(ClientMessage reply) throws Exception { + String errMsg = (String) ManagementHelper.getResult(reply, String.class); + context.err.println("Failed to show address " + getName() + ". Reason: " + errMsg); + } + }); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isBindings() { + return bindings; + } + + public void setBindings(boolean bindings) { + this.bindings = bindings; + } +} http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b441b74/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/CreateQueue.java ---------------------------------------------------------------------- diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/CreateQueue.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/CreateQueue.java index fba9369..76cea6e 100644 --- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/CreateQueue.java +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/CreateQueue.java @@ -22,9 +22,13 @@ import io.airlift.airline.Option; import org.apache.activemq.artemis.api.core.client.ClientMessage; import org.apache.activemq.artemis.api.core.management.ManagementHelper; import org.apache.activemq.artemis.cli.commands.ActionContext; +import org.apache.activemq.artemis.cli.commands.AbstractAction; @Command(name = "create", description = "create a queue or topic") -public class CreateQueue extends QueueAction { +public class CreateQueue extends AbstractAction { + + @Option(name = "--name", description = "queue name") + String name; @Option(name = "--filter", description = "queue's filter string (default null)") String filter = null; @@ -98,4 +102,16 @@ public class CreateQueue extends QueueAction { public void setAddress(String address) { this.address = address; } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + if (name == null) { + name = input("--name", "Please provide the destination name:", ""); + } + + return name; + } } http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b441b74/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/DeleteQueue.java ---------------------------------------------------------------------- diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/DeleteQueue.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/DeleteQueue.java index 5d92e81..19d2e99 100644 --- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/DeleteQueue.java +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/DeleteQueue.java @@ -22,9 +22,13 @@ import io.airlift.airline.Option; import org.apache.activemq.artemis.api.core.client.ClientMessage; import org.apache.activemq.artemis.api.core.management.ManagementHelper; import org.apache.activemq.artemis.cli.commands.ActionContext; +import org.apache.activemq.artemis.cli.commands.AbstractAction; @Command(name = "delete", description = "delete a queue") -public class DeleteQueue extends QueueAction { +public class DeleteQueue extends AbstractAction { + + @Option(name = "--name", description = "queue name") + String name; @Option(name = "--removeConsumers", description = "whether deleting destination with consumers or not (default false)") boolean removeConsumers = false; @@ -43,7 +47,7 @@ public class DeleteQueue extends QueueAction { performCoreManagement(new ManagementCallback<ClientMessage>() { @Override public void setUpInvocation(ClientMessage message) throws Exception { - ManagementHelper.putOperationInvocation(message, "broker", "destroyQueue", getName(), removeConsumers); + ManagementHelper.putOperationInvocation(message, "broker", "destroyQueue", getName(), removeConsumers, autoDeleteAddress); } @Override @@ -66,4 +70,16 @@ public class DeleteQueue extends QueueAction { public void setAutoDeleteAddress(boolean autoDeleteAddress) { this.autoDeleteAddress = autoDeleteAddress; } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + if (name == null) { + name = input("--name", "Please provide the destination name:", ""); + } + + return name; + } } http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b441b74/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/QueueAction.java ---------------------------------------------------------------------- diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/QueueAction.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/QueueAction.java deleted file mode 100644 index dc839ef..0000000 --- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/QueueAction.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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. - */ -package org.apache.activemq.artemis.cli.commands.queue; - -import io.airlift.airline.Option; -import org.apache.activemq.artemis.api.core.client.ActiveMQClient; -import org.apache.activemq.artemis.api.core.client.ClientMessage; -import org.apache.activemq.artemis.api.core.client.ClientRequestor; -import org.apache.activemq.artemis.api.core.client.ClientSession; -import org.apache.activemq.artemis.api.core.client.ClientSessionFactory; -import org.apache.activemq.artemis.api.core.client.ServerLocator; -import org.apache.activemq.artemis.api.core.management.ManagementHelper; -import org.apache.activemq.artemis.cli.commands.messages.ConnectionAbstract; -import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory; - -public abstract class QueueAction extends ConnectionAbstract { - - @Option(name = "--name", description = "queue name") - String name; - - public void performCoreManagement(ManagementCallback<ClientMessage> cb) throws Exception { - - try (ActiveMQConnectionFactory factory = createConnectionFactory(); - ServerLocator locator = factory.getServerLocator(); - ClientSessionFactory sessionFactory = locator.createSessionFactory(); - ClientSession session = sessionFactory.createSession(user, password, false, true, true, false, ActiveMQClient.DEFAULT_ACK_BATCH_SIZE)) { - session.start(); - ClientRequestor requestor = new ClientRequestor(session, "activemq.management"); - ClientMessage message = session.createMessage(false); - - cb.setUpInvocation(message); - - ClientMessage reply = requestor.request(message); - - if (ManagementHelper.hasOperationSucceeded(reply)) { - cb.requestSuccessful(reply); - } else { - cb.requestFailed(reply); - } - } - } - - public void setName(String name) { - this.name = name; - } - - public String getName() { - if (name == null) { - name = input("--name", "Please provide the destination name:", ""); - } - - return name; - } - - public interface ManagementCallback<T> { - - void setUpInvocation(T message) throws Exception; - - void requestSuccessful(T reply) throws Exception; - - void requestFailed(T reply) throws Exception; - } -} http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b441b74/artemis-commons/src/main/java/org/apache/activemq/artemis/api/core/ActiveMQAddressDoesNotExistException.java ---------------------------------------------------------------------- diff --git a/artemis-commons/src/main/java/org/apache/activemq/artemis/api/core/ActiveMQAddressDoesNotExistException.java b/artemis-commons/src/main/java/org/apache/activemq/artemis/api/core/ActiveMQAddressDoesNotExistException.java new file mode 100644 index 0000000..46a82b5 --- /dev/null +++ b/artemis-commons/src/main/java/org/apache/activemq/artemis/api/core/ActiveMQAddressDoesNotExistException.java @@ -0,0 +1,31 @@ +/* + * 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. + */ +package org.apache.activemq.artemis.api.core; + +/** + * An operation failed because an address exists on the server. + */ +public final class ActiveMQAddressDoesNotExistException extends ActiveMQException { + + public ActiveMQAddressDoesNotExistException() { + super(ActiveMQExceptionType.ADDRESS_EXISTS); + } + + public ActiveMQAddressDoesNotExistException(String msg) { + super(ActiveMQExceptionType.ADDRESS_EXISTS, msg); + } +} http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b441b74/artemis-commons/src/main/java/org/apache/activemq/artemis/api/core/ActiveMQDeleteAddressException.java ---------------------------------------------------------------------- diff --git a/artemis-commons/src/main/java/org/apache/activemq/artemis/api/core/ActiveMQDeleteAddressException.java b/artemis-commons/src/main/java/org/apache/activemq/artemis/api/core/ActiveMQDeleteAddressException.java new file mode 100644 index 0000000..9c80306 --- /dev/null +++ b/artemis-commons/src/main/java/org/apache/activemq/artemis/api/core/ActiveMQDeleteAddressException.java @@ -0,0 +1,31 @@ +/* + * 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. + */ +package org.apache.activemq.artemis.api.core; + +/** + * An operation failed because an address exists on the server. + */ +public final class ActiveMQDeleteAddressException extends ActiveMQException { + + public ActiveMQDeleteAddressException() { + super(ActiveMQExceptionType.DELETE_ADDRESS_ERROR); + } + + public ActiveMQDeleteAddressException(String msg) { + super(ActiveMQExceptionType.DELETE_ADDRESS_ERROR, msg); + } +} http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b441b74/artemis-commons/src/main/java/org/apache/activemq/artemis/api/core/ActiveMQExceptionType.java ---------------------------------------------------------------------- diff --git a/artemis-commons/src/main/java/org/apache/activemq/artemis/api/core/ActiveMQExceptionType.java b/artemis-commons/src/main/java/org/apache/activemq/artemis/api/core/ActiveMQExceptionType.java index 785dac3..64518ec 100644 --- a/artemis-commons/src/main/java/org/apache/activemq/artemis/api/core/ActiveMQExceptionType.java +++ b/artemis-commons/src/main/java/org/apache/activemq/artemis/api/core/ActiveMQExceptionType.java @@ -106,6 +106,12 @@ public enum ActiveMQExceptionType { return new ActiveMQSecurityException(msg); } }, + ADDRESS_DOES_NOT_EXIST(106) { + @Override + public ActiveMQException createException(String msg) { + return new ActiveMQAddressDoesNotExistException(msg); + } + }, ADDRESS_EXISTS(107) { @Override public ActiveMQException createException(String msg) { @@ -231,6 +237,12 @@ public enum ActiveMQExceptionType { public ActiveMQException createException(String msg) { return new ActiveMQInvalidQueueConfiguration(msg); } + }, + DELETE_ADDRESS_ERROR(217) { + @Override + public ActiveMQException createException(String msg) { + return new ActiveMQDeleteAddressException(msg); + } }; private static final Map<Integer, ActiveMQExceptionType> TYPE_MAP; http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b441b74/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/ActiveMQServerControl.java ---------------------------------------------------------------------- diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/ActiveMQServerControl.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/ActiveMQServerControl.java index 4384d54..0654dbf 100644 --- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/ActiveMQServerControl.java +++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/ActiveMQServerControl.java @@ -19,6 +19,8 @@ package org.apache.activemq.artemis.api.core.management; import javax.management.MBeanOperationInfo; import java.util.Map; +import org.apache.activemq.artemis.api.core.ActiveMQAddressDoesNotExistException; + /** * An ActiveMQServerControl is used to manage ActiveMQ Artemis servers. */ @@ -438,6 +440,13 @@ public interface ActiveMQServerControl { @Parameter(name = "defaultDeleteOnNoConsumers", desc = "Whether or not a queue with this address is deleted when it has no consumers") boolean defaultDeleteOnNoConsumers, @Parameter(name = "defaultMaxConsumers", desc = "The maximim number of consumer a queue with this address can have") int defaultMaxConsumers) throws Exception; + + @Operation(desc = "create an address", impact = MBeanOperationInfo.ACTION) + void createAddress(@Parameter(name = "name", desc = "The name of the address") String name, + @Parameter(name = "routingType", desc = "The routing type for the address either 'MULTICAST' or 'ANYCAST'") String routingType, + @Parameter(name = "defaultDeleteOnNoConsumers", desc = "Whether or not a queue with this address is deleted when it has no consumers") boolean defaultDeleteOnNoConsumers, + @Parameter(name = "defaultMaxConsumers", desc = "The maximim number of consumer a queue with this address can have") int defaultMaxConsumers) throws Exception; + @Operation(desc = "delete an address", impact = MBeanOperationInfo.ACTION) void deleteAddress(@Parameter(name = "name", desc = "The name of the address") String name) throws Exception; @@ -455,6 +464,7 @@ public interface ActiveMQServerControl { void createQueue(@Parameter(name = "address", desc = "Address of the queue") String address, @Parameter(name = "name", desc = "Name of the queue") String name) throws Exception; + /** * Create a queue. * <br> @@ -556,6 +566,14 @@ public interface ActiveMQServerControl { @Parameter(name = "removeConsumers", desc = "Remove consumers of this queue") boolean removeConsumers) throws Exception; /** + * Destroys the queue corresponding to the specified name and delete it's address if there are no other queues + */ + @Operation(desc = "Destroy a queue", impact = MBeanOperationInfo.ACTION) + void destroyQueue(@Parameter(name = "name", desc = "Name of the queue to destroy") String name, + @Parameter(name = "removeConsumers", desc = "Remove consumers of this queue") boolean removeConsumers, boolean autoDeleteAddress) throws Exception; + + + /** * Enables message counters for this server. */ @Operation(desc = "Enable message counters", impact = MBeanOperationInfo.ACTION) @@ -920,5 +938,10 @@ public interface ActiveMQServerControl { @Operation(desc = "List the Network Topology", impact = MBeanOperationInfo.INFO) String listNetworkTopology() throws Exception; + + String getAddressInfo(String address) throws ActiveMQAddressDoesNotExistException; + + @Operation(desc = "Get a list of bindings associated with an address", impact = MBeanOperationInfo.INFO) + String[] listBindingsForAddress(String address) throws Exception; } http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b441b74/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/ActiveMQServerControlImpl.java ---------------------------------------------------------------------- diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/ActiveMQServerControlImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/ActiveMQServerControlImpl.java index f2a193f..c38b2cf 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/ActiveMQServerControlImpl.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/ActiveMQServerControlImpl.java @@ -42,6 +42,7 @@ import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.atomic.AtomicLong; +import org.apache.activemq.artemis.api.core.ActiveMQAddressDoesNotExistException; import org.apache.activemq.artemis.api.core.SimpleString; import org.apache.activemq.artemis.api.core.TransportConfiguration; import org.apache.activemq.artemis.api.core.management.ActiveMQServerControl; @@ -63,8 +64,10 @@ import org.apache.activemq.artemis.core.persistence.StorageManager; import org.apache.activemq.artemis.core.persistence.config.PersistedAddressSetting; import org.apache.activemq.artemis.core.persistence.config.PersistedRoles; import org.apache.activemq.artemis.core.postoffice.Binding; +import org.apache.activemq.artemis.core.postoffice.Bindings; import org.apache.activemq.artemis.core.postoffice.DuplicateIDCache; import org.apache.activemq.artemis.core.postoffice.PostOffice; +import org.apache.activemq.artemis.core.postoffice.QueueBinding; import org.apache.activemq.artemis.core.postoffice.impl.LocalQueueBinding; import org.apache.activemq.artemis.core.remoting.server.RemotingService; import org.apache.activemq.artemis.core.security.CheckType; @@ -72,6 +75,7 @@ import org.apache.activemq.artemis.core.security.Role; import org.apache.activemq.artemis.core.server.ActiveMQMessageBundle; import org.apache.activemq.artemis.core.server.ActiveMQServer; import org.apache.activemq.artemis.core.server.ActiveMQServerLogger; +import org.apache.activemq.artemis.core.server.BindingQueryResult; import org.apache.activemq.artemis.core.server.ConnectorServiceFactory; import org.apache.activemq.artemis.core.server.Consumer; import org.apache.activemq.artemis.core.server.JournalType; @@ -563,13 +567,22 @@ public class ActiveMQServerControlImpl extends AbstractControl implements Active clearIO(); try { - server.createOrUpdateAddressInfo(new AddressInfo(new SimpleString(name), AddressInfo.RoutingType.getType((byte)routingType), defaultDeleteOnNoConsumers, defaultMaxConsumers)); + server.createAddressInfo(new AddressInfo(new SimpleString(name), AddressInfo.RoutingType.getType((byte) routingType), defaultDeleteOnNoConsumers, defaultMaxConsumers)); } finally { blockOnIO(); } } @Override + public void createAddress(@Parameter(name = "name", desc = "The name of the address") String name, + @Parameter(name = "routingType", desc = "The routing type for the address either 'MULTICAST' or 'ANYCAST'") String routingType, + @Parameter(name = "defaultDeleteOnNoConsumers", desc = "Whether or not a queue with this address is deleted when it has no consumers") boolean defaultDeleteOnNoConsumers, + @Parameter(name = "defaultMaxConsumers", desc = "The maximim number of consumer a queue with this address can have") int defaultMaxConsumers) throws Exception { + AddressInfo.RoutingType rt = AddressInfo.RoutingType.valueOf(routingType.toUpperCase()); + createAddress(name, rt.ordinal(), defaultDeleteOnNoConsumers, defaultMaxConsumers); + } + + @Override public void deleteAddress(String name) throws Exception { checkStarted(); @@ -752,24 +765,52 @@ public class ActiveMQServerControlImpl extends AbstractControl implements Active } @Override - public void destroyQueue(final String name, final boolean removeConsumers) throws Exception { + public void destroyQueue(final String name, final boolean removeConsumers, final boolean autoDeleteAddress) throws Exception { checkStarted(); clearIO(); try { SimpleString queueName = new SimpleString(name); - server.destroyQueue(queueName, null, !removeConsumers, removeConsumers); + server.destroyQueue(queueName, null, !removeConsumers, removeConsumers, autoDeleteAddress); } finally { blockOnIO(); } } @Override + public void destroyQueue(final String name, final boolean removeConsumers) throws Exception { + destroyQueue(name, removeConsumers, false); + } + + @Override public void destroyQueue(final String name) throws Exception { destroyQueue(name, false); } @Override + public String getAddressInfo(String address) throws ActiveMQAddressDoesNotExistException { + AddressInfo addressInfo = server.getAddressInfo(SimpleString.toSimpleString(address)); + if (addressInfo == null) { + throw ActiveMQMessageBundle.BUNDLE.addressDoesNotExist(SimpleString.toSimpleString(address)); + } + else { + return addressInfo.toString(); + } + } + + @Override + public String[] listBindingsForAddress(String address) throws Exception { + Bindings bindings = server.getPostOffice().getBindingsForAddress(new SimpleString(address)); + List<String> result = new ArrayList<>(bindings.getBindings().size()); + + int i = 0; + for (Binding binding : bindings.getBindings()) { + + } + return (String[]) result.toArray(); + } + + @Override public int getConnectionCount() { checkStarted(); http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b441b74/artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/PostOffice.java ---------------------------------------------------------------------- diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/PostOffice.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/PostOffice.java index f1225c1..48ec7db 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/PostOffice.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/PostOffice.java @@ -16,6 +16,7 @@ */ package org.apache.activemq.artemis.core.postoffice; +import java.util.List; import java.util.Map; import java.util.Set; @@ -50,6 +51,8 @@ public interface PostOffice extends ActiveMQComponent { AddressInfo getAddressInfo(SimpleString address); + List<Queue> listQueuesForAddress(SimpleString address) throws Exception; + void addBinding(Binding binding) throws Exception; Binding removeBinding(SimpleString uniqueName, Transaction tx, boolean deleteData) throws Exception; http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b441b74/artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/impl/PostOfficeImpl.java ---------------------------------------------------------------------- diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/impl/PostOfficeImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/impl/PostOfficeImpl.java index 52abcdb..3064363 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/impl/PostOfficeImpl.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/impl/PostOfficeImpl.java @@ -54,6 +54,7 @@ import org.apache.activemq.artemis.core.postoffice.Bindings; import org.apache.activemq.artemis.core.postoffice.BindingsFactory; import org.apache.activemq.artemis.core.postoffice.DuplicateIDCache; import org.apache.activemq.artemis.core.postoffice.PostOffice; +import org.apache.activemq.artemis.core.postoffice.QueueBinding; import org.apache.activemq.artemis.core.postoffice.QueueInfo; import org.apache.activemq.artemis.core.postoffice.RoutingStatus; import org.apache.activemq.artemis.core.server.ActiveMQMessageBundle; @@ -131,6 +132,8 @@ public class PostOfficeImpl implements PostOffice, NotificationListener, Binding private final ActiveMQServer server; + private Object addressLock = new Object(); + public PostOfficeImpl(final ActiveMQServer server, final StorageManager storageManager, final PagingManager pagingManager, @@ -420,39 +423,61 @@ public class PostOfficeImpl implements PostOffice, NotificationListener, Binding @Override public AddressInfo addAddressInfo(AddressInfo addressInfo) { - try { - managementService.registerAddress(addressInfo); - } catch (Exception e) { - e.printStackTrace(); + synchronized (addressLock) { + try { + managementService.registerAddress(addressInfo); + } catch (Exception e) { + e.printStackTrace(); + } + return addressManager.addAddressInfo(addressInfo); } - return addressManager.addAddressInfo(addressInfo); } @Override public AddressInfo addOrUpdateAddressInfo(AddressInfo addressInfo) { - try { - managementService.registerAddress(addressInfo); - } catch (Exception e) { - e.printStackTrace(); + synchronized (addressLock) { + try { + managementService.registerAddress(addressInfo); + } catch (Exception e) { + e.printStackTrace(); + } + return addressManager.addOrUpdateAddressInfo(addressInfo); } - return addressManager.addOrUpdateAddressInfo(addressInfo); } @Override public AddressInfo removeAddressInfo(SimpleString address) throws Exception { - Bindings bindingsForAddress = getBindingsForAddress(address); - if (bindingsForAddress.getBindings().size() > 0) { - throw new IllegalStateException("Address has bindings"); + synchronized (addressLock) { + Bindings bindingsForAddress = getBindingsForAddress(address); + if (bindingsForAddress.getBindings().size() > 0) { + throw new IllegalStateException("Address has bindings"); + } + managementService.unregisterAddress(address); + return addressManager.removeAddressInfo(address); } - managementService.unregisterAddress(address); - return addressManager.removeAddressInfo(address); } @Override public AddressInfo getAddressInfo(SimpleString addressName) { - return addressManager.getAddressInfo(addressName); + synchronized (addressLock) { + return addressManager.getAddressInfo(addressName); + } } + @Override + public List<Queue> listQueuesForAddress(SimpleString address) throws Exception { + Bindings bindingsForAddress = getBindingsForAddress(address); + List<Queue> queues = new ArrayList<>(); + for (Binding b : bindingsForAddress.getBindings()) { + if (b instanceof QueueBinding) { + Queue q = ((QueueBinding) b).getQueue(); + queues.add(q); + } + } + return queues; + } + + // TODO - needs to be synchronized to prevent happening concurrently with activate() // (and possible removeBinding and other methods) // Otherwise can have situation where createQueue comes in before failover, then failover occurs http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b441b74/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQMessageBundle.java ---------------------------------------------------------------------- diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQMessageBundle.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQMessageBundle.java index a64e4fc..5d39df0 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQMessageBundle.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQMessageBundle.java @@ -18,9 +18,12 @@ package org.apache.activemq.artemis.core.server; import java.io.File; +import org.apache.activemq.artemis.api.core.ActiveMQAddressDoesNotExistException; +import org.apache.activemq.artemis.api.core.ActiveMQAddressExistsException; import org.apache.activemq.artemis.api.core.ActiveMQAddressFullException; import org.apache.activemq.artemis.api.core.ActiveMQClusterSecurityException; import org.apache.activemq.artemis.api.core.ActiveMQConnectionTimedOutException; +import org.apache.activemq.artemis.api.core.ActiveMQDeleteAddressException; import org.apache.activemq.artemis.api.core.ActiveMQDisconnectedException; import org.apache.activemq.artemis.api.core.ActiveMQDuplicateMetaDataException; import org.apache.activemq.artemis.api.core.ActiveMQException; @@ -392,5 +395,11 @@ public interface ActiveMQMessageBundle { ActiveMQInvalidQueueConfiguration invalidQueueConfiguration(SimpleString address, SimpleString queueName, String queuePropertyName, Object expectedValue, Object actualValue); @Message(id = 119203, value = "Address Does Not Exist: {0}", format = Message.Format.MESSAGE_FORMAT) - ActiveMQInvalidQueueConfiguration addressDoesNotExist(SimpleString address); + ActiveMQAddressDoesNotExistException addressDoesNotExist(SimpleString address); + + @Message(id = 119204, value = "Address already exists: {0}", format = Message.Format.MESSAGE_FORMAT) + ActiveMQAddressExistsException addressAlreadyExists(SimpleString address); + + @Message(id = 119205, value = "Address {0} has bindings", format = Message.Format.MESSAGE_FORMAT) + ActiveMQDeleteAddressException addressHasBindings(SimpleString address); } http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b441b74/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServer.java ---------------------------------------------------------------------- diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServer.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServer.java index 723ddf4..c45be50 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServer.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServer.java @@ -22,6 +22,7 @@ import java.util.Set; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import com.google.common.collect.Queues; import org.apache.activemq.artemis.api.core.SimpleString; import org.apache.activemq.artemis.core.config.BridgeConfiguration; import org.apache.activemq.artemis.core.config.Configuration; @@ -114,6 +115,12 @@ public interface ActiveMQServer extends ActiveMQComponent { */ ActiveMQServerControlImpl getActiveMQServerControl(); + void destroyQueue(SimpleString queueName, + SecurityAuth session, + boolean checkConsumerCount, + boolean removeConsumers, + boolean autoDeleteAddress) throws Exception; + void registerActivateCallback(ActivateCallback callback); void unregisterActivateCallback(ActivateCallback callback); @@ -448,6 +455,8 @@ public interface ActiveMQServer extends ActiveMQComponent { AddressInfo putAddressInfoIfAbsent(AddressInfo addressInfo) throws Exception; + void createAddressInfo(AddressInfo addressInfo) throws Exception; + AddressInfo createOrUpdateAddressInfo(AddressInfo addressInfo) throws Exception; void removeAddressInfo(SimpleString address) throws Exception; http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b441b74/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/Queue.java ---------------------------------------------------------------------- diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/Queue.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/Queue.java index 0120a53..2b845d5 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/Queue.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/Queue.java @@ -106,8 +106,6 @@ public interface Queue extends Bindable { void deleteQueue(boolean removeConsumers) throws Exception; - void deleteQueue(boolean removeConsumers, boolean autoDeleteAddress) throws Exception; - void destroyPaging() throws Exception; long getMessageCount(); http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b441b74/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java ---------------------------------------------------------------------- diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java index 1e1424d..5ab6ef7 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java @@ -48,6 +48,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration; +import org.apache.activemq.artemis.api.core.ActiveMQDeleteAddressException; import org.apache.activemq.artemis.api.core.Pair; import org.apache.activemq.artemis.api.core.SimpleString; import org.apache.activemq.artemis.core.client.impl.ClientSessionFactoryImpl; @@ -1555,7 +1556,7 @@ public class ActiveMQServerImpl implements ActiveMQServer { public void destroyQueue(final SimpleString queueName, final SecurityAuth session, final boolean checkConsumerCount) throws Exception { - destroyQueue(queueName, session, checkConsumerCount, false); + destroyQueue(queueName, session, checkConsumerCount, false, true); } @Override @@ -1563,6 +1564,15 @@ public class ActiveMQServerImpl implements ActiveMQServer { final SecurityAuth session, final boolean checkConsumerCount, final boolean removeConsumers) throws Exception { + destroyQueue(queueName, session, checkConsumerCount, removeConsumers, true); + } + + @Override + public void destroyQueue(final SimpleString queueName, + final SecurityAuth session, + final boolean checkConsumerCount, + final boolean removeConsumers, + final boolean autoDeleteAddress) throws Exception { if (postOffice == null) { return; } @@ -1596,6 +1606,14 @@ public class ActiveMQServerImpl implements ActiveMQServer { queue.deleteQueue(removeConsumers); + if (autoDeleteAddress && postOffice != null) { + try { + postOffice.removeAddressInfo(address); + } catch (ActiveMQDeleteAddressException e) { + // Could be thrown if the address has bindings or is not deletable. + } + } + callPostQueueDeletionCallbacks(address, queueName); } @@ -1870,7 +1888,6 @@ public class ActiveMQServerImpl implements ActiveMQServer { } this.executorFactory = new OrderedExecutorFactory(threadPool); - if (serviceRegistry.getIOExecutorService() != null) { this.ioExecutorFactory = new OrderedExecutorFactory(serviceRegistry.getIOExecutorService()); } else { @@ -2036,15 +2053,15 @@ public class ActiveMQServerImpl implements ActiveMQServer { // Deploy any predefined queues deployQueuesFromConfiguration(); - registerPostQueueDeletionCallback(new PostQueueDeletionCallback() { - // TODO delete auto-created addresses when queueCount == 0 - @Override - public void callback(SimpleString address, SimpleString queueName) throws Exception { - if (getAddressInfo(address).isAutoCreated() && postOffice.getBindingsForAddress(address).getBindings().size() == 0) { - removeAddressInfo(address); - } - } - }); + // registerPostQueueDeletionCallback(new PostQueueDeletionCallback() { + // // TODO delete auto-created addresses when queueCount == 0 + // @Override + // public void callback(SimpleString address, SimpleString queueName) throws Exception { + // if (getAddressInfo(address).isAutoCreated()) { + // removeAddressInfo(address); + // } + // } + // }); // We need to call this here, this gives any dependent server a chance to deploy its own addresses // this needs to be done before clustering is fully activated @@ -2251,6 +2268,13 @@ public class ActiveMQServerImpl implements ActiveMQServer { } @Override + public void createAddressInfo(AddressInfo addressInfo) throws Exception { + if (putAddressInfoIfAbsent(addressInfo) != null) { + throw ActiveMQMessageBundle.BUNDLE.addressAlreadyExists(addressInfo.getName()); + } + } + + @Override public AddressInfo createOrUpdateAddressInfo(AddressInfo addressInfo) throws Exception { AddressInfo result = postOffice.addOrUpdateAddressInfo(addressInfo); @@ -2264,12 +2288,14 @@ public class ActiveMQServerImpl implements ActiveMQServer { @Override public void removeAddressInfo(SimpleString address) throws Exception { - postOffice.removeAddressInfo(address); + if (postOffice.removeAddressInfo(address) == null) { + throw ActiveMQMessageBundle.BUNDLE.addressDoesNotExist(address); + }; // TODO: is this the right way to do this? -// long txID = storageManager.generateID(); -// storageManager.deleteAddressBinding(txID, getAddressInfo(address).getID()); -// storageManager.commitBindings(txID); + // long txID = storageManager.generateID(); + // storageManager.deleteAddressBinding(txID, getAddressInfo(address).getID()); + // storageManager.commitBindings(txID); } @@ -2292,18 +2318,7 @@ public class ActiveMQServerImpl implements ActiveMQServer { final boolean ignoreIfExists, final boolean transientQueue, final boolean autoCreated) throws Exception { - return createQueue(addressName, - queueName, - filterString, - user, - durable, - temporary, - ignoreIfExists, - transientQueue, - autoCreated, - null, - null, - true); + return createQueue(addressName, queueName, filterString, user, durable, temporary, ignoreIfExists, transientQueue, autoCreated, null, null, true); } @Override @@ -2347,8 +2362,7 @@ public class ActiveMQServerImpl implements ActiveMQServer { if (info == null) { if (autoCreateAddress) { info = defaultAddressInfo; - } - else { + } else { throw ActiveMQMessageBundle.BUNDLE.addressDoesNotExist(addressName); } } @@ -2356,24 +2370,13 @@ public class ActiveMQServerImpl implements ActiveMQServer { final boolean isDeleteOnNoConsumers = deleteOnNoConsumers == null ? info.isDefaultDeleteOnNoConsumers() : deleteOnNoConsumers; final int noMaxConsumers = maxConsumers == null ? info.getDefaultMaxQueueConsumers() : maxConsumers; - final QueueConfig queueConfig = queueConfigBuilder - .filter(filter) - .pagingManager(pagingManager) - .user(user) - .durable(durable) - .temporary(temporary) - .autoCreated(autoCreated) - .deleteOnNoConsumers(isDeleteOnNoConsumers) - .maxConsumers(noMaxConsumers) - .build(); + final QueueConfig queueConfig = queueConfigBuilder.filter(filter).pagingManager(pagingManager).user(user).durable(durable).temporary(temporary).autoCreated(autoCreated).deleteOnNoConsumers(isDeleteOnNoConsumers).maxConsumers(noMaxConsumers).build(); final Queue queue = queueFactory.createQueueWith(queueConfig); boolean addressAlreadyExists = true; if (postOffice.getAddressInfo(queue.getAddress()) == null) { - postOffice.addAddressInfo(new AddressInfo(queue.getAddress()) - .setRoutingType(AddressInfo.RoutingType.MULTICAST) - .setDefaultMaxQueueConsumers(maxConsumers == null ? ActiveMQDefaultConfiguration.getDefaultMaxQueueConsumers() : maxConsumers)); + postOffice.addAddressInfo(new AddressInfo(queue.getAddress()).setRoutingType(AddressInfo.RoutingType.MULTICAST).setDefaultMaxQueueConsumers(maxConsumers == null ? ActiveMQDefaultConfiguration.getDefaultMaxQueueConsumers() : maxConsumers)); addressAlreadyExists = false; } http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b441b74/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/AddressInfo.java ---------------------------------------------------------------------- diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/AddressInfo.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/AddressInfo.java index 6ad40fa..a92e8d3 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/AddressInfo.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/AddressInfo.java @@ -31,6 +31,8 @@ public class AddressInfo { private boolean autoCreated = false; + private boolean deletable = false; + public AddressInfo(SimpleString name) { this.name = name; } @@ -85,7 +87,7 @@ public class AddressInfo { @Override public String toString() { StringBuffer buff = new StringBuffer(); - buff.append("AddressInfo [name=" + name); + buff.append("Address [name=" + name); buff.append(", routingType=" + routingType); buff.append(", defaultMaxQueueConsumers=" + defaultMaxQueueConsumers); buff.append(", defaultDeleteOnNoConsumers=" + defaultDeleteOnNoConsumers); http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b441b74/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/QueueImpl.java ---------------------------------------------------------------------- diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/QueueImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/QueueImpl.java index b9cb79f..f6da245 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/QueueImpl.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/QueueImpl.java @@ -1420,11 +1420,6 @@ public class QueueImpl implements Queue { @Override public void deleteQueue(boolean removeConsumers) throws Exception { - deleteQueue(removeConsumers, false); - } - - @Override - public void deleteQueue(boolean removeConsumers, boolean autoDeleteAddress) throws Exception { synchronized (this) { if (this.queueDestroyed) return; @@ -1892,6 +1887,7 @@ public class QueueImpl implements Queue { return "QueueImpl[name=" + name.toString() + ", postOffice=" + this.postOffice + ", temp=" + this.temporary + "]@" + Integer.toHexString(System.identityHashCode(this)); } + private synchronized void internalAddTail(final MessageReference ref) { refAdded(ref); messageReferences.addTail(ref, getPriority(ref)); http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b441b74/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cli/AddressCommandTest.java ---------------------------------------------------------------------- diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cli/AddressCommandTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cli/AddressCommandTest.java new file mode 100644 index 0000000..9589f47 --- /dev/null +++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cli/AddressCommandTest.java @@ -0,0 +1,155 @@ +/* + * 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. + */ +package org.apache.activemq.artemis.tests.integration.cli; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.UUID; + +import org.apache.activemq.artemis.api.core.SimpleString; +import org.apache.activemq.artemis.cli.commands.AbstractAction; +import org.apache.activemq.artemis.cli.commands.ActionContext; +import org.apache.activemq.artemis.cli.commands.address.CreateAddress; +import org.apache.activemq.artemis.cli.commands.address.DeleteAddress; +import org.apache.activemq.artemis.cli.commands.address.ShowAddress; +import org.apache.activemq.artemis.cli.commands.queue.CreateQueue; +import org.apache.activemq.artemis.cli.commands.queue.DeleteQueue; +import org.apache.activemq.artemis.core.config.DivertConfiguration; +import org.apache.activemq.artemis.core.server.Queue; +import org.apache.activemq.artemis.core.server.impl.AddressInfo; +import org.apache.activemq.artemis.tests.util.JMSTestBase; +import org.junit.Before; +import org.junit.Test; + +public class AddressCommandTest extends JMSTestBase { + + //the command + private ByteArrayOutputStream output; + private ByteArrayOutputStream error; + + @Before + @Override + public void setUp() throws Exception { + super.setUp(); + this.output = new ByteArrayOutputStream(1024); + this.error = new ByteArrayOutputStream(1024); + } + + @Test + public void testCreateAddress() throws Exception { + String address = "address"; + CreateAddress command = new CreateAddress(); + command.setName(address); + command.execute(new ActionContext(System.in, new PrintStream(output), new PrintStream(error))); + checkExecutionPassed(command); + assertNotNull(server.getAddressInfo(new SimpleString(address))); + } + + @Test + public void testCreateAddressAlreadyExistsShowsError() throws Exception { + String address = "address"; + CreateAddress command = new CreateAddress(); + command.setName(address); + command.execute(new ActionContext(System.in, new PrintStream(output), new PrintStream(error))); + checkExecutionPassed(command); + assertNotNull(server.getAddressInfo(new SimpleString(address))); + + command.execute(new ActionContext(System.in, new PrintStream(output), new PrintStream(error))); + checkExecutionFailure(command, "Address already exists"); + } + + @Test + public void testDeleteAddress() throws Exception { + String address = "address"; + CreateAddress command = new CreateAddress(); + command.setName(address); + command.execute(new ActionContext()); + assertNotNull(server.getAddressInfo(new SimpleString(address))); + + DeleteAddress deleteAddress = new DeleteAddress(); + deleteAddress.setName(address); + deleteAddress.execute(new ActionContext(System.in, new PrintStream(output), new PrintStream(error))); + checkExecutionPassed(deleteAddress); + assertNull(server.getAddressInfo(new SimpleString(address))); + } + + @Test + public void testDeleteAddressDoesNotExistsShowsError() throws Exception { + String address = "address"; + DeleteAddress deleteAddress = new DeleteAddress(); + deleteAddress.setName(address); + deleteAddress.execute(new ActionContext(System.in, new PrintStream(output), new PrintStream(error))); + checkExecutionFailure(deleteAddress, "Address Does Not Exist"); + } + + @Test + public void testShowAddress() throws Exception { + String address = "address"; + CreateAddress command = new CreateAddress(); + command.setName(address); + command.execute(new ActionContext()); + assertNotNull(server.getAddressInfo(new SimpleString(address))); + + ShowAddress showAddress = new ShowAddress(); + showAddress.setName(address); + showAddress.execute(new ActionContext(System.in, new PrintStream(output), new PrintStream(error))); + System.out.println(output.toString()); + } + + @Test + public void testShowAddressDoesNotExist() throws Exception { + String address = "address"; + ShowAddress showAddress = new ShowAddress(); + showAddress.setName(address); + showAddress.execute(new ActionContext(System.in, new PrintStream(output), new PrintStream(error))); + checkExecutionFailure(showAddress, "Address Does Not Exist"); + } + + @Test + public void testShowAddressBindings() throws Exception { + + // Create bindings + SimpleString address = new SimpleString("address"); + server.createAddressInfo(new AddressInfo(address)); + server.createQueue(address, new SimpleString("queue1"), null, true, false); + server.createQueue(address, new SimpleString("queue2"), null, true, false); + server.createQueue(address, new SimpleString("queue3"), null, true, false); + + DivertConfiguration divertConfiguration = new DivertConfiguration(); + divertConfiguration.setName(address.toString()); + divertConfiguration.setAddress(address.toString()); + server.deployDivert(divertConfiguration); + + ShowAddress showAddress = new ShowAddress(); + showAddress.setName(address.toString()); + showAddress.setBindings(true); + showAddress.execute(new ActionContext(System.in, new PrintStream(output), new PrintStream(error))); + System.out.println(output.toString()); + } + + private void checkExecutionPassed(AbstractAction command) throws Exception { + String fullMessage = output.toString(); + System.out.println("output: " + fullMessage); + assertTrue(fullMessage, fullMessage.contains("successfully")); + } + + private void checkExecutionFailure(AbstractAction command, String message) throws Exception { + String fullMessage = error.toString(); + System.out.println("error: " + fullMessage); + assertTrue(fullMessage, fullMessage.contains(message)); + } +} http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b441b74/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cli/QueueCommandTest.java ---------------------------------------------------------------------- diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cli/QueueCommandTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cli/QueueCommandTest.java index 9d63439..5d7a695 100644 --- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cli/QueueCommandTest.java +++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cli/QueueCommandTest.java @@ -24,7 +24,7 @@ import org.apache.activemq.artemis.api.core.SimpleString; import org.apache.activemq.artemis.cli.commands.ActionContext; import org.apache.activemq.artemis.cli.commands.queue.CreateQueue; import org.apache.activemq.artemis.cli.commands.queue.DeleteQueue; -import org.apache.activemq.artemis.cli.commands.queue.QueueAction; +import org.apache.activemq.artemis.cli.commands.AbstractAction; import org.apache.activemq.artemis.core.server.Queue; import org.apache.activemq.artemis.core.server.impl.AddressInfo; import org.apache.activemq.artemis.tests.util.JMSTestBase; @@ -209,17 +209,18 @@ public class QueueCommandTest extends JMSTestBase { delete.setRemoveConsumers(true); delete.setAutoDeleteAddress(true); delete.execute(new ActionContext(System.in, new PrintStream(output), new PrintStream(error))); + checkExecutionPassed(command); assertNull(server.getAddressInfo(queueName)); } - private void checkExecutionPassed(QueueAction command) throws Exception { + private void checkExecutionPassed(AbstractAction command) throws Exception { String fullMessage = output.toString(); System.out.println("output: " + fullMessage); assertTrue(fullMessage, fullMessage.contains("successfully")); } - private void checkExecutionFailure(QueueAction command, String message) throws Exception { + private void checkExecutionFailure(AbstractAction command, String message) throws Exception { String fullMessage = error.toString(); System.out.println("error: " + fullMessage); assertTrue(fullMessage, fullMessage.contains(message)); http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b441b74/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlUsingCoreTest.java ---------------------------------------------------------------------- diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlUsingCoreTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlUsingCoreTest.java index bac0784..2547bb6 100644 --- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlUsingCoreTest.java +++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlUsingCoreTest.java @@ -16,6 +16,7 @@ */ package org.apache.activemq.artemis.tests.integration.management; +import org.apache.activemq.artemis.api.core.ActiveMQAddressDoesNotExistException; import org.apache.activemq.artemis.api.core.management.ActiveMQServerControl; import org.apache.activemq.artemis.api.core.management.Parameter; import org.apache.activemq.artemis.api.core.management.ResourceNames; @@ -104,6 +105,14 @@ public class ActiveMQServerControlUsingCoreTest extends ActiveMQServerControlTes } @Override + public void createAddress(@Parameter(name = "name", desc = "The name of the address") String name, + @Parameter(name = "routingType", desc = "The routing type for the address either 'MULTICAST' or 'ANYCAST'") String routingType, + @Parameter(name = "defaultDeleteOnNoConsumers", desc = "Whether or not a queue with this address is deleted when it has no consumers") boolean defaultDeleteOnNoConsumers, + @Parameter(name = "defaultMaxConsumers", desc = "The maximim number of consumer a queue with this address can have") int defaultMaxConsumers) throws Exception { + proxy.invokeOperation("createAddress", name, routingType, defaultDeleteOnNoConsumers, defaultMaxConsumers); + } + + @Override public void deleteAddress(@Parameter(name = "name", desc = "The name of the address") String name) throws Exception { proxy.invokeOperation("deleteAddress", name); } @@ -156,6 +165,12 @@ public class ActiveMQServerControlUsingCoreTest extends ActiveMQServerControlTes } @Override + public void destroyQueue(@Parameter(name = "name", desc = "Name of the queue to destroy") String name, + @Parameter(name = "removeConsumers", desc = "Remove consumers of this queue") boolean removeConsumers, + boolean autoDeleteAddress) throws Exception { + } + + @Override public void disableMessageCounters() throws Exception { proxy.invokeOperation("disableMessageCounters"); } @@ -643,6 +658,16 @@ public class ActiveMQServerControlUsingCoreTest extends ActiveMQServerControlTes } @Override + public String getAddressInfo(String address) throws ActiveMQAddressDoesNotExistException { + return null; + } + + @Override + public String[] listBindingsForAddress(String address) throws Exception { + return new String[0]; + } + + @Override public void removeAddressSettings(String addressMatch) throws Exception { proxy.invokeOperation("removeAddressSettings", addressMatch); } http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b441b74/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/server/impl/fakes/FakePostOffice.java ---------------------------------------------------------------------- diff --git a/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/server/impl/fakes/FakePostOffice.java b/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/server/impl/fakes/FakePostOffice.java index 35fe5cc..f2c844e 100644 --- a/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/server/impl/fakes/FakePostOffice.java +++ b/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/server/impl/fakes/FakePostOffice.java @@ -16,6 +16,7 @@ */ package org.apache.activemq.artemis.tests.unit.core.server.impl.fakes; +import java.util.List; import java.util.Map; import java.util.Set; @@ -81,6 +82,11 @@ public class FakePostOffice implements PostOffice { } @Override + public List<Queue> listQueuesForAddress(SimpleString address) throws Exception { + return null; + } + + @Override public void addBinding(final Binding binding) throws Exception { }
