diff options
Diffstat (limited to 'java/systests/src/main/java/org/apache/qpid')
12 files changed, 1536 insertions, 550 deletions
diff --git a/java/systests/src/main/java/org/apache/qpid/server/failover/MessageDisappearWithIOExceptionTest.java b/java/systests/src/main/java/org/apache/qpid/server/failover/MessageDisappearWithIOExceptionTest.java index 863aa43d22..4050637bb2 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/failover/MessageDisappearWithIOExceptionTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/failover/MessageDisappearWithIOExceptionTest.java @@ -263,7 +263,7 @@ public class MessageDisappearWithIOExceptionTest extends FailoverBaseCase implem throws Exception { //Create Connection using the default connection URL. i.e. not the Failover URL that would be used by default - _connection = (AMQConnection) getConnection(getConnectionFactory("default").getConnectionURL()); + _connection = (AMQConnection) getConnectionFactory("default").createConnection("guest", "guest"); // The default connection does not have any retries configured so // Allow this connection to retry so that we can block on the failover. // The alternative would be to use the getConnection() default. However, diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java new file mode 100644 index 0000000000..21c121ff2c --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java @@ -0,0 +1,285 @@ +/* + * 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.qpid.server.security.acl; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import javax.jms.Connection; +import javax.jms.ExceptionListener; +import javax.jms.JMSException; +import javax.naming.NamingException; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.lang.StringUtils; +import org.apache.qpid.AMQException; +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQConnectionURL; +import org.apache.qpid.jms.ConnectionListener; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.url.URLSyntaxException; + +/** + * Abstract test case for ACLs. + * + * This base class contains convenience methods to mange ACL files and implements a mechanism that allows each + * test method to run its own setup code before the broker starts. + * + * TODO move the pre broker-startup setup method invocation code to {@link QpidTestCase} + * + * @see SimpleACLTest + * @see ExternalACLTest + * @see ExternalACLFileTest + * @see ExternalACLJMXTest + * @see ExternalAdminACLTest + * @see ExhaustiveACLTest + */ +public abstract class AbstractACLTestCase extends QpidTestCase implements ConnectionListener +{ + /** Used to synchronise {@link #tearDown()} when exceptions are thrown */ + protected CountDownLatch _exceptionReceived; + + /** Override this to return the name of the configuration XML file. */ + public String getConfig() + { + return "config-systests-acl.xml"; + } + + /** Override this to setup external ACL files for virtual hosts. */ + public List<String> getHostList() + { + return Collections.emptyList(); + } + + /** + * This setup method checks {@link #getConfig()} and {@link #getHostList()} to initialise the broker with specific + * ACL configurations and then runs an optional per-test setup method, which is simply a method with the same name + * as the test, but starting with {@code setUp} rather than {@code test}. + * + * @see #setUpACLFile(String) + * @see org.apache.qpid.test.utils.QpidTestCase#setUp() + */ + @Override + public void setUp() throws Exception + { + if (QpidHome == null) + { + fail("QPID_HOME not set"); + } + + // Initialise ACLs. + _configFile = new File(QpidHome, "etc" + File.separator + getConfig()); + + // Initialise ACL files + for (String virtualHost : getHostList()) + { + setUpACLFile(virtualHost); + } + + // run test specific setup + String testSetup = StringUtils.replace(getName(), "test", "setUp"); + try + { + Method setup = getClass().getDeclaredMethod(testSetup); + setup.invoke(this); + } + catch (NoSuchMethodException e) + { + // Ignore + } + catch (InvocationTargetException e) + { + throw (Exception) e.getTargetException(); + } + + super.setUp(); + } + + @Override + public void tearDown() throws Exception + { + try + { + super.tearDown(); + } + catch (JMSException e) + { + //we're throwing this away as it can happen in this test as the state manager remembers exceptions + //that we provoked with authentication failures, where the test passes - we can ignore on con close + } + } + + /** + * Configures specific ACL files for a virtual host. + * + * This method checks for ACL files that exist on the filesystem. If dynamically generatyed ACL files are required in a test, + * then it is easier to use the {@code setUp} prefix on a method to generate the ACL file. In order, this method looks + * for three files: + * <ol> + * <li><em>virtualhost</em>-<em>class</em>-<em>test</em>.txt + * <li><em>virtualhost</em>-<em>class</em>.txt + * <li><em>virtualhost</em>-default.txt + * </ol> + * The <em>class</em> and <em>test</em> parts are the test class and method names respectively, with the word {@code test} + * removed and the rest of the text converted to lowercase. For example, the test class and method named + * {@code org.apache.qpid.test.AccessExampleTest#testExampleMethod} on the {@code testhost} virtualhost would use + * one of the following files: + * <ol> + * <li>testhost-accessexample-examplemethod.txt + * <li>testhost-accessexample.txt + * <li>testhost-default.txt + * </ol> + * These files should be copied to the <em>${QPID_HOME}/etc</em> directory when the test is run. + * + * @see #writeACLFile(String, String...) + */ + public void setUpACLFile(String virtualHost) throws IOException, ConfigurationException + { + String path = QpidHome + File.separator + "etc"; + String className = StringUtils.substringBeforeLast(getClass().getSimpleName().toLowerCase(), "test"); + String testName = StringUtils.substringAfter(getName(), "test").toLowerCase(); + + File aclFile = new File(path, virtualHost + "-" + className + "-" + testName + ".txt"); + if (!aclFile.exists()) + { + aclFile = new File(path, virtualHost + "-" + className + ".txt"); + if (!aclFile.exists()) + { + aclFile = new File(path, virtualHost + "-" + "default.txt"); + } + } + + // Set the ACL file configuration property + if (virtualHost.equals("global")) + { + setConfigurationProperty("security.aclv2", aclFile.getAbsolutePath()); + } + else + { + setConfigurationProperty("virtualhosts.virtualhost." + virtualHost + ".security.aclv2", aclFile.getAbsolutePath()); + } + } + + public void writeACLFile(String vhost, String...rules) throws ConfigurationException, IOException + { + File aclFile = File.createTempFile(getClass().getSimpleName(), getName()); + aclFile.deleteOnExit(); + + if ("global".equals(vhost)) + { + setConfigurationProperty("security.aclv2", aclFile.getAbsolutePath()); + } + else + { + setConfigurationProperty("virtualhosts.virtualhost." + vhost + ".security.aclv2", aclFile.getAbsolutePath()); + } + + PrintWriter out = new PrintWriter(new FileWriter(aclFile)); + out.println(String.format("# %s", _testName)); + for (String line : rules) + { + out.println(line); + } + out.close(); + } + + /** + * Creates a connection to the broker, and sets a connection listener to prevent failover and an exception listener + * with a {@link CountDownLatch} to synchronise in the {@link #check403Exception(Throwable)} method and allow the + * {@link #tearDown()} method to complete properly. + */ + public Connection getConnection(String vhost, String username, String password) throws NamingException, JMSException, URLSyntaxException + { + AMQConnection connection = (AMQConnection) getConnection(createConnectionURL(vhost, username, password)); + + //Prevent Failover + connection.setConnectionListener(this); + + //QPID-2081: use a latch to sync on exception causing connection close, to work + //around the connection close race during tearDown() causing sporadic failures + _exceptionReceived = new CountDownLatch(1); + + connection.setExceptionListener(new ExceptionListener() + { + public void onException(JMSException e) + { + _exceptionReceived.countDown(); + } + }); + + return (Connection) connection; + } + + // Connection Listener Interface - Used here to block failover + + public void bytesSent(long count) + { + } + + public void bytesReceived(long count) + { + } + + public boolean preFailover(boolean redirect) + { + //Prevent failover. + return false; + } + + public boolean preResubscribe() + { + return false; + } + + public void failoverComplete() + { + } + + /** + * Convenience method to build an {@link AMQConnectionURL} with the right parameters. + */ + public AMQConnectionURL createConnectionURL(String vhost, String username, String password) throws URLSyntaxException + { + String url = "amqp://" + username + ":" + password + "@clientid/" + vhost + "?brokerlist='" + getBroker() + "?retries='0''"; + return new AMQConnectionURL(url); + } + + /** + * Convenience method to validate a JMS exception with a linked {@link AMQConstant#ACCESS_REFUSED} 403 error code exception. + */ + public void check403Exception(Throwable t) throws Exception + { + assertNotNull("There was no linked exception", t); + assertTrue("Wrong linked exception type", t instanceof AMQException); + assertEquals("Incorrect error code received", 403, ((AMQException) t).getErrorCode().getCode()); + + //use the latch to ensure the control thread waits long enough for the exception thread + //to have done enough to mark the connection closed before teardown commences + assertTrue("Timed out waiting for conneciton to report close", _exceptionReceived.await(2, TimeUnit.SECONDS)); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExhaustiveACLTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExhaustiveACLTest.java new file mode 100644 index 0000000000..1b2c98d30a --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExhaustiveACLTest.java @@ -0,0 +1,195 @@ +/* + * 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.qpid.server.security.acl; + +import java.util.Arrays; +import java.util.List; + +import javax.jms.Connection; +import javax.jms.Session; + +import org.apache.qpid.AMQException; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.protocol.AMQConstant; + +/** + * ACL version 2/3 file testing to verify that ACL entries control queue creation with specific properties. + * + * Tests have their own ACL files that setup specific permissions, and then try to create queues with every possible combination + * of properties to show that rule matching works correctly. For example, a rule that specified {@code autodelete="true"} for + * queues with {@link name="temp.true.*"} as well should not affect queues that have names that do not match, or queues that + * are not autodelete, or both. Also checks that ACL entries only affect the specified users and virtual hosts. + */ +public class ExhaustiveACLTest extends AbstractACLTestCase +{ + @Override + public String getConfig() + { + return "config-systests-aclv2.xml"; + } + + @Override + public List<String> getHostList() + { + return Arrays.asList("test", "test2"); + } + + /** + * Creates a queue. + * + * Connects to the broker as a particular user and create the named queue on a virtual host, with the provided + * parameters. Uses a new {@link Connection} and {@link Session} and closes them afterwards. + */ + private void createQueue(String vhost, String user, String name, boolean autoDelete, boolean durable) throws Exception + { + Connection conn = getConnection(vhost, user, "guest"); + Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); + conn.start(); + ((AMQSession<?, ?>) sess).createQueue(new AMQShortString(name), autoDelete, durable, false); + sess.commit(); + conn.close(); + } + + /** + * Calls {@link #createQueue(String, String, String, boolean, boolean)} with the provided parameters and checks that + * no exceptions were thrown. + */ + private void createQueueSuccess(String vhost, String user, String name, boolean autoDelete, boolean durable) throws Exception + { + try + { + createQueue(vhost, user, name, autoDelete, durable); + } + catch (AMQException e) + { + fail(String.format("Create queue should have worked for \"%s\" for user %s@%s, autoDelete=%s, durable=%s", + name, user, vhost, Boolean.toString(autoDelete), Boolean.toString(durable))); + } + } + + /** + * Calls {@link #createQueue(String, String, String, boolean, boolean)} with the provided parameters and checks that + * the exception thrown was an {@link AMQConstant#ACCESS_REFUSED} or 403 error code. + */ + private void createQueueFailure(String vhost, String user, String name, boolean autoDelete, boolean durable) throws Exception + { + try + { + createQueue(vhost, user, name, autoDelete, durable); + fail(String.format("Create queue should have failed for \"%s\" for user %s@%s, autoDelete=%s, durable=%s", + name, user, vhost, Boolean.toString(autoDelete), Boolean.toString(durable))); + } + catch (AMQException e) + { + assertEquals("Should be an ACCESS_REFUSED error", 403, e.getErrorCode().getCode()); + } + } + + public void setUpAuthoriseCreateQueueAutodelete() throws Exception + { + writeACLFile("test", + "acl allow client access virtualhost", + "acl allow server access virtualhost", + "acl allow client create queue name=\"temp.true.*\" autodelete=true", + "acl allow client create queue name=\"temp.false.*\" autodelete=false", + "acl deny client create queue", + "acl allow client delete queue", + "acl deny all create queue" + ); + } + + /** + * Test creation of temporary queues, with the autodelete property set to true. + */ + public void testAuthoriseCreateQueueAutodelete() throws Exception + { + createQueueSuccess("test", "client", "temp.true.00", true, false); + createQueueSuccess("test", "client", "temp.true.01", true, false); + createQueueSuccess("test", "client", "temp.true.02", true, true); + createQueueSuccess("test", "client", "temp.false.03", false, false); + createQueueSuccess("test", "client", "temp.false.04", false, false); + createQueueSuccess("test", "client", "temp.false.05", false, true); + createQueueFailure("test", "client", "temp.true.06", false, false); + createQueueFailure("test", "client", "temp.false.07", true, false); + createQueueFailure("test", "server", "temp.true.08", true, false); + createQueueFailure("test", "client", "temp.other.09", false, false); + createQueueSuccess("test2", "guest", "temp.true.01", false, false); + createQueueSuccess("test2", "guest", "temp.false.02", true, false); + createQueueSuccess("test2", "guest", "temp.true.03", true, false); + createQueueSuccess("test2", "guest", "temp.false.04", false, false); + createQueueSuccess("test2", "guest", "temp.other.05", false, false); + } + + public void setUpAuthoriseCreateQueue() throws Exception + { + writeACLFile("test", + "acl allow client access virtualhost", + "acl allow server access virtualhost", + "acl allow client create queue name=\"create.*\"" + ); + } + + /** + * Tests creation of named queues. + * + * If a named queue is specified + */ + public void testAuthoriseCreateQueue() throws Exception + { + createQueueSuccess("test", "client", "create.00", true, true); + createQueueSuccess("test", "client", "create.01", true, false); + createQueueSuccess("test", "client", "create.02", false, true); + createQueueSuccess("test", "client", "create.03", true, false); + createQueueFailure("test", "server", "create.04", true, true); + createQueueFailure("test", "server", "create.05", true, false); + createQueueFailure("test", "server", "create.06", false, true); + createQueueFailure("test", "server", "create.07", true, false); + createQueueSuccess("test2", "guest", "create.00", true, true); + createQueueSuccess("test2", "guest", "create.01", true, false); + createQueueSuccess("test2", "guest", "create.02", false, true); + createQueueSuccess("test2", "guest", "create.03", true, false); + } + + public void setUpAuthoriseCreateQueueBoth() throws Exception + { + writeACLFile("test", + "acl allow all access virtualhost", + "acl allow client create queue name=\"create.*\"", + "acl allow all create queue temporary=true" + ); + } + + /** + * Tests creation of named queues. + * + * If a named queue is specified + */ + public void testAuthoriseCreateQueueBoth() throws Exception + { + createQueueSuccess("test", "client", "create.00", true, false); + createQueueSuccess("test", "client", "create.01", false, false); + createQueueFailure("test", "server", "create.02", false, false); + createQueueFailure("test", "guest", "create.03", false, false); + createQueueSuccess("test", "client", "tmp.00", true, false); + createQueueSuccess("test", "server", "tmp.01", true, false); + createQueueSuccess("test", "guest", "tmp.02", true, false); + createQueueSuccess("test2", "guest", "create.02", false, false); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLFileTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLFileTest.java new file mode 100644 index 0000000000..1d08015669 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLFileTest.java @@ -0,0 +1,184 @@ +/* + * 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.qpid.server.security.acl; + +import java.util.Arrays; +import java.util.List; + +import javax.jms.Connection; +import javax.jms.Session; + +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.framing.AMQShortString; + +/** + * Tests that ACL version 2/3 files following the specification work correctly. + * + * ACL lines that are identical in meaning apart from differences allowed by the specification, such as whitespace or case + * of tokens are set up for numbered queues and the queues are then created to show that the meaning is correctly parsed by + * the plugin. + * + * TODO move this to the access-control plugin unit tests instead + */ +public class ExternalACLFileTest extends AbstractACLTestCase +{ + @Override + public String getConfig() + { + return "config-systests-aclv2.xml"; + } + + @Override + public List<String> getHostList() + { + return Arrays.asList("test"); + } + + private void createQueuePrefixList(String prefix, int count) + { + try + { + Connection conn = getConnection("test", "client", "guest"); + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + conn.start(); + + //Create n queues + for (int n = 0; n < count; n++) + { + AMQShortString queueName = new AMQShortString(String.format("%s.%03d", prefix, n)); + ((AMQSession<?, ?>) sess).createQueue(queueName, false, false, false); + } + + conn.close(); + } + catch (Exception e) + { + fail("Test failed due to:" + e.getMessage()); + } + } + + private void createQueueNameList(String...queueNames) + { + try + { + Connection conn = getConnection("test", "client", "guest"); + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + conn.start(); + + //Create all queues + for (String queueName : queueNames) + { + ((AMQSession<?, ?>) sess).createQueue(new AMQShortString(queueName), false, false, false); + } + + conn.close(); + } + catch (Exception e) + { + fail("Test failed due to:" + e.getMessage()); + } + } + + public void setUpCreateQueueMixedCase() throws Exception + { + writeACLFile( + "test", + "acl allow client create queue name=mixed.000", + "ACL ALLOW client CREATE QUEUE NAME=mixed.001", + "Acl Allow client Create Queue Name=mixed.002", + "aCL aLLOW client cREATE qUEUE nAME=mixed.003", + "aCl AlLoW client cReAtE qUeUe NaMe=mixed.004" + ); + } + + public void testCreateQueueMixedCase() + { + createQueuePrefixList("mixed", 5); + } + + public void setUpCreateQueueContinuation() throws Exception + { + writeACLFile( + "test", + "acl allow client create queue name=continuation.000", + "acl allow client create queue \\", + " name=continuation.001", + "acl allow client \\", + " create queue \\", + " name=continuation.002", + "acl allow \\", + " client \\", + " create queue \\", + " name=continuation.003", + "acl \\", + " allow \\", + " client \\", + " create queue \\", + " name=continuation.004" + ); + } + + public void testCreateQueueContinuation() + { + createQueuePrefixList("continuation", 5); + } + + public void setUpCreateQueueWhitespace() throws Exception + { + writeACLFile( + "test", + "acl allow client create queue name=whitespace.000", + "acl\tallow\tclient\tcreate\tqueue\tname=whitespace.001", + "acl allow client create queue name = whitespace.002", + "acl\tallow\tclient\tcreate\tqueue\tname\t=\twhitespace.003", + "acl allow\t\tclient\t \tcreate\t\t queue\t \t name \t =\t \twhitespace.004" + ); + } + + public void testCreateQueueWhitespace() + { + createQueuePrefixList("whitespace", 5); + } + + public void setUpCreateQueueQuoting() throws Exception + { + writeACLFile( + "test", + "acl allow client create queue name='quoting.ABC.000'", + "acl allow client create queue name='quoting.*.000'", + "acl allow client create queue name='quoting.#.000'", + "acl allow client create queue name='quoting. .000'", + "acl allow client create queue name='quoting.!@$%.000'" + ); + } + + public void testCreateQueueQuoting() + { + createQueueNameList( + "quoting.ABC.000", + "quoting.*.000", + "quoting.#.000", + "quoting. .000", + "quoting.!@$%.000" + ); + } +} + + + diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java new file mode 100644 index 0000000000..b823690002 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java @@ -0,0 +1,244 @@ +/* + * 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.qpid.server.security.acl; + +import java.util.Arrays; +import java.util.List; + +import org.apache.qpid.AMQConnectionClosedException; +import org.apache.qpid.AMQException; +import org.apache.qpid.AMQSecurityException; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.test.utils.JMXTestUtils; + +/** + * Tests that ACL entries that apply to AMQP objects also apply when those objects are accessed via JMX. + */ +public class ExternalACLJMXTest extends AbstractACLTestCase +{ + private JMXTestUtils _jmx; + + private static final String QUEUE_NAME = "kipper"; + private static final String EXCHANGE_NAME = "amq.kipper"; + + @Override + public String getConfig() + { + return "config-systests-aclv2.xml"; + } + + @Override + public List<String> getHostList() + { + return Arrays.asList("test"); + } + + @Override + public void setUp() throws Exception + { + _jmx = new JMXTestUtils(this, "admin", "admin"); + _jmx.setUp(); + super.setUp(); + _jmx.open(); + } + + @Override + public void tearDown() throws Exception + { + _jmx.close(); + super.tearDown(); + } + + // test-externalacljmx.txt + // create queue owner=client # success + public void testCreateClientQueueSuccess() throws Exception + { + //Queue Parameters + String queueOwner = "client"; + + _jmx.createQueue("test", QUEUE_NAME, queueOwner, true); + } + + // test-externalacljmx.txt + // create queue owner=client # failure + public void testCreateServerQueueFailure() throws Exception + { + //Queue Parameters + String queueOwner = "server"; + + try + { + _jmx.createQueue("test", QUEUE_NAME, queueOwner, true); + + fail("Queue create should fail"); + } + catch (Exception e) + { + assertNotNull("Cause is not set", e.getCause()); + assertEquals("Cause message incorrect", + "org.apache.qpid.AMQSecurityException: Permission denied: queue-name 'kipper' [error code 403: access refused]", e.getCause().getMessage()); + } + } + + // no create queue acl in file # failure + public void testCreateQueueFailure() throws Exception + { + //Queue Parameters + String queueOwner = "guest"; + + try + { + _jmx.createQueue("test", QUEUE_NAME, queueOwner, true); + + fail("Queue create should fail"); + } + catch (Exception e) + { + assertNotNull("Cause is not set", e.getCause()); + assertEquals("Cause message incorrect", + "org.apache.qpid.AMQSecurityException: Permission denied: queue-name 'kipper' [error code 403: access refused]", e.getCause().getMessage()); + } + } + + // test-externalacljmx.txt + // allow create exchange name=amq.kipper.success + public void testCreateExchangeSuccess() throws Exception + { + _jmx.createExchange("test", EXCHANGE_NAME + ".success", "direct", true); + } + + // test-externalacljmx.txt + // deny create exchange name=amq.kipper.failure + public void testCreateExchangeFailure() throws Exception + { + try + { + _jmx.createExchange("test", EXCHANGE_NAME + ".failure", "direct", true); + + fail("Exchange create should fail"); + } + catch (Exception e) + { + assertNotNull("Cause is not set", e.getCause()); + assertEquals("Cause message incorrect", + "org.apache.qpid.AMQSecurityException: Permission denied: exchange-name 'amq.kipper.failure' [error code 403: access refused]", e.getCause().getMessage()); + } + } + + // test-externalacljmx.txt + // allow create exchange name=amq.kipper.success + // allow delete exchange name=amq.kipper.success + public void testDeleteExchangeSuccess() throws Exception + { + _jmx.createExchange("test", EXCHANGE_NAME + ".success", "direct", true); + _jmx.unregisterExchange("test", EXCHANGE_NAME + ".success"); + } + + // test-externalacljmx-deleteexchangefailure.txt + // allow create exchange name=amq.kipper.delete + // deny delete exchange name=amq.kipper.delete + public void testDeleteExchangeFailure() throws Exception + { + _jmx.createExchange("test", EXCHANGE_NAME + ".delete", "direct", true); + try + { + _jmx.unregisterExchange("test", EXCHANGE_NAME + ".delete"); + + fail("Exchange delete should fail"); + } + catch (Exception e) + { + assertNotNull("Cause is not set", e.getCause()); + assertEquals("Cause message incorrect", + "org.apache.qpid.AMQSecurityException: Permission denied [error code 403: access refused]", e.getCause().getMessage()); + } + } + + /** + * admin user has JMX right but not AMQP + */ + public void setUpCreateQueueJMXRights() throws Exception + { + writeACLFile("test", + "ACL ALLOW admin EXECUTE METHOD component=\"VirtualHost.VirtualHostManager\" name=\"createNewQueue\"", + "ACL DENY admin CREATE QUEUE"); + } + + public void testCreateQueueJMXRights() throws Exception + { + try + { + _jmx.createQueue("test", QUEUE_NAME, "admin", true); + + fail("Queue create should fail"); + } + catch (Exception e) + { + assertNotNull("Cause is not set", e.getCause()); + assertEquals("Cause message incorrect", + "org.apache.qpid.AMQSecurityException: Permission denied: queue-name 'kipper' [error code 403: access refused]", e.getCause().getMessage()); + } + } + + /** + * admin user has AMQP right but not JMX + */ + public void setUpCreateQueueAMQPRights() throws Exception + { + writeACLFile("test", + "ACL DENY admin EXECUTE METHOD component=\"VirtualHost.VirtualHostManager\" name=\"createNewQueue\"", + "ACL ALLOW admin CREATE QUEUE"); + } + + public void testCreateQueueAMQPRights() throws Exception + { + try + { + _jmx.createQueue("test", QUEUE_NAME, "admin", true); + + fail("Queue create should fail"); + } + catch (Exception e) + { + assertEquals("Cause message incorrect", "Permission denied: Execute createNewQueue", e.getMessage()); + } + } + + /** + * admin has both JMX and AMQP rights + */ + public void setUpCreateQueueJMXAMQPRights() throws Exception + { + writeACLFile("test", + "ACL ALLOW admin EXECUTE METHOD component=\"VirtualHost.VirtualHostManager\" name=\"createNewQueue\"", + "ACL ALLOW admin CREATE QUEUE"); + } + + public void testCreateQueueJMXAMQPRights() throws Exception + { + try + { + _jmx.createQueue("test", QUEUE_NAME, "admin", true); + } + catch (Exception e) + { + fail("Queue create should succeed: " + e.getCause().getMessage()); + } + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java new file mode 100644 index 0000000000..4603cc1862 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.server.security.acl; + +import java.util.Arrays; +import java.util.List; + +public class ExternalACLTest extends SimpleACLTest +{ + @Override + public String getConfig() + { + return "config-systests-aclv2.xml"; + } + + @Override + public List<String> getHostList() + { + return Arrays.asList("test", "test2"); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalAdminACLTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalAdminACLTest.java new file mode 100644 index 0000000000..290cbfdc14 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalAdminACLTest.java @@ -0,0 +1,186 @@ +/* + * 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.qpid.server.security.acl; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +import org.apache.qpid.server.logging.management.LoggingManagementMBean; +import org.apache.qpid.test.utils.JMXTestUtils; + +/** + * Tests that ACLs can be applied to mangement operations that do not correspond to a specific AMQP object. + * + * Theses tests use the logging component, exposed as the {@link LoggingManagementMBean}, to get and set properties. + */ +public class ExternalAdminACLTest extends AbstractACLTestCase +{ + private static final String CATEGORY_PRIORITY = "LogManMBeanTest.category.priority"; + private static final String CATEGORY_LEVEL = "LogManMBeanTest.category.level"; + private static final String LOGGER_LEVEL = "LogManMBeanTest.logger.level"; + + private static final String NEWLINE = System.getProperty("line.separator"); + + private JMXTestUtils _jmx; + private File _testConfigFile; + + @Override + public String getConfig() + { + return "config-systests-aclv2.xml"; + } + + @Override + public List<String> getHostList() + { + return Arrays.asList("global"); + } + + @Override + public void setUp() throws Exception + { + _testConfigFile = createTempTestLog4JConfig(); + + _jmx = new JMXTestUtils(this, "admin", "admin"); + _jmx.setUp(); + super.setUp(); + _jmx.open(); + } + + @Override + public void tearDown() throws Exception + { + _jmx.close(); + super.tearDown(); + } + + private File createTempTestLog4JConfig() + { + File tmpFile = null; + try + { + tmpFile = File.createTempFile("LogManMBeanTestLog4jConfig", ".tmp"); + tmpFile.deleteOnExit(); + + FileWriter fstream = new FileWriter(tmpFile); + BufferedWriter writer = new BufferedWriter(fstream); + + writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+NEWLINE); + writer.write("<!DOCTYPE log4j:configuration SYSTEM \"log4j.dtd\">"+NEWLINE); + + writer.write("<log4j:configuration xmlns:log4j=\"http://jakarta.apache.org/log4j/\" debug=\"null\" " + + "threshold=\"null\">"+NEWLINE); + + writer.write(" <appender class=\"org.apache.log4j.ConsoleAppender\" name=\"STDOUT\">"+NEWLINE); + writer.write(" <layout class=\"org.apache.log4j.PatternLayout\">"+NEWLINE); + writer.write(" <param name=\"ConversionPattern\" value=\"%d %-5p [%t] %C{2} (%F:%L) - %m%n\"/>"+NEWLINE); + writer.write(" </layout>"+NEWLINE); + writer.write(" </appender>"+NEWLINE); + + //Example of a 'category' with a 'priority' + writer.write(" <category additivity=\"true\" name=\"" + CATEGORY_PRIORITY +"\">"+NEWLINE); + writer.write(" <priority value=\"info\"/>"+NEWLINE); + writer.write(" <appender-ref ref=\"STDOUT\"/>"+NEWLINE); + writer.write(" </category>"+NEWLINE); + + //Example of a 'category' with a 'level' + writer.write(" <category additivity=\"true\" name=\"" + CATEGORY_LEVEL +"\">"+NEWLINE); + writer.write(" <level value=\"warn\"/>"+NEWLINE); + writer.write(" <appender-ref ref=\"STDOUT\"/>"+NEWLINE); + writer.write(" </category>"+NEWLINE); + + //Example of a 'logger' with a 'level' + writer.write(" <logger additivity=\"true\" name=\"" + LOGGER_LEVEL + "\">"+NEWLINE); + writer.write(" <level value=\"error\"/>"+NEWLINE); + writer.write(" <appender-ref ref=\"STDOUT\"/>"+NEWLINE); + writer.write(" </logger>"+NEWLINE); + + //'root' logger + writer.write(" <root>"+NEWLINE); + writer.write(" <priority value=\"info\"/>"+NEWLINE); + writer.write(" <appender-ref ref=\"STDOUT\"/>"+NEWLINE); + writer.write(" </root>"+NEWLINE); + + writer.write("</log4j:configuration>"+NEWLINE); + + writer.flush(); + writer.close(); + } + catch (IOException e) + { + fail("Unable to create temporary test log4j configuration"); + } + + return tmpFile; + } + + public void testGetAllLoggerLevels() throws Exception + { + String[] levels = _jmx.getAvailableLoggerLevels(); + for (int i = 0; i < levels.length; i++) + { + System.out.println(levels[i]); + } + assertEquals("Got incorrect number of log levels", 9, levels.length); + } + + public void testGetAllLoggerLevelsDenied() throws Exception + { + try + { + _jmx.getAvailableLoggerLevels(); + fail("Got list of log levels"); + } + catch (Exception e) + { + // Exception throws + e.printStackTrace(); + assertEquals("Permission denied: Access getAvailableLoggerLevels", e.getMessage()); + } + } + + public void testChangeLoggerLevel() throws Exception + { + String oldLevel = _jmx.getRuntimeRootLoggerLevel(); + System.out.println("old level = " + oldLevel); + _jmx.setRuntimeRootLoggerLevel("DEBUG"); + String newLevel = _jmx.getRuntimeRootLoggerLevel(); + System.out.println("new level = " + newLevel); + assertEquals("Logging level was not changed", "DEBUG", newLevel); + } + + public void testChangeLoggerLevelDenied() throws Exception + { + try + { + _jmx.setRuntimeRootLoggerLevel("DEBUG"); + fail("Logging level was changed"); + } + catch (Exception e) + { + assertEquals("Permission denied: Update setRuntimeRootLoggerLevel", e.getMessage()); + } + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java index 08fc047533..fc9b07eadd 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java @@ -4,7 +4,7 @@ * 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 + * "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 @@ -15,28 +15,13 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. - * - * */ - package org.apache.qpid.server.security.acl; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.qpid.AMQException; -import org.apache.qpid.AMQConnectionFailureException; -import org.apache.qpid.client.AMQAuthenticationException; -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQConnectionURL; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.jms.ConnectionListener; -import org.apache.qpid.jms.ConnectionURL; -import org.apache.qpid.test.utils.QpidTestCase; -import org.apache.qpid.url.URLSyntaxException; +import java.io.IOException; import javax.jms.Connection; import javax.jms.DeliveryMode; -import javax.jms.ExceptionListener; import javax.jms.IllegalStateException; import javax.jms.JMSException; import javax.jms.Message; @@ -45,71 +30,45 @@ import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.Session; import javax.jms.TextMessage; +import javax.jms.Topic; +import javax.jms.TopicSubscriber; import javax.naming.NamingException; -import java.io.File; -import java.io.IOException; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -public class SimpleACLTest extends QpidTestCase implements ConnectionListener -{ - public void setUp() throws Exception - { - //Performing setUp here would result in a broker with the default ACL test config - - //Each test now calls the private setUpACLTest to allow them to make - //individual customisations to the base ACL settings - } - - public void tearDown() throws Exception - { - try - { - super.tearDown(); - } - catch (JMSException e) - { - //we're throwing this away as it can happen in this test as the state manager remembers exceptions - //that we provoked with authentication failures, where the test passes - we can ignore on con close - } - } - - private void setUpACLTest() throws Exception - { - final String QPID_HOME = System.getProperty("QPID_HOME"); - - if (QPID_HOME == null) - { - fail("QPID_HOME not set"); - } - - // Initialise ACLs. - _configFile = new File(QPID_HOME, "etc/config-systests-acl.xml"); - - super.setUp(); - } - - public String createConnectionString(String username, String password) - { - - return "amqp://" + username + ":" + password + "@clientid/test?brokerlist='" + getBroker() + "?retries='0''"; - } +import org.apache.qpid.AMQException; +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.url.URLSyntaxException; +/** + * Basic access control list tests. + * + * These tests require an access control security plugin to be configured in the broker, and carry out various broker + * operations that will succeed or fail depending on the user and virtual host. See the {@code config-systests-acl-setup.xml} + * configuration file for the {@link SimpleXML} version of the ACLs used by the Java broker only, or the various {@code .txt} + * files in the system tests directory for the external version 3 ACL files used by both the Java and C++ brokers. + * <p> + * This class can be extended and the {@link #getConfig()} method overridden to run the same tests with a different type + * of access control mechanism. Extension classes should differ only in the configuration file used, but extra tests can be + * added that are specific to a particular configuration. + * <p> + * The tests perform basic AMQP operations like creating queues or excahnges and publishing and consuming messages, using + * JMS to contact the broker. + * + * @see ExternalACLTest + */ +public class SimpleACLTest extends AbstractACLTestCase +{ public void testAccessAuthorized() throws AMQException, URLSyntaxException, Exception { - setUpACLTest(); - try { - Connection conn = getConnection("client", "guest"); - - Session sesh = conn.createSession(true, Session.SESSION_TRANSACTED); - + Connection conn = getConnection("test", "client", "guest"); + Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); conn.start(); //Do something to show connection is active. - sesh.rollback(); + sess.rollback(); conn.close(); } @@ -125,8 +84,6 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener //is unable to perform actions such as connecting (and by extension, creating a queue, and consuming //from a queue etc). In order to test the vhost-wide 'access' ACL right, the 'guest' user has been given //this right in the 'test2' vhost. - - setUpACLTest(); try { @@ -141,16 +98,16 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener conn.start(); //create Queues and consumers for each - Queue namedQueue = sesh.createQueue("vhostAccessCreatedQueue" + getTestQueueName()); - Queue tempQueue = sesh.createTemporaryQueue(); - MessageConsumer consumer = sesh.createConsumer(namedQueue); - MessageConsumer tempConsumer = sesh.createConsumer(tempQueue); + Queue namedQueue = sess.createQueue("vhostAccessCreatedQueue" + getTestQueueName()); + Queue tempQueue = sess.createTemporaryQueue(); + MessageConsumer consumer = sess.createConsumer(namedQueue); + MessageConsumer tempConsumer = sess.createConsumer(tempQueue); //send a message to each queue (also causing an exchange declare) - MessageProducer sender = ((AMQSession)sesh).createProducer(null); - ((org.apache.qpid.jms.MessageProducer) sender).send(namedQueue, sesh.createTextMessage("test"), + MessageProducer sender = ((AMQSession<?, ?>) sess).createProducer(null); + ((org.apache.qpid.jms.MessageProducer) sender).send(namedQueue, sess.createTextMessage("test"), DeliveryMode.NON_PERSISTENT, 0, 0L, false, false, true); - ((org.apache.qpid.jms.MessageProducer) sender).send(tempQueue, sesh.createTextMessage("test"), + ((org.apache.qpid.jms.MessageProducer) sender).send(tempQueue, sess.createTextMessage("test"), DeliveryMode.NON_PERSISTENT, 0, 0L, false, false, true); //consume the messages from the queues @@ -165,47 +122,93 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener } } + // XXX one public void testAccessNoRights() throws Exception { - setUpACLTest(); - try { - Connection conn = getConnection("guest", "guest"); - - //Attempt to do do things to test connection. - Session sesh = conn.createSession(true, Session.SESSION_TRANSACTED); + Connection conn = getConnection("test", "guest", "guest"); + Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); conn.start(); - sesh.rollback(); - + sess.rollback(); + fail("Connection was created."); } - catch (JMSException jmse) + catch (JMSException e) { - Throwable linkedException = jmse.getLinkedException(); - assertNotNull("Cause was null", linkedException); + // XXX JMSException -> linkedException -> cause = AMQException.403 + Exception linkedException = e.getLinkedException(); + assertNotNull("There was no linked exception", linkedException); + Throwable cause = linkedException.getCause(); + assertNotNull("Cause was null", cause); + assertTrue("Wrong linked exception type",cause instanceof AMQException); + assertEquals("Incorrect error code received", 403, ((AMQException) cause).getErrorCode().getCode()); + } + } + + public void testClientDeleteQueueSuccess() throws Exception + { + try + { + Connection conn = getConnection("test", "client", "guest"); + Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); + conn.start(); - assertEquals("Linked Exception was wrong type", AMQConnectionFailureException.class, linkedException.getClass()); + // create kipper + Topic kipper = sess.createTopic("kipper"); + TopicSubscriber subscriber = sess.createDurableSubscriber(kipper, "kipper"); - Throwable cause = linkedException.getCause(); - assertEquals("Cause was wrong type", AMQAuthenticationException.class, cause.getClass()); - assertEquals("Incorrect error code thrown", 403, ((AMQAuthenticationException) cause).getErrorCode().getCode()); + subscriber.close(); + sess.unsubscribe("kipper"); + + //Do something to show connection is active. + sess.rollback(); + conn.close(); + } + catch (Exception e) + { + fail("Test failed due to:" + e.getMessage()); + } + } + + // XXX two + public void testServerDeleteQueueFailure() throws Exception + { + try + { + Connection conn = getConnection("test", "server", "guest"); + Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); + conn.start(); + + // create kipper + Topic kipper = sess.createTopic("kipper"); + TopicSubscriber subscriber = sess.createDurableSubscriber(kipper, "kipper"); + + subscriber.close(); + sess.unsubscribe("kipper"); + + //Do something to show connection is active. + sess.rollback(); + conn.close(); + } + catch (JMSException e) + { + // XXX JMSException -> linedException = AMQException.403 + check403Exception(e.getLinkedException()); } } public void testClientConsumeFromTempQueueValid() throws AMQException, URLSyntaxException, Exception { - setUpACLTest(); - try { - Connection conn = getConnection("client", "guest"); + Connection conn = getConnection("test", "client", "guest"); - Session sesh = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); conn.start(); - sesh.createConsumer(sesh.createTemporaryQueue()); + sess.createConsumer(sess.createTemporaryQueue()); conn.close(); } @@ -217,64 +220,38 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener public void testClientConsumeFromNamedQueueInvalid() throws NamingException, Exception { - setUpACLTest(); - - //QPID-2081: use a latch to sync on exception causing connection close, to work - //around the connection close race during tearDown() causing sporadic failures - final CountDownLatch exceptionReceived = new CountDownLatch(1); - try { - Connection conn = getConnection("client", "guest"); - - //Prevent Failover - ((AMQConnection) conn).setConnectionListener(this); - - conn.setExceptionListener(new ExceptionListener() - { - public void onException(JMSException e) - { - exceptionReceived.countDown(); - } - }); + Connection conn = getConnection("test", "client", "guest"); - Session sesh = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); conn.start(); - sesh.createConsumer(sesh.createQueue("IllegalQueue")); + sess.createConsumer(sess.createQueue("IllegalQueue")); + + conn.close(); + fail("Test failed as consumer was created."); - //conn will be automatically closed } catch (JMSException e) { - Throwable cause = e.getLinkedException(); - - assertNotNull("There was no liked exception", cause); - assertEquals("Wrong linked exception type", AMQAuthenticationException.class, cause.getClass()); - assertEquals("Incorrect error code received", 403, ((AMQAuthenticationException) cause).getErrorCode().getCode()); - - //use the latch to ensure the control thread waits long enough for the exception thread - //to have done enough to mark the connection closed before teardown commences - assertTrue("Timed out waiting for conneciton to report close", - exceptionReceived.await(2, TimeUnit.SECONDS)); + check403Exception(e.getLinkedException()); } } public void testClientCreateTemporaryQueue() throws JMSException, URLSyntaxException, Exception { - setUpACLTest(); - try { - Connection conn = getConnection("client", "guest"); + Connection conn = getConnection("test", "client", "guest"); - Session sesh = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); conn.start(); //Create Temporary Queue - can't use the createTempQueue as QueueName is null. - ((AMQSession) sesh).createQueue(new AMQShortString("doesnt_matter_as_autodelete_means_tmp"), + ((AMQSession<?, ?>) sess).createQueue(new AMQShortString("doesnt_matter_as_autodelete_means_tmp"), true, false, false); conn.close(); @@ -287,66 +264,43 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener public void testClientCreateNamedQueue() throws NamingException, JMSException, AMQException, Exception { - setUpACLTest(); - - //QPID-2081: use a latch to sync on exception causing connection close, to work - //around the connection close race during tearDown() causing sporadic failures - final CountDownLatch exceptionReceived = new CountDownLatch(1); - try { - Connection conn = getConnection("client", "guest"); + Connection conn = getConnection("test", "client", "guest"); - Session sesh = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); conn.start(); - - conn.setExceptionListener(new ExceptionListener() - { - public void onException(JMSException e) - { - exceptionReceived.countDown(); - } - }); //Create a Named Queue - ((AMQSession) sesh).createQueue(new AMQShortString("IllegalQueue"), false, false, false); - + ((AMQSession<?, ?>) sess).createQueue(new AMQShortString("IllegalQueue"), false, false, false); + fail("Test failed as Queue creation succeded."); //conn will be automatically closed } - catch (AMQAuthenticationException amqe) + catch (AMQException e) { - amqe.printStackTrace(); - assertEquals("Incorrect error code thrown", 403, ((AMQAuthenticationException) amqe).getErrorCode().getCode()); - - //use the latch to ensure the control thread waits long enough for the exception thread - //to have done enough to mark the connection closed before teardown commences - assertTrue("Timed out waiting for conneciton to report close", - exceptionReceived.await(2, TimeUnit.SECONDS)); + // XXX AMQException.403 + check403Exception(e); } } public void testClientPublishUsingTransactionSuccess() throws AMQException, URLSyntaxException, Exception { - setUpACLTest(); - try { - Connection conn = getConnection("client", "guest"); - - ((AMQConnection) conn).setConnectionListener(this); + Connection conn = getConnection("test", "client", "guest"); - Session sesh = conn.createSession(true, Session.SESSION_TRANSACTED); + Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); conn.start(); - MessageProducer sender = sesh.createProducer(sesh.createQueue("example.RequestQueue")); + MessageProducer sender = sess.createProducer(sess.createQueue("example.RequestQueue")); - sender.send(sesh.createTextMessage("test")); + sender.send(sess.createTextMessage("test")); //Send the message using a transaction as this will allow us to retrieve any errors that occur on the broker. - sesh.commit(); + sess.commit(); conn.close(); } @@ -358,26 +312,22 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener public void testClientPublishValidQueueSuccess() throws AMQException, URLSyntaxException, Exception { - setUpACLTest(); - try { - Connection conn = getConnection("client", "guest"); + Connection conn = getConnection("test", "client", "guest"); - ((AMQConnection) conn).setConnectionListener(this); - - Session sesh = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); conn.start(); - MessageProducer sender = ((AMQSession) sesh).createProducer(null); + MessageProducer sender = ((AMQSession<?, ?>) sess).createProducer(null); - Queue queue = sesh.createQueue("example.RequestQueue"); + Queue queue = sess.createQueue("example.RequestQueue"); // Send a message that we will wait to be sent, this should give the broker time to process the msg // before we finish this test. Message is set !immed !mand as the queue is invalid so want to test ACLs not // queue existence. - ((org.apache.qpid.jms.MessageProducer) sender).send(queue, sesh.createTextMessage("test"), + ((org.apache.qpid.jms.MessageProducer) sender).send(queue, sess.createTextMessage("test"), DeliveryMode.NON_PERSISTENT, 0, 0L, false, false, true); conn.close(); @@ -390,31 +340,15 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener public void testClientPublishInvalidQueueSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, Exception { - setUpACLTest(); - - //QPID-2081: use a latch to sync on exception causing connection close, to work - //around the connection close race during tearDown() causing sporadic failures - final CountDownLatch exceptionReceived = new CountDownLatch(1); - try { - Connection conn = getConnection("client", "guest"); - - ((AMQConnection) conn).setConnectionListener(this); - - conn.setExceptionListener(new ExceptionListener() - { - public void onException(JMSException e) - { - exceptionReceived.countDown(); - } - }); + Connection conn = getConnection("test", "client", "guest"); Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); conn.start(); - MessageProducer sender = ((AMQSession) session).createProducer(null); + MessageProducer sender = ((AMQSession<?, ?>) session).createProducer(null); Queue queue = session.createQueue("Invalid"); @@ -435,53 +369,27 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener fail("Close is not expected to succeed."); } + catch (IllegalStateException e) + { + _logger.info("QPID-2345: Session became closed and we got that error rather than the authentication error."); + } catch (JMSException e) { - Throwable cause = e.getLinkedException(); - - if (cause == null) - { - e.printStackTrace(System.out); - if (e instanceof IllegalStateException) - { - System.out.println("QPID-2345: Session became closed and we got that error rather than the authentication error."); - } - else - { - fail("JMS Exception of did not have cause.:" + e.getMessage()); - } - } - else - { - if (!(cause instanceof AMQAuthenticationException)) - { - e.printStackTrace(); - } - assertEquals("Incorrect exception", AMQAuthenticationException.class, cause.getClass()); - assertEquals("Incorrect error code thrown", 403, ((AMQAuthenticationException) cause).getErrorCode().getCode()); - - //use the latch to ensure the control thread waits long enough for the exception thread - //to have done enough to mark the connection closed before teardown commences - assertTrue("Timed out waiting for connection to report close", - exceptionReceived.await(2, TimeUnit.SECONDS)); - } - + check403Exception(e.getLinkedException()); } } public void testServerConsumeFromNamedQueueValid() throws AMQException, URLSyntaxException, Exception { - setUpACLTest(); - try { - Connection conn = getConnection("server", "guest"); + Connection conn = getConnection("test", "server", "guest"); - Session sesh = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); conn.start(); - sesh.createConsumer(sesh.createQueue("example.RequestQueue")); + sess.createConsumer(sess.createQueue("example.RequestQueue")); conn.close(); } @@ -493,116 +401,58 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener public void testServerConsumeFromNamedQueueInvalid() throws AMQException, URLSyntaxException, NamingException, Exception { - setUpACLTest(); - - //QPID-2081: use a latch to sync on exception causing connection close, to work - //around the connection close race during tearDown() causing sporadic failures - final CountDownLatch exceptionReceived = new CountDownLatch(1); - try { - Connection conn = getConnection("client", "guest"); - - conn.setExceptionListener(new ExceptionListener() - { - public void onException(JMSException e) - { - exceptionReceived.countDown(); - } - }); + Connection conn = getConnection("test", "client", "guest"); - Session sesh = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); conn.start(); - sesh.createConsumer(sesh.createQueue("Invalid")); + sess.createConsumer(sess.createQueue("Invalid")); + + conn.close(); fail("Test failed as consumer was created."); - //conn will be automatically closed } catch (JMSException e) { - Throwable cause = e.getLinkedException(); - - assertNotNull("There was no liked exception", cause); - assertEquals("Wrong linked exception type", AMQAuthenticationException.class, cause.getClass()); - assertEquals("Incorrect error code received", 403, ((AMQAuthenticationException) cause).getErrorCode().getCode()); - - //use the latch to ensure the control thread waits long enough for the exception thread - //to have done enough to mark the connection closed before teardown commences - assertTrue("Timed out waiting for conneciton to report close", - exceptionReceived.await(2, TimeUnit.SECONDS)); + check403Exception(e.getLinkedException()); } } public void testServerConsumeFromTemporaryQueue() throws AMQException, URLSyntaxException, NamingException, Exception { - setUpACLTest(); - - //QPID-2081: use a latch to sync on exception causing connection close, to work - //around the connection close race during tearDown() causing sporadic failures - final CountDownLatch exceptionReceived = new CountDownLatch(1); - try { - Connection conn = getConnection("server", "guest"); - - conn.setExceptionListener(new ExceptionListener() - { - public void onException(JMSException e) - { - exceptionReceived.countDown(); - } - }); + Connection conn = getConnection("test", "server", "guest"); - Session sesh = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); conn.start(); - sesh.createConsumer(sesh.createTemporaryQueue()); + sess.createConsumer(sess.createTemporaryQueue()); + fail("Test failed as consumer was created."); - //conn will be automatically closed } catch (JMSException e) { - Throwable cause = e.getLinkedException(); - - assertNotNull("There was no liked exception", cause); - assertEquals("Wrong linked exception type", AMQAuthenticationException.class, cause.getClass()); - assertEquals("Incorrect error code received", 403, ((AMQAuthenticationException) cause).getErrorCode().getCode()); - - //use the latch to ensure the control thread waits long enough for the exception thread - //to have done enough to mark the connection closed before teardown commences - assertTrue("Timed out waiting for conneciton to report close", - exceptionReceived.await(2, TimeUnit.SECONDS)); + check403Exception(e.getLinkedException()); } } - @Override - public Connection getConnection(String username, String password) throws NamingException, JMSException - { - AMQConnection connection = (AMQConnection) super.getConnection(username, password); - - //Prevent Failover - connection.setConnectionListener(this); - - return (Connection) connection; - } - public void testServerCreateNamedQueueValid() throws JMSException, URLSyntaxException, Exception { - setUpACLTest(); - try { - Connection conn = getConnection("server", "guest"); + Connection conn = getConnection("test", "server", "guest"); - Session sesh = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); conn.start(); //Create Temporary Queue - ((AMQSession) sesh).createQueue(new AMQShortString("example.RequestQueue"), false, false, false); + ((AMQSession<?, ?>) sess).createQueue(new AMQShortString("example.RequestQueue"), false, false, false); conn.close(); } @@ -614,65 +464,30 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener public void testServerCreateNamedQueueInvalid() throws JMSException, URLSyntaxException, AMQException, NamingException, Exception { - setUpACLTest(); - - //QPID-2081: use a latch to sync on exception causing connection close, to work - //around the connection close race during tearDown() causing sporadic failures - final CountDownLatch exceptionReceived = new CountDownLatch(1); - try { - Connection conn = getConnection("server", "guest"); - - conn.setExceptionListener(new ExceptionListener() - { - public void onException(JMSException e) - { - exceptionReceived.countDown(); - } - }); + Connection conn = getConnection("test", "server", "guest"); - Session sesh = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); conn.start(); //Create a Named Queue - ((AMQSession) sesh).createQueue(new AMQShortString("IllegalQueue"), false, false, false); + ((AMQSession<?, ?>) sess).createQueue(new AMQShortString("IllegalQueue"), false, false, false); fail("Test failed as creation succeded."); - //conn will be automatically closed } - catch (AMQAuthenticationException amqe) + catch (Exception e) { - assertEquals("Incorrect error code thrown", 403, amqe.getErrorCode().getCode()); - - //use the latch to ensure the control thread waits long enough for the exception thread - //to have done enough to mark the connection closed before teardown commences - assertTrue("Timed out waiting for conneciton to report close", - exceptionReceived.await(2, TimeUnit.SECONDS)); + check403Exception(e); } } public void testServerCreateTemporaryQueueInvalid() throws NamingException, Exception { - setUpACLTest(); - - //QPID-2081: use a latch to sync on exception causing connection close, to work - //around the connection close race during tearDown() causing sporadic failures - final CountDownLatch exceptionReceived = new CountDownLatch(1); - - Connection conn = getConnection("server", "guest"); try { - - conn.setExceptionListener(new ExceptionListener() - { - public void onException(JMSException e) - { - exceptionReceived.countDown(); - } - }); - + Connection conn = getConnection("test", "server", "guest"); Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); conn.start(); @@ -683,69 +498,28 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener } catch (JMSException e) { - Throwable cause = e.getLinkedException(); - - assertNotNull("There was no liked exception", cause); - assertEquals("Wrong linked exception type", AMQAuthenticationException.class, cause.getClass()); - assertEquals("Incorrect error code received", 403, ((AMQAuthenticationException) cause).getErrorCode().getCode()); - - //use the latch to ensure the control thread waits long enough for the exception thread - //to have done enough to mark the connection closed before teardown commences - assertTrue("Timed out waiting for conneciton to report close", - exceptionReceived.await(2, TimeUnit.SECONDS)); - } - finally - { - try - { - conn.close(); - } - catch (Exception e) - { - // This normally fails because we are denied - } + check403Exception(e.getLinkedException()); } } - + public void testServerCreateAutoDeleteQueueInvalid() throws NamingException, JMSException, AMQException, Exception { - setUpACLTest(); - - //QPID-2081: use a latch to sync on exception causing connection close, to work - //around the connection close race during tearDown() causing sporadic failures - final CountDownLatch exceptionReceived = new CountDownLatch(1); - - Connection connection = null; try { - connection = getConnection("server", "guest"); - - connection.setExceptionListener(new ExceptionListener() - { - public void onException(JMSException e) - { - exceptionReceived.countDown(); - } - }); + Connection connection = getConnection("test", "server", "guest"); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); connection.start(); - ((AMQSession) session).createQueue(new AMQShortString("again_ensure_auto_delete_queue_for_temporary"), + ((AMQSession<?, ?>) session).createQueue(new AMQShortString("again_ensure_auto_delete_queue_for_temporary"), true, false, false); fail("Test failed as creation succeded."); - //connection will be automatically closed } - catch (AMQAuthenticationException amqe) + catch (Exception e) { - assertEquals("Incorrect error code thrown", 403, amqe.getErrorCode().getCode()); - - //use the latch to ensure the control thread waits long enough for the exception thread - //to have done enough to mark the connection closed before teardown commences - assertTrue("Timed out waiting for conneciton to report close", - exceptionReceived.await(2, TimeUnit.SECONDS)); + check403Exception(e); } } @@ -759,12 +533,8 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener */ public void testServerPublishUsingTransactionSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, Exception { - setUpACLTest(); - //Set up the Server - Connection serverConnection = getConnection("server", "guest"); - - ((AMQConnection) serverConnection).setConnectionListener(this); + Connection serverConnection = getConnection("test", "server", "guest"); Session serverSession = serverConnection.createSession(true, Session.SESSION_TRANSACTED); @@ -775,7 +545,7 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener serverConnection.start(); //Set up the consumer - Connection clientConnection = getConnection("client", "guest"); + Connection clientConnection = getConnection("test", "client", "guest"); //Send a test mesage Session clientSession = clientConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); @@ -841,23 +611,9 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener public void testServerPublishInvalidQueueSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, Exception { - setUpACLTest(); - - //QPID-2081: use a latch to sync on exception causing connection close, to work - //around the connection close race during tearDown() causing sporadic failures - final CountDownLatch exceptionReceived = new CountDownLatch(1); - try { - Connection conn = getConnection("server", "guest"); - - conn.setExceptionListener(new ExceptionListener() - { - public void onException(JMSException e) - { - exceptionReceived.countDown(); - } - }); + Connection conn = getConnection("test", "server", "guest"); ((AMQConnection) conn).setConnectionListener(this); @@ -865,7 +621,7 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener conn.start(); - MessageProducer sender = ((AMQSession) session).createProducer(null); + MessageProducer sender = ((AMQSession<?, ?>) session).createProducer(null); Queue queue = session.createQueue("Invalid"); @@ -886,63 +642,13 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener fail("Close is not expected to succeed."); } + catch (IllegalStateException e) + { + _logger.info("QPID-2345: Session became closed and we got that error rather than the authentication error."); + } catch (JMSException e) { - Throwable cause = e.getLinkedException(); - - if (cause == null) - { - e.printStackTrace(System.out); - if (e instanceof IllegalStateException) - { - System.out.println("QPID-2345: Session became closed and we got that error rather than the authentication error."); - } - else - { - fail("JMS Exception of did not have cause.:" + e.getMessage()); - } - } - else if (!(cause instanceof AMQAuthenticationException)) - { - cause.printStackTrace(System.out); - assertEquals("Incorrect exception", IllegalStateException.class, cause.getClass()); - System.out.println("QPID-2345: Session became closed and we got that error rather than the authentication error."); - } - else - { - assertEquals("Incorrect exception", AMQAuthenticationException.class, cause.getClass()); - assertEquals("Incorrect error code thrown", 403, ((AMQAuthenticationException) cause).getErrorCode().getCode()); - } - - //use the latch to ensure the control thread waits long enough for the exception thread - //to have done enough to mark the connection closed before teardown commences - assertTrue("Timed out waiting for conneciton to report close", - exceptionReceived.await(2, TimeUnit.SECONDS)); + check403Exception(e.getLinkedException()); } } - - // Connection Listener Interface - Used here to block failover - - public void bytesSent(long count) - { - } - - public void bytesReceived(long count) - { - } - - public boolean preFailover(boolean redirect) - { - //Prevent failover. - return false; - } - - public boolean preResubscribe() - { - return false; - } - - public void failoverComplete() - { - } } diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/firewall/FirewallConfigTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/firewall/FirewallConfigTest.java index ec9a297047..874a0c37e2 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/security/firewall/FirewallConfigTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/security/firewall/FirewallConfigTest.java @@ -1,6 +1,4 @@ -package org.apache.qpid.server.security.firewall; /* - * * 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 @@ -17,9 +15,8 @@ package org.apache.qpid.server.security.firewall; * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. - * */ - +package org.apache.qpid.server.security.firewall; import java.io.File; import java.io.FileWriter; @@ -85,7 +82,7 @@ public class FirewallConfigTest extends QpidTestCase } out.close(); } - + public void testVhostAllowBrokerDeny() throws Exception { if (_broker.equals(VM)) @@ -104,8 +101,7 @@ public class FirewallConfigTest extends QpidTestCase { //Try to get a connection to the 'test2' vhost //This is expected to fail as it is denied at the broker level - conn = getConnection(new AMQConnectionURL( - "amqp://username:password@clientid/test2?brokerlist='" + getBroker() + "'")); + conn = getConnection(new AMQConnectionURL("amqp://username:password@clientid/test2?brokerlist='" + getBroker() + "'")); fail("We expected the connection to fail"); } catch (JMSException e) @@ -235,7 +231,7 @@ public class FirewallConfigTest extends QpidTestCase } ); } - + public void testDenyOnReloadInVhost() throws Exception { testDeny(true, new Runnable() { @@ -259,7 +255,7 @@ public class FirewallConfigTest extends QpidTestCase { testFirewall(true, inVhost, restartOrReload); } - + /* * Check we can get a connection */ @@ -278,7 +274,7 @@ public class FirewallConfigTest extends QpidTestCase return conn != null; } - + private void testFirewall(boolean initial, boolean inVhost, Runnable restartOrReload) throws Exception { if (_broker.equals(VM)) diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java index b0484e20d7..a6b7e20a42 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java @@ -147,13 +147,13 @@ public class TopicSessionTest extends QpidTestCase public void testUnsubscriptionAfterConnectionClose() throws Exception { - AMQConnection con1 = (AMQConnection) getConnection("guest", "guest", "clientid"); + AMQConnection con1 = (AMQConnection) getClientConnection("guest", "guest", "clientid"); AMQTopic topic = new AMQTopic(con1, "MyTopic3"); TopicSession session1 = con1.createTopicSession(true, AMQSession.AUTO_ACKNOWLEDGE); TopicPublisher publisher = session1.createPublisher(topic); - AMQConnection con2 = (AMQConnection) getConnection("guest", "guest", "clientid"); + AMQConnection con2 = (AMQConnection) getClientConnection("guest", "guest", "clientid"); TopicSession session2 = con2.createTopicSession(true, AMQSession.AUTO_ACKNOWLEDGE); TopicSubscriber sub = session2.createDurableSubscriber(topic, "subscription0"); @@ -167,7 +167,7 @@ public class TopicSessionTest extends QpidTestCase con2.close(); publisher.publish(session1.createTextMessage("Hello2")); session1.commit(); - con2 = (AMQConnection) getConnection("guest", "guest", "clientid"); + con2 = (AMQConnection) getClientConnection("guest", "guest", "clientid"); session2 = con2.createTopicSession(true, AMQSession.NO_ACKNOWLEDGE); sub = session2.createDurableSubscriber(topic, "subscription0"); con2.start(); @@ -367,7 +367,7 @@ public class TopicSessionTest extends QpidTestCase m = (TextMessage) noLocal.receive(100); assertNull(m); - AMQConnection con2 = (AMQConnection) getConnection("guest", "guest", "foo"); + AMQConnection con2 = (AMQConnection) getClientConnection("guest", "guest", "foo"); TopicSession session2 = con2.createTopicSession(true, AMQSession.AUTO_ACKNOWLEDGE); TopicPublisher publisher2 = session2.createPublisher(topic); diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java b/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java index 9b786a5c62..18e373b8d7 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java @@ -20,23 +20,28 @@ */ package org.apache.qpid.test.utils; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.qpid.commands.objects.AllObjects; -import org.apache.qpid.management.common.JMXConnnectionFactory; -import org.apache.qpid.management.common.mbeans.ManagedBroker; -import org.apache.qpid.management.common.mbeans.ManagedExchange; +import java.io.IOException; +import java.util.Set; import javax.management.JMException; import javax.management.MBeanException; import javax.management.MBeanServerConnection; import javax.management.MBeanServerInvocationHandler; import javax.management.ObjectName; +import javax.management.MalformedObjectNameException; import javax.management.remote.JMXConnector; -import java.io.IOException; -import java.util.Set; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.qpid.commands.objects.AllObjects; +import org.apache.qpid.management.common.JMXConnnectionFactory; +import org.apache.qpid.management.common.mbeans.ManagedBroker; +import org.apache.qpid.management.common.mbeans.ManagedExchange; +import org.apache.qpid.management.common.mbeans.LoggingManagement; +import org.apache.qpid.management.common.mbeans.ConfigurationManagement; +import org.apache.qpid.management.common.mbeans.UserManagement; /** - * + * JMX access for tests. */ public class JMXTestUtils { @@ -61,9 +66,8 @@ public class JMXTestUtils public void open() throws Exception { - _jmxc = JMXConnnectionFactory.getJMXConnection( - 5000, "127.0.0.1", - _test.getManagementPort(_test.getPort()), USER, PASSWORD); + _jmxc = JMXConnnectionFactory.getJMXConnection(5000, "127.0.0.1", + _test.getManagementPort(_test.getPort()), USER, PASSWORD); _mbsc = _jmxc.getMBeanServerConnection(); } @@ -77,12 +81,11 @@ public class JMXTestUtils } /** - * Create a non-durable test exchange with the current test name + * Create a non-durable exchange with the requested name * - * @throws javax.management.JMException - is thrown if a exchange with this testName already exists - * @throws java.io.IOException - if there is a problem with the JMX Connection - * @throws javax.management.MBeanException - * - if there is another problem creating the exchange + * @throws JMException if a exchange with this name already exists + * @throws IOException if there is a problem with the JMX Connection + * @throws MBeanException if there is another problem creating the exchange */ public void createExchange(String virtualHostName, String name, String type, boolean durable) throws JMException, IOException, MBeanException @@ -96,24 +99,134 @@ public class JMXTestUtils * Create a non-durable queue (with no owner) that is named after the * creating test. * - * @throws JMException - is thrown if a queue with this testName already exists - * @throws IOException - if there is a problem with the JMX Connection + * @throws JMException if a queue with this name already exists + * @throws IOException if there is a problem with the JMX Connection + * @throws MBeanException if there is another problem creating the exchange */ public void createQueue(String virtualHostName, String name, String owner, boolean durable) - throws JMException, IOException + throws JMException, MBeanException, IOException { ManagedBroker managedBroker = getManagedBroker(virtualHostName); managedBroker.createNewQueue(name, owner, durable); } + + /** + * Unregisters all the channels, queuebindings etc and unregisters + * this exchange from managed objects. + * + * @throws JMException if an exchange with this name does not exist + * @throws IOException if there is a problem with the JMX Connection + * @throws MBeanException if there is another problem creating the exchange + */ + public void unregisterExchange(String virtualHostName, String exchange) + throws IOException, JMException, MBeanException + { + ManagedBroker managedBroker = getManagedBroker(virtualHostName); + + managedBroker.unregisterExchange(exchange); + } + + /** + * Unregisters the Queue bindings, removes the subscriptions and unregisters + * from the managed objects. + * + * @throws JMException if a queue with this name does not exist + * @throws IOException if there is a problem with the JMX Connection + * @throws MBeanException if there is another problem creating the exchange + */ + public void deleteQueue(String virtualHostName, String queueName) + throws IOException, JMException, MBeanException + { + ManagedBroker managedBroker = getManagedBroker(virtualHostName); + managedBroker.deleteQueue(queueName); + } + + /** + * Sets the logging level. + * + * @throws JMException + * @throws IOException if there is a problem with the JMX Connection + * @throws MBeanException + */ + public void setRuntimeLoggerLevel(String logger, String level) + throws IOException, JMException, MBeanException + { + LoggingManagement loggingManagement = getLoggingManagement(); + + loggingManagement.setRuntimeLoggerLevel(logger, level); + } + + /** + * Reload logging config file. + * + * @throws JMException + * @throws IOException if there is a problem with the JMX Connection + * @throws MBeanException + */ + public void reloadConfigFile() + throws IOException, JMException, MBeanException + { + LoggingManagement loggingManagement = getLoggingManagement(); + + loggingManagement.reloadConfigFile(); + } + + /** + * Get list of available logger levels. + * + * @throws JMException + * @throws IOException if there is a problem with the JMX Connection + * @throws MBeanException + */ + public String[] getAvailableLoggerLevels() + throws IOException, JMException, MBeanException + { + LoggingManagement loggingManagement = getLoggingManagement(); + + return loggingManagement.getAvailableLoggerLevels(); + } + + /** + * Set root logger level. + * + * @throws JMException + * @throws IOException if there is a problem with the JMX Connection + * @throws MBeanException + */ + public void setRuntimeRootLoggerLevel(String level) + throws IOException, JMException, MBeanException + { + LoggingManagement loggingManagement = getLoggingManagement(); + + loggingManagement.setRuntimeRootLoggerLevel(level); + } + + /** + * Get root logger level. + * + * @throws JMException + * @throws IOException if there is a problem with the JMX Connection + * @throws MBeanException + */ + public String getRuntimeRootLoggerLevel() + throws IOException, JMException, MBeanException + { + LoggingManagement loggingManagement = getLoggingManagement(); + + return loggingManagement.getRuntimeRootLoggerLevel(); + } + /** - * Retrive the ObjectName for the test Virtualhost. + * Retrive the ObjectName for a Virtualhost. * - * This is then use to create aproxy to the ManagedBroker MBean. + * This is then used to create a proxy to the ManagedBroker MBean. * - * @return the ObjectName for the 'test' VirtualHost. + * @param virtualHostName the VirtualHost to retrieve + * @return the ObjectName for the VirtualHost */ + @SuppressWarnings("static-access") public ObjectName getVirtualHostManagerObjectName(String vhostName) { // Get the name of the test manager @@ -126,18 +239,21 @@ public class JMXTestUtils _test.assertEquals("Incorrect number test vhosts returned", 1, objectNames.size()); // We have verified we have only one value in objectNames so return it - return objectNames.iterator().next(); + ObjectName objectName = objectNames.iterator().next(); + _test.getLogger().info("Loading: " + objectName); + return objectName; } /** - * Retrive the ObjectName for the given Exchange on the test Virtualhost. + * Retrive the ObjectName for the given Queue on a Virtualhost. * - * This is then use to create aproxy to the ManagedExchange MBean. + * This is then used to create a proxy to the ManagedQueue MBean. * - * @param queue The exchange to retireve e.g. 'direct' - * - * @return the ObjectName for the given exchange on the test VirtualHost. + * @param virtualHostName the VirtualHost the Queue is on + * @param queue The Queue to retireve + * @return the ObjectName for the given queue on the VirtualHost */ + @SuppressWarnings("static-access") public ObjectName getQueueObjectName(String virtualHostName, String queue) { // Get the name of the test manager @@ -151,19 +267,21 @@ public class JMXTestUtils "' returned", 1, objectNames.size()); // We have verified we have only one value in objectNames so return it - return objectNames.iterator().next(); + ObjectName objectName = objectNames.iterator().next(); + _test.getLogger().info("Loading: " + objectName); + return objectName; } /** - * Retrive the ObjectName for the given Exchange on the test Virtualhost. + * Retrive the ObjectName for the given Exchange on a VirtualHost. * - * This is then use to create aproxy to the ManagedExchange MBean. + * This is then used to create a proxy to the ManagedExchange MBean. * - * @param virtualHostName - * @param exchange The exchange to retireve e.g. 'direct' - * - * @return the ObjectName for the given exchange on the test VirtualHost. + * @param virtualHostName the VirtualHost the Exchange is on + * @param exchange the Exchange to retireve e.g. 'direct' + * @return the ObjectName for the given Exchange on the VirtualHost */ + @SuppressWarnings("static-access") public ObjectName getExchangeObjectName(String virtualHostName, String exchange) { // Get the name of the test manager @@ -173,13 +291,15 @@ public class JMXTestUtils Set<ObjectName> objectNames = allObject.returnObjects(); _test.assertNotNull("Null ObjectName Set returned", objectNames); - _test.assertEquals("Incorrect number of exchange with name '" + exchange + - "' returned", 1, objectNames.size()); + _test.assertEquals("Incorrect number of exchange with name '" + exchange + "' returned", 1, objectNames.size()); // We have verified we have only one value in objectNames so return it - return objectNames.iterator().next(); + ObjectName objectName = objectNames.iterator().next(); + _test.getLogger().info("Loading: " + objectName); + return objectName; } + @SuppressWarnings("static-access") public <T> T getManagedObject(Class<T> managedClass, String queryString) { AllObjects allObject = new AllObjects(_mbsc); @@ -191,25 +311,41 @@ public class JMXTestUtils _test.assertEquals("More than one " + managedClass + " returned", 1, objectNames.size()); ObjectName objectName = objectNames.iterator().next(); - + _test.getLogger().info("Loading: " + objectName); return getManagedObject(managedClass, objectName); } public <T> T getManagedObject(Class<T> managedClass, ObjectName objectName) { - return MBeanServerInvocationHandler. - newProxyInstance(_mbsc, objectName, managedClass, false); + return MBeanServerInvocationHandler.newProxyInstance(_mbsc, objectName, managedClass, false); } public ManagedBroker getManagedBroker(String virtualHost) { - return getManagedObject(ManagedBroker.class, getVirtualHostManagerObjectName(virtualHost).toString()); + return getManagedObject(ManagedBroker.class, getVirtualHostManagerObjectName(virtualHost)); } - + public ManagedExchange getManagedExchange(String exchangeName) { - return MBeanServerInvocationHandler. - newProxyInstance(_mbsc, getExchangeObjectName("test", exchangeName), - ManagedExchange.class, false); + ObjectName objectName = getExchangeObjectName("test", exchangeName); + return MBeanServerInvocationHandler.newProxyInstance(_mbsc, objectName, ManagedExchange.class, false); + } + + public LoggingManagement getLoggingManagement() throws MalformedObjectNameException + { + ObjectName objectName = new ObjectName("org.apache.qpid:type=LoggingManagement,name=LoggingManagement"); + return getManagedObject(LoggingManagement.class, objectName); + } + + public ConfigurationManagement getConfigurationManagement() throws MalformedObjectNameException + { + ObjectName objectName = new ObjectName("org.apache.qpid:type=ConfigurationManagement,name=ConfigurationManagement"); + return getManagedObject(ConfigurationManagement.class, objectName); + } + + public UserManagement getUserManagement() throws MalformedObjectNameException + { + ObjectName objectName = new ObjectName("org.apache.qpid:type=UserManagement,name=UserManagement"); + return getManagedObject(UserManagement.class, objectName); } } diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java b/java/systests/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java index 5b7670eaa3..57a7659782 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java @@ -56,6 +56,7 @@ import junit.framework.TestResult; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.XMLConfiguration; import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; import org.apache.log4j.Level; import org.apache.qpid.AMQException; import org.apache.qpid.client.AMQConnection; @@ -71,26 +72,23 @@ import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry; import org.apache.qpid.server.store.DerbyMessageStore; import org.apache.qpid.url.URLSyntaxException; import org.apache.qpid.util.LogMonitor; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** - * - * + * Qpid base class for system testing test cases. */ public class QpidTestCase extends TestCase { protected final String QpidHome = System.getProperty("QPID_HOME"); protected File _configFile = new File(System.getProperty("broker.config")); - protected static final Logger _logger = LoggerFactory.getLogger(QpidTestCase.class); + protected static final Logger _logger = Logger.getLogger(QpidTestCase.class); protected static final int LOGMONITOR_TIMEOUT = 5000; protected long RECEIVE_TIMEOUT = 1000l; private Map<String, String> _propertiesSetForTestOnly = new HashMap<String, String>(); private Map<String, String> _propertiesSetForBroker = new HashMap<String, String>(); - private Map<org.apache.log4j.Logger, Level> _loggerLevelSetForTest = new HashMap<org.apache.log4j.Logger, Level>(); + private Map<Logger, Level> _loggerLevelSetForTest = new HashMap<Logger, Level>(); private XMLConfiguration _testConfiguration = new XMLConfiguration(); private XMLConfiguration _testVirtualhosts = new XMLConfiguration(); @@ -98,7 +96,6 @@ public class QpidTestCase extends TestCase protected static final String INDEX = "index"; protected static final String CONTENT = "content"; - /** * Some tests are excluded when the property test.excludes is set to true. * An exclusion list is either a file (prop test.excludesfile) which contains one test name @@ -198,10 +195,10 @@ public class QpidTestCase extends TestCase private String _brokerClean = System.getProperty(BROKER_CLEAN, null); private Boolean _brokerCleanBetweenTests = Boolean.getBoolean(BROKER_CLEAN_BETWEEN_TESTS); private String _brokerVersion = System.getProperty(BROKER_VERSION, VERSION_08); - private String _output = System.getProperty(TEST_OUTPUT); + protected String _output = System.getProperty(TEST_OUTPUT); protected Boolean _brokerPersistent = Boolean.getBoolean(BROKER_PERSITENT); - private static String _brokerLogPrefix = System.getProperty(BROKER_LOG_PREFIX,"BROKER: "); + protected static String _brokerLogPrefix = System.getProperty(BROKER_LOG_PREFIX,"BROKER: "); protected static boolean _interleaveBrokerLog = Boolean.getBoolean(BROKER_LOG_INTERLEAVE); protected File _outputFile; @@ -210,10 +207,10 @@ public class QpidTestCase extends TestCase protected Map<Integer, Process> _brokers = new HashMap<Integer, Process>(); - private InitialContext _initialContext; + protected InitialContext _initialContext; protected AMQConnectionFactory _connectionFactory; - private String _testName; + protected String _testName; // the connections created for a given test protected List<Connection> _connections = new ArrayList<Connection>(); @@ -248,6 +245,11 @@ public class QpidTestCase extends TestCase { this("QpidTestCase"); } + + public Logger getLogger() + { + return QpidTestCase._logger; + } public void runBare() throws Throwable { @@ -287,6 +289,11 @@ public class QpidTestCase extends TestCase { super.runBare(); } + catch (Exception e) + { + _logger.error("exception", e); + throw e; + } finally { try @@ -935,7 +942,7 @@ public class QpidTestCase extends TestCase * @param logger the logger to change * @param level the level to set */ - protected void setLoggerLevel(org.apache.log4j.Logger logger, Level level) + protected void setLoggerLevel(Logger logger, Level level) { assertNotNull("Cannot set level of null logger", logger); assertNotNull("Cannot set Logger("+logger.getName()+") to null level.",level); @@ -954,7 +961,7 @@ public class QpidTestCase extends TestCase */ protected void revertLoggingLevels() { - for (org.apache.log4j.Logger logger : _loggerLevelSetForTest.keySet()) + for (Logger logger : _loggerLevelSetForTest.keySet()) { logger.setLevel(_loggerLevelSetForTest.get(logger)); } @@ -1079,7 +1086,8 @@ public class QpidTestCase extends TestCase public Connection getConnection(ConnectionURL url) throws JMSException { - Connection connection = new AMQConnectionFactory(url).createConnection("guest", "guest"); + _logger.info(url.getURL()); + Connection connection = new AMQConnectionFactory(url).createConnection(url.getUsername(), url.getPassword()); _connections.add(connection); @@ -1098,14 +1106,14 @@ public class QpidTestCase extends TestCase */ public Connection getConnection(String username, String password) throws JMSException, NamingException { - _logger.info("get Connection"); + _logger.info("get connection"); Connection con = getConnectionFactory().createConnection(username, password); //add the connection in the lis of connections _connections.add(con); return con; } - public Connection getConnection(String username, String password, String id) throws JMSException, URLSyntaxException, AMQException, NamingException + public Connection getClientConnection(String username, String password, String id) throws JMSException, URLSyntaxException, AMQException, NamingException { _logger.info("get Connection"); Connection con; @@ -1382,10 +1390,19 @@ public class QpidTestCase extends TestCase /* * Sigh, this is going to get messy. grep for BRKR and the port number */ - - Process p = Runtime.getRuntime().exec("/usr/bin/pgrep -f " + getPort(port)); + String osName = System.getProperty("os.name"); + boolean osx = osName.equals("Mac OS X"); + + String cmd = osx ? "/usr/sbin/lsof -i TCP:%d -Fp" : "/usr/bin/pgrep -f %d"; + Process p = Runtime.getRuntime().exec(String.format(cmd, getPort(port))); BufferedReader reader = new BufferedReader (new InputStreamReader(p.getInputStream())); - String cmd = "/bin/kill -SIGHUP " + reader.readLine(); + String pid = reader.readLine(); + while (reader.ready()) + { + pid = reader.readLine(); + } + + cmd = "/bin/kill -SIGHUP " + (osx ? pid.substring(1) : pid); p = Runtime.getRuntime().exec(cmd); LogMonitor _monitor = new LogMonitor(_outputFile); |