ARTEMIS-670 Adding destination creation and deletion cli commands

This commit is contained in:
Howard Gao 2016-08-10 21:23:25 +08:00 committed by Clebert Suconic
parent ecff3e3ecf
commit 76e7992906
6 changed files with 711 additions and 1 deletions

View File

@ -27,7 +27,10 @@ import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.commands.Browse;
import org.apache.activemq.artemis.cli.commands.Consumer;
import org.apache.activemq.artemis.cli.commands.Create;
import org.apache.activemq.artemis.cli.commands.CreateDestination;
import org.apache.activemq.artemis.cli.commands.DeleteDestination;
import org.apache.activemq.artemis.cli.commands.HelpAction;
import org.apache.activemq.artemis.cli.commands.HelpDestination;
import org.apache.activemq.artemis.cli.commands.Kill;
import org.apache.activemq.artemis.cli.commands.Producer;
import org.apache.activemq.artemis.cli.commands.Run;
@ -112,8 +115,15 @@ public class Artemis {
private static Cli.CliBuilder<Action> builder(File artemisInstance) {
String instance = artemisInstance != null ? artemisInstance.getAbsolutePath() : System.getProperty("artemis.instance");
Cli.CliBuilder<Action> builder = Cli.<Action>builder("artemis").withDescription("ActiveMQ Artemis Command Line").withCommand(HelpAction.class).withCommand(Producer.class).withCommand(Consumer.class).withCommand(Browse.class).withDefaultCommand(HelpAction.class);
Cli.CliBuilder<Action> builder = Cli.<Action>builder("artemis").withDescription("ActiveMQ Artemis Command Line")
.withCommand(HelpAction.class)
.withCommand(Producer.class)
.withCommand(Consumer.class)
.withCommand(Browse.class)
.withDefaultCommand(HelpAction.class);
builder.withGroup("destination").withDescription("Destination tools group (create|delete) (example ./artemis destination create)").
withDefaultCommand(HelpDestination.class).withCommands(CreateDestination.class, DeleteDestination.class);
if (instance != null) {
builder.withGroup("data").withDescription("data tools group (print|exp|imp|exp|encode|decode|compact) (example ./artemis data print)").
withDefaultCommand(HelpData.class).withCommands(PrintData.class, XmlDataExporter.class, XmlDataImporter.class, DecodeJournal.class, EncodeJournal.class, CompactJournal.class);

View File

@ -0,0 +1,151 @@
/*
* 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.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.api.jms.management.JMSManagementHelper;
import javax.jms.Message;
@Command(name = "create", description = "create a queue or topic")
public class CreateDestination extends DestinationAction {
@Option(name = "--filter", description = "queue's filter string (default null)")
String filter = null;
@Option(name = "--address", description = "address of the core queue (default queue's name)")
String address;
@Option(name = "--durable", description = "whether the queue is durable or not (default false)")
boolean durable = false;
@Option(name = "--bindings", description = "comma separated jndi binding names (default null)")
String bindings = null;
@Override
public Object execute(ActionContext context) throws Exception {
super.execute(context);
if (JMS_QUEUE.equals(destType)) {
createJmsQueue(context);
}
else if (CORE_QUEUE.equals(destType)) {
createCoreQueue(context);
}
else if (JMS_TOPIC.equals(destType)) {
createJmsTopic(context);
}
else {
throw new IllegalArgumentException("--type can only be one of " + JMS_QUEUE + ", " + JMS_TOPIC + " and " + CORE_QUEUE);
}
return null;
}
private void createJmsTopic(final ActionContext context) throws Exception {
performJmsManagement(brokerURL, user, password, new ManagementCallback<Message>() {
@Override
public void setUpInvocation(Message message) throws Exception {
JMSManagementHelper.putOperationInvocation(message, "jms.server", "createTopic", name, bindings);
}
@Override
public void requestSuccessful(Message reply) throws Exception {
boolean result = (boolean) JMSManagementHelper.getResult(reply, Boolean.class);
if (result) {
context.out.println("Topic " + name + " created successfully.");
}
else {
context.err.println("Failed to create topic " + name + ".");
}
}
@Override
public void requestFailed(Message reply) throws Exception {
String errorMsg = (String) JMSManagementHelper.getResult(reply, String.class);
context.err.println("Failed to create topic " + name + ". Reason: " + errorMsg);
}
});
}
public String getAddress() {
if (address == null || "".equals(address.trim())) {
address = name;
}
return address.trim();
}
private void createCoreQueue(final ActionContext context) throws Exception {
performCoreManagement(brokerURL, user, password, new ManagementCallback<ClientMessage>() {
@Override
public void setUpInvocation(ClientMessage message) throws Exception {
String address = getAddress();
ManagementHelper.putOperationInvocation(message, "core.server", "createQueue", address, name, filter, durable);
}
@Override
public void requestSuccessful(ClientMessage reply) throws Exception {
context.out.println("Core queue " + name + " 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 " + name + ". Reason: " + errMsg);
}
});
}
private void createJmsQueue(final ActionContext context) throws Exception {
performJmsManagement(brokerURL, user, password, new ManagementCallback<Message>() {
@Override
public void setUpInvocation(Message message) throws Exception {
JMSManagementHelper.putOperationInvocation(message, "jms.server", "createQueue", name, bindings, filter, durable);
}
@Override
public void requestSuccessful(Message reply) throws Exception {
boolean result = (boolean) JMSManagementHelper.getResult(reply, Boolean.class);
if (result) {
context.out.println("Jms queue " + name + " created successfully.");
}
else {
context.err.println("Failed to create jms queue " + name + ".");
}
}
@Override
public void requestFailed(Message reply) throws Exception {
String errorMsg = (String) JMSManagementHelper.getResult(reply, String.class);
context.err.println("Failed to create jms queue " + name + ". Reason: " + errorMsg);
}
});
}
public void setFilter(String filter) {
this.filter = filter;
}
public void setBindings(String bindings) {
this.bindings = bindings;
}
}

View File

@ -0,0 +1,125 @@
/*
* 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.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.api.jms.management.JMSManagementHelper;
import javax.jms.Message;
@Command(name = "delete", description = "delete a queue or topic")
public class DeleteDestination extends DestinationAction {
@Option(name = "--removeConsumers", description = "whether deleting destination with consumers or not (default false)")
boolean removeConsumers = false;
@Override
public Object execute(ActionContext context) throws Exception {
super.execute(context);
if (JMS_QUEUE.equals(destType)) {
deleteJmsQueue(context);
}
else if (CORE_QUEUE.equals(destType)) {
deleteCoreQueue(context);
}
else if (JMS_TOPIC.equals(destType)) {
deleteJmsTopic(context);
}
else {
throw new IllegalArgumentException("--type can only be one of " + JMS_QUEUE + ", " + JMS_TOPIC + " and " + CORE_QUEUE);
}
return null;
}
private void deleteJmsTopic(final ActionContext context) throws Exception {
performJmsManagement(brokerURL, user, password, new ManagementCallback<Message>() {
@Override
public void setUpInvocation(Message message) throws Exception {
JMSManagementHelper.putOperationInvocation(message, "jms.server", "destroyTopic", name, removeConsumers);
}
@Override
public void requestSuccessful(Message reply) throws Exception {
boolean result = (boolean) JMSManagementHelper.getResult(reply, Boolean.class);
if (result) {
context.out.println("Topic " + name + " deleted successfully.");
}
else {
context.err.println("Failed to delete topic " + name);
}
}
@Override
public void requestFailed(Message reply) throws Exception {
String errorMsg = (String) JMSManagementHelper.getResult(reply, String.class);
context.err.println("Failed to delete topic " + name + ". Reason: " + errorMsg);
}
});
}
private void deleteJmsQueue(final ActionContext context) throws Exception {
performJmsManagement(brokerURL, user, password, new ManagementCallback<Message>() {
@Override
public void setUpInvocation(Message message) throws Exception {
JMSManagementHelper.putOperationInvocation(message, "jms.server", "destroyQueue", name, removeConsumers);
}
@Override
public void requestSuccessful(Message reply) throws Exception {
boolean result = (boolean) JMSManagementHelper.getResult(reply, Boolean.class);
if (result) {
context.out.println("Jms queue " + name + " deleted successfully.");
}
else {
context.err.println("Failed to delete queue " + name);
}
}
@Override
public void requestFailed(Message reply) throws Exception {
String errorMsg = (String) JMSManagementHelper.getResult(reply, String.class);
context.err.println("Failed to create " + name + " with reason: " + errorMsg);
}
});
}
private void deleteCoreQueue(final ActionContext context) throws Exception {
performCoreManagement(brokerURL, user, password, new ManagementCallback<ClientMessage>() {
@Override
public void setUpInvocation(ClientMessage message) throws Exception {
ManagementHelper.putOperationInvocation(message, "core.server", "destroyQueue", name);
}
@Override
public void requestSuccessful(ClientMessage reply) throws Exception {
context.out.println("Queue " + name + " 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 " + name + ". Reason: " + errMsg);
}
});
}
}

View File

@ -0,0 +1,142 @@
/*
* 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.api.jms.ActiveMQJMSClient;
import org.apache.activemq.artemis.api.jms.management.JMSManagementHelper;
import org.apache.activemq.artemis.core.client.impl.ServerLocatorImpl;
import org.apache.activemq.artemis.jms.client.ActiveMQConnection;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.jms.client.ActiveMQSession;
import javax.jms.Message;
import javax.jms.Queue;
import javax.jms.QueueRequestor;
import javax.jms.Session;
public abstract class DestinationAction extends ActionAbstract {
public static final String JMS_QUEUE = "jms-queue";
public static final String JMS_TOPIC = "topic";
public static final String CORE_QUEUE = "core-queue";
@Option(name = "--type", description = "type of destination to be created (one of jms-queue, topic and core-queue, default jms-queue")
String destType = JMS_QUEUE;
@Option(name = "--url", description = "URL towards the broker. (default: tcp://localhost:61616)")
String brokerURL = "tcp://localhost:61616";
@Option(name = "--user", description = "User used to connect")
String user;
@Option(name = "--password", description = "Password used to connect")
String password;
@Option(name = "--name", description = "destination name", required = true)
String name;
public static void performJmsManagement(String brokerURL, String user, String password, ManagementCallback<Message> cb) throws Exception {
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(brokerURL, user, password);
ActiveMQConnection connection = (ActiveMQConnection) factory.createConnection();
ActiveMQSession session = (ActiveMQSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue managementQueue = ActiveMQJMSClient.createQueue("activemq.management");
QueueRequestor requestor = new QueueRequestor(session, managementQueue);
try {
connection.start();
Message message = session.createMessage();
cb.setUpInvocation(message);
Message reply = requestor.request(message);
boolean result = JMSManagementHelper.hasOperationSucceeded(reply);
if (result) {
cb.requestSuccessful(reply);
}
else {
cb.requestFailed(reply);
}
}
finally {
connection.close();
}
}
public static void performCoreManagement(String brokerURL, String user, String password, ManagementCallback<ClientMessage> cb) throws Exception {
ServerLocator locator = ServerLocatorImpl.newLocator(brokerURL);
ClientSessionFactory sessionFactory = locator.createSessionFactory();
ClientSession session = sessionFactory.createSession(user, password, false, true, true, false, ActiveMQClient.DEFAULT_ACK_BATCH_SIZE);
try {
session.start();
ClientRequestor requestor = new ClientRequestor(session, "jms.queue.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);
}
}
finally {
session.close();
sessionFactory.close();
}
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String getDestType() {
return destType;
}
public void setDestType(String destType) {
this.destType = destType;
}
public interface ManagementCallback<T> {
void setUpInvocation(T message) throws Exception;
void requestSuccessful(T reply) throws Exception;
void requestFailed(T reply) throws Exception;
}
}

View File

@ -0,0 +1,54 @@
/*
* 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.Help;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class HelpDestination extends Help implements Action {
@Override
public boolean isVerbose() {
return false;
}
@Override
public void setHomeValues(File brokerHome, File brokerInstance) {
}
@Override
public String getBrokerInstance() {
return null;
}
@Override
public String getBrokerHome() {
return null;
}
@Override
public Object execute(ActionContext context) throws Exception {
List<String> commands = new ArrayList<>(1);
commands.add("destination");
help(global, commands);
return null;
}
}

View File

@ -0,0 +1,228 @@
/*
* 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 org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.commands.CreateDestination;
import org.apache.activemq.artemis.cli.commands.DeleteDestination;
import org.apache.activemq.artemis.cli.commands.DestinationAction;
import org.apache.activemq.artemis.core.filter.Filter;
import org.apache.activemq.artemis.core.postoffice.Binding;
import org.apache.activemq.artemis.tests.util.JMSTestBase;
import org.junit.Before;
import org.junit.Test;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.Map;
public class DestinationCommandTest extends JMSTestBase {
//the command
private ByteArrayOutputStream output;
private ByteArrayOutputStream error;
@Before
public void setUp() throws Exception {
super.setUp();
this.output = new ByteArrayOutputStream(1024);
this.error = new ByteArrayOutputStream(1024);
}
@Test
public void testCreateJmsQueue() throws Exception {
CreateDestination command = new CreateDestination();
command.setName("jmsQueue1");
command.setBindings("jmsQueue1Binding");
command.execute(new ActionContext(System.in, new PrintStream(output), new PrintStream(error)));
checkExecutionResult(command);
}
@Test
public void testDeleteJmsQueue() throws Exception {
CreateDestination command = new CreateDestination();
command.setName("jmsQueue1");
command.setBindings("jmsQueue1Binding");
command.execute(new ActionContext());
DeleteDestination delete = new DeleteDestination();
delete.setName("jmsQueue1");
delete.execute(new ActionContext(System.in, new PrintStream(output), new PrintStream(error)));
checkExecutionResult(delete);
}
@Test
public void testDeleteNonExistJmsQueue() throws Exception {
DeleteDestination delete = new DeleteDestination();
delete.setName("jmsQueue1NotExist");
delete.execute(new ActionContext(System.in, new PrintStream(output), new PrintStream(error)));
checkExecutionResult(delete);
}
@Test
public void testCreateJmsQueueWithFilter() throws Exception {
CreateDestination command = new CreateDestination();
command.setName("jmsQueue2");
command.setBindings("jmsQueue2Binding");
command.setFilter("color='red'");
command.execute(new ActionContext(System.in, new PrintStream(output), new PrintStream(error)));
checkExecutionResult(command);
assertTrue(checkBindingExists(command, "color='red'"));
}
@Test
public void testCreateJmsTopic() throws Exception {
CreateDestination command = new CreateDestination();
command.setDestType(DestinationAction.JMS_TOPIC);
command.setName("jmsTopic1");
command.setBindings("jmsTopic1Binding");
command.execute(new ActionContext(System.in, new PrintStream(output), new PrintStream(error)));
checkExecutionResult(command);
}
@Test
public void testDeleteJmsTopic() throws Exception {
CreateDestination command = new CreateDestination();
command.setDestType(DestinationAction.JMS_TOPIC);
command.setName("jmsTopic1");
command.setBindings("jmsTopic1Binding");
command.execute(new ActionContext());
DeleteDestination delete = new DeleteDestination();
delete.setDestType(DestinationAction.JMS_TOPIC);
delete.setName("jmsTopic1");
delete.execute(new ActionContext(System.in, new PrintStream(output), new PrintStream(error)));
checkExecutionResult(delete);
}
@Test
public void testDeleteJmsTopicNotExist() throws Exception {
DeleteDestination delete = new DeleteDestination();
delete.setDestType(DestinationAction.JMS_TOPIC);
delete.setName("jmsTopic1NotExist");
delete.execute(new ActionContext(System.in, new PrintStream(output), new PrintStream(error)));
checkExecutionResult(delete);
}
@Test
public void testCreateCoreQueue() throws Exception {
CreateDestination command = new CreateDestination();
command.setDestType(DestinationAction.CORE_QUEUE);
command.setName("coreQueue1");
command.execute(new ActionContext(System.in, new PrintStream(output), new PrintStream(error)));
checkExecutionResult(command);
}
@Test
public void testCreateCoreQueueWithFilter() throws Exception {
CreateDestination command = new CreateDestination();
command.setName("coreQueue2");
command.setDestType(DestinationAction.CORE_QUEUE);
command.setFilter("color='green'");
command.execute(new ActionContext(System.in, new PrintStream(output), new PrintStream(error)));
checkExecutionResult(command);
}
@Test
public void testDeleteCoreQueue() throws Exception {
CreateDestination command = new CreateDestination();
command.setName("coreQueue2");
command.setDestType(DestinationAction.CORE_QUEUE);
command.setFilter("color='green'");
command.execute(new ActionContext());
DeleteDestination delete = new DeleteDestination();
delete.setName("coreQueue2");
delete.setDestType(DestinationAction.CORE_QUEUE);
delete.execute(new ActionContext(System.in, new PrintStream(output), new PrintStream(error)));
checkExecutionResult(delete);
}
@Test
public void testDeleteCoreQueueNotExist() throws Exception {
DeleteDestination delete = new DeleteDestination();
delete.setName("coreQueue2NotExist");
delete.setDestType(DestinationAction.CORE_QUEUE);
delete.execute(new ActionContext(System.in, new PrintStream(output), new PrintStream(error)));
checkExecutionResult(delete);
}
private boolean isCreateCommand(DestinationAction command) {
return command instanceof CreateDestination;
}
private boolean isJms(DestinationAction command) {
String destType = command.getDestType();
return !DestinationAction.CORE_QUEUE.equals(destType);
}
private boolean isTopic(DestinationAction command) {
String destType = command.getDestType();
return DestinationAction.JMS_TOPIC.equals(destType);
}
private void checkExecutionResult(DestinationAction command) throws Exception {
if (isCreateCommand(command)) {
String fullMessage = output.toString();
System.out.println("output: " + fullMessage);
assertTrue(fullMessage, fullMessage.contains("successfully"));
assertTrue(checkBindingExists(command, null));
}
else {
if (command.getName().equals("jmsQueue1") || command.getName().equals("coreQueue2") || command.getName().equals("jmsTopic1")) {
String fullMessage = output.toString();
System.out.println("output: " + fullMessage);
assertTrue(fullMessage, fullMessage.contains("successfully"));
assertFalse(checkBindingExists(command, null));
}
else {
String errorMessage = error.toString();
System.out.println("error: " + errorMessage);
assertTrue(errorMessage, errorMessage.contains("Failed to"));
assertFalse(checkBindingExists(command, null));
}
}
}
private boolean checkBindingExists(DestinationAction command, String filter) {
String bindingKey = command.getName();
if (isJms(command)) {
if (isTopic(command)) {
bindingKey = "jms.topic." + bindingKey;
}
else {
bindingKey = "jms.queue." + bindingKey;
}
}
Map<SimpleString, Binding> bindings = server.getPostOffice().getAllBindings();
System.out.println("bindings: " + bindings);
Binding binding = bindings.get(new SimpleString(bindingKey));
System.out.println("got binding: " + binding);
if (binding == null) {
System.out.println("No bindings for " + bindingKey);
return false;
}
if (filter != null) {
Filter bindingFilter = binding.getFilter();
assertNotNull(bindingFilter);
assertEquals(filter, bindingFilter.getFilterString().toString());
}
return true;
}
}